{
  "openapi": "3.1.1",
  "info": {
    "title": "Car Image API",
    "version": "2.0.0",
    "summary": "The AI-native car image API: studio-quality, transparent-background renders of any vehicle in the open @meterapp/vehicle-db catalog.",
    "description": "Renders any of 1,145 makes and 14,841 models (1990–2026) in 6 camera views and 15 preset colors as PNG/WebP/JPG up to 1024px. Every delivered image costs exactly 1 credit whether it was cached or freshly generated; $1 = 1,000 credits, 100 free credits per account, no subscription. Authenticate server-side requests with `Authorization: Bearer cimg_…`. For browsers, mint signed delivery URLs (billed once at creation, free to load until expiry) instead of shipping a key. All JSON failures are RFC 9457 problem documents; keep `request_id` for support.",
    "contact": { "name": "Meter", "url": "https://car-imgs.vercel.app", "email": "hello@meterapp.co" },
    "license": { "name": "Proprietary", "identifier": "LicenseRef-Proprietary" },
    "x-pricing": {
      "currency": "USD",
      "credits_per_dollar": 1000,
      "free_credits": 100,
      "subscription": false,
      "charges": {
        "GET /api/v1/images/car -> 200 image bytes": 1,
        "GET /api/v1/images/car -> 200 JSON url (response=url or Accept: application/json)": 1,
        "GET /api/v1/images/car -> 304 Not Modified": 0,
        "POST /api/v1/image-urls": "1 per URL, charged once at creation",
        "GET /api/v1/delivery/{token} (any number of loads until expiry)": 0,
        "GET /images/car.png with an API key": 1,
        "GET /images/car.png signed (exp+sig), mode=cached, playground, examples": 0,
        "everything else (options, vehicles, resolve, account, feedback, events)": 0
      },
      "packs": [
        { "credits": 5000, "usd": 5 },
        { "credits": 10000, "usd": 10 },
        { "credits": 25000, "usd": 25 },
        { "credits": 100000, "usd": 100 }
      ],
      "refunds": "A render that fails after the charge is refunded automatically; a failed first load of a signed URL refunds that URL's credit."
    },
    "x-agent-notes": [
      "Never place an API key in a URL, prompt, tool result or log. Browsers get signed delivery URLs, not keys.",
      "Do not buy credits autonomously on 402; surface the balance and ask the human.",
      "Honor Retry-After on 429 and 503 with exponential backoff and jitter. Never retry 400/402/404 unchanged.",
      "Send If-None-Match with the last ETag: a 304 is free and rate-limited only.",
      "Use POST /api/v1/images/resolve to turn a free-text description into exact parameters before spending a credit.",
      "Images are generated product renders, not OEM photography; say so when accuracy matters."
    ]
  },
  "servers": [{ "url": "https://car-imgs.vercel.app" }],
  "security": [{ "bearerAuth": [] }, { "apiKeyHeader": [] }],
  "tags": [
    { "name": "Images", "description": "Billed image delivery and free discovery helpers." },
    { "name": "Signed URLs", "description": "Browser-safe delivery URLs: billed once at creation, free to load until expiry." },
    { "name": "Catalog", "description": "Public vehicle catalog (no key required)." },
    { "name": "Account", "description": "Balance, usage and feedback." },
    { "name": "Billing", "description": "Hosted Stripe pages. Nothing is charged by the API itself." },
    { "name": "Auth", "description": "RFC 8628-style device login used by `npx @meterapp/car-image login`." },
    { "name": "Agents", "description": "Endpoints built for AI agents: MCP and telemetry." },
    { "name": "Legacy", "description": "/images/car.png embed endpoint with partner signatures." }
  ],
  "paths": {
    "/api/v1/images/car": {
      "get": {
        "tags": ["Images"],
        "operationId": "getCarImage",
        "summary": "Get a vehicle image (1 credit)",
        "description": "Returns image bytes. Cached and freshly generated images cost the same 1 credit; a failed render is refunded. Send `If-None-Match` with a previous `ETag` to get a free `304`. With `?response=url` (or `Accept: application/json` and no image type) the credit is charged now and a signed delivery URL is returned instead; the image is rendered on its first load.",
        "parameters": [
          { "$ref": "#/components/parameters/Make" },
          { "$ref": "#/components/parameters/Model" },
          { "$ref": "#/components/parameters/Year" },
          { "$ref": "#/components/parameters/View" },
          { "$ref": "#/components/parameters/Color" },
          { "$ref": "#/components/parameters/Width" },
          { "$ref": "#/components/parameters/Height" },
          { "$ref": "#/components/parameters/Size" },
          { "$ref": "#/components/parameters/Format" },
          {
            "name": "response",
            "in": "query",
            "description": "`url` returns a signed delivery URL as JSON instead of bytes (same 1-credit charge).",
            "schema": { "type": "string", "enum": ["image", "url"], "default": "image" }
          },
          { "$ref": "#/components/parameters/IfNoneMatch" },
          { "$ref": "#/components/parameters/XRequestIdHeader" }
        ],
        "responses": {
          "200": {
            "description": "Image bytes (or, for `response=url`, a JSON delivery URL). Check `X-Credits-Charged`, `X-Credits-Remaining` and `X-Image-Source`.",
            "headers": {
              "Content-Location": { "description": "Canonical URL of this image, in `make` spelling.", "schema": { "type": "string" } },
              "ETag": { "$ref": "#/components/headers/ETag" },
              "Cache-Control": { "description": "`private, max-age=86400`", "schema": { "type": "string" } },
              "X-Credits-Charged": { "$ref": "#/components/headers/XCreditsCharged" },
              "X-Credits-Remaining": { "$ref": "#/components/headers/XCreditsRemaining" },
              "X-Image-Source": { "$ref": "#/components/headers/XImageSource" },
              "X-Image-Width": { "$ref": "#/components/headers/XImageWidth" },
              "X-Image-Height": { "$ref": "#/components/headers/XImageHeight" },
              "X-Request-Id": { "$ref": "#/components/headers/XRequestId" },
              "RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" },
              "RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" },
              "RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }
            },
            "content": {
              "image/png": { "schema": { "type": "string", "contentEncoding": "binary" } },
              "image/webp": { "schema": { "type": "string", "contentEncoding": "binary" } },
              "image/jpeg": { "schema": { "type": "string", "contentEncoding": "binary" } },
              "application/json": { "schema": { "$ref": "#/components/schemas/ImageUrlResponse" } }
            }
          },
          "304": { "$ref": "#/components/responses/NotModified" },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "402": { "$ref": "#/components/responses/PaymentRequired" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/VehicleNotFound" },
          "429": { "$ref": "#/components/responses/RateLimited" },
          "502": { "$ref": "#/components/responses/RenderFailed" },
          "503": { "$ref": "#/components/responses/Unavailable" }
        },
        "x-agent-notes": "Costs 1 credit per 200. Prefer `size` presets (thumb 256, small 512, medium 768, large 1024). Do not buy credits on 402 without asking the human."
      }
    },
    "/api/v1/image-urls": {
      "post": {
        "tags": ["Signed URLs"],
        "operationId": "createImageUrls",
        "summary": "Create 1–50 signed delivery URLs (1 credit each, charged now)",
        "description": "Mints browser-safe URLs that contain no key or account identifier. Each URL costs 1 credit at creation and can then be loaded for free until `expires_at` (`max_uses` 0 = unlimited; a positive number caps redemptions and disables shared caching). All images are validated before anything is charged; the whole batch is one debit.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  { "$ref": "#/components/schemas/ImageRequest" },
                  { "$ref": "#/components/schemas/BatchImageUrlRequest" }
                ]
              },
              "examples": {
                "single": { "value": { "make": "Porsche", "model": "911", "year": 2024, "view": "side", "color": "red", "size": "medium" } },
                "batch": {
                  "value": {
                    "images": [
                      { "make": "BMW", "model": "M3", "year": 2022 },
                      { "make": "Tesla", "model": "Model 3", "year": 2023, "view": "rear", "format": "webp" }
                    ],
                    "ttl_seconds": 86400,
                    "max_uses": 0
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "URLs created and billed.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ImageUrlsResponse" } } }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "402": { "$ref": "#/components/responses/PaymentRequired" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/VehicleNotFound" },
          "413": { "$ref": "#/components/responses/PayloadTooLarge" },
          "429": { "$ref": "#/components/responses/RateLimited" },
          "500": { "$ref": "#/components/responses/ServerError" }
        },
        "x-agent-notes": "Body limit 64 KiB. On 400/404 the problem includes `index` of the failing batch item. Nothing is charged when any item is invalid."
      }
    },
    "/api/v1/delivery/{token}": {
      "parameters": [
        {
          "name": "token",
          "in": "path",
          "required": true,
          "description": "Opaque token from createImageUrls or getCarImage(response=url).",
          "schema": { "type": "string" }
        }
      ],
      "get": {
        "tags": ["Signed URLs"],
        "operationId": "redeemDeliveryUrl",
        "summary": "Load a signed delivery URL (free)",
        "description": "Public. Renders (and caches) the image on first load; later loads are served from cache. Unlimited-use URLs are publicly cacheable until they expire; use-capped URLs are `private, no-store` and return 410 once exhausted. Revoking the API key that minted a URL invalidates it. If the first render fails, the URL's credit is refunded.",
        "security": [],
        "parameters": [{ "$ref": "#/components/parameters/IfNoneMatch" }],
        "responses": {
          "200": {
            "description": "Image bytes.",
            "headers": {
              "ETag": { "$ref": "#/components/headers/ETag" },
              "Cache-Control": { "description": "`public, max-age=<remaining>, s-maxage=<remaining>, stale-while-revalidate=60` for unlimited-use URLs; `private, no-store` when max_uses > 0.", "schema": { "type": "string" } },
              "X-Image-Source": { "$ref": "#/components/headers/XImageSource" },
              "X-Image-Width": { "$ref": "#/components/headers/XImageWidth" },
              "X-Image-Height": { "$ref": "#/components/headers/XImageHeight" },
              "X-Request-Id": { "$ref": "#/components/headers/XRequestId" }
            },
            "content": {
              "image/png": { "schema": { "type": "string", "contentEncoding": "binary" } },
              "image/webp": { "schema": { "type": "string", "contentEncoding": "binary" } },
              "image/jpeg": { "schema": { "type": "string", "contentEncoding": "binary" } }
            }
          },
          "304": { "$ref": "#/components/responses/NotModified" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "410": { "$ref": "#/components/responses/Gone" },
          "502": { "$ref": "#/components/responses/RenderFailed" },
          "503": { "$ref": "#/components/responses/Unavailable" }
        }
      },
      "head": {
        "tags": ["Signed URLs"],
        "operationId": "checkDeliveryUrl",
        "summary": "Validate a delivery URL without rendering or consuming a use",
        "security": [],
        "responses": {
          "200": { "description": "URL is valid. `Content-Type` is the image type it will serve." },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "503": { "$ref": "#/components/responses/Unavailable" }
        }
      }
    },
    "/api/v1/images/options": {
      "get": {
        "tags": ["Images"],
        "operationId": "getImageOptions",
        "summary": "Views, colors, sizes, formats, pricing, limits (free, public)",
        "security": [],
        "responses": {
          "200": {
            "description": "Everything needed to build valid requests. Cacheable for an hour.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ImageOptionsResponse" } } }
          }
        }
      }
    },
    "/api/v1/images/resolve": {
      "post": {
        "tags": ["Images"],
        "operationId": "resolveVehicleQuery",
        "summary": "Free text -> exact image parameters (free, deterministic)",
        "description": "Parses year, color (including synonyms such as navy, charcoal, cream), view phrases (\"side profile\", \"from behind\", \"front 3/4\"), size and format, then searches the catalog for the remaining words. No model calls; the same input always resolves the same way. Requires the `account:read` scope.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/ResolveRequest" },
              "example": { "query": "red 2024 porsche 911 side profile, webp" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Best match with candidates and a confidence level.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ResolveResponse" } } }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/VehicleNotFound" },
          "413": { "$ref": "#/components/responses/PayloadTooLarge" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        },
        "x-agent-notes": "Use `image_path` directly when confidence is `high`; show `candidates` to the human when it is `medium` or `low`. A 404 may carry `makes` when only a make was recognised."
      }
    },
    "/api/v1/vehicles": {
      "get": {
        "tags": ["Catalog"],
        "operationId": "browseVehicles",
        "summary": "Browse or search the vehicle catalog (free, public)",
        "description": "No parameters: available years. `year`: makes for that year. `year` + `makeId`: models. `q`: free-text search (optionally with `year`, `limit` ≤ 25). `make=<slug>`: models for a make (optionally `year`); add `model=<slug>` for that model's years. Slugs are lower-case, hyphenated (`mercedes-benz`, `model-3`); a model slug may also be a unique prefix.",
        "security": [],
        "parameters": [
          { "name": "year", "in": "query", "schema": { "type": "integer", "minimum": 1990 } },
          { "name": "makeId", "in": "query", "schema": { "type": "integer" } },
          { "name": "q", "in": "query", "schema": { "type": "string", "maxLength": 200 } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 25, "default": 10 } },
          { "name": "make", "in": "query", "description": "Make slug", "schema": { "type": "string" } },
          { "name": "model", "in": "query", "description": "Model slug (with `make`)", "schema": { "type": "string" } }
        ],
        "responses": {
          "200": {
            "description": "Catalog data; the `data` shape depends on the parameters (see schema variants). Cacheable for a day.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/VehiclesResponse" } } }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/api/v1/feedback": {
      "post": {
        "tags": ["Account"],
        "operationId": "submitImageFeedback",
        "summary": "Rate a rendered image (free)",
        "description": "Attach a rating or verdict to an image identified by the `request_id` (or `X-Request-Id`) of the request that delivered it, or by make/model/year/view/color. Repeated negative feedback flags the cached render for regeneration. Requires `account:read`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/FeedbackRequest" },
              "example": { "request_id": "8a1b…", "verdict": "bad", "reason": "wheels are blurred" }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Feedback recorded.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FeedbackResponse" } } }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "413": { "$ref": "#/components/responses/PayloadTooLarge" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/api/v1/account": {
      "get": {
        "tags": ["Account"],
        "operationId": "getAccount",
        "summary": "Balance, 30-day usage, pricing and key info (free)",
        "description": "Requires the `account:read` scope.",
        "responses": {
          "200": {
            "description": "Account state.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountResponse" } } }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/api/v1/billing/checkout": {
      "post": {
        "tags": ["Billing"],
        "operationId": "createBillingCheckout",
        "summary": "Create a hosted Stripe Checkout URL for a credit pack",
        "description": "Requires the `billing:write` scope (granted to keys created by the CLI login). Creating the session charges nothing; a human must open the URL and pay.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["credits"],
                "properties": { "credits": { "type": "integer", "enum": [5000, 10000, 25000, 100000] } },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Hosted Checkout URL.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CheckoutResponse" } } }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "413": { "$ref": "#/components/responses/PayloadTooLarge" },
          "429": { "$ref": "#/components/responses/RateLimited" },
          "500": { "$ref": "#/components/responses/ServerError" }
        },
        "x-agent-notes": "Only call after the human asked to add credits. Never complete a payment autonomously."
      }
    },
    "/api/v1/billing/portal": {
      "post": {
        "tags": ["Billing"],
        "operationId": "createBillingPortal",
        "summary": "Create a Stripe Customer Portal URL",
        "description": "Requires `billing:write` and a previous purchase (400 otherwise).",
        "responses": {
          "201": {
            "description": "Hosted portal URL.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PortalResponse" } } }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "429": { "$ref": "#/components/responses/RateLimited" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/api/v1/events": {
      "post": {
        "tags": ["Agents"],
        "operationId": "ingestEvents",
        "summary": "Public telemetry sink for the web beacon, CLI, MCP and SDKs",
        "description": "Unauthenticated, CORS-enabled, rate-limited per IP (120 batches/minute). Accepts 1–20 funnel events (≤ 32 KiB) and writes them after responding. Events are never billed and never affect an account.",
        "security": [],
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/EventsRequest" } } }
        },
        "responses": {
          "202": {
            "description": "Accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": ["accepted"],
                  "properties": { "accepted": { "type": "integer" } }
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "413": { "$ref": "#/components/responses/PayloadTooLarge" },
          "429": { "$ref": "#/components/responses/RateLimited" },
          "503": { "$ref": "#/components/responses/Unavailable" }
        }
      }
    },
    "/api/mcp": {
      "post": {
        "tags": ["Agents"],
        "operationId": "mcpStreamableHttp",
        "summary": "Remote MCP server (Streamable HTTP)",
        "description": "Model Context Protocol endpoint. Connect an MCP client to `https://car-imgs.vercel.app/api/mcp` with `Authorization: Bearer cimg_…`; the tools mirror this API (get an image, create signed URLs, resolve a description, browse the catalog, check the account, leave feedback). Requests are JSON-RPC 2.0 messages; responses are JSON or `text/event-stream` per the MCP Streamable HTTP transport. A local stdio alternative is `npx @meterapp/car-image mcp`.",
        "security": [{ "bearerAuth": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "type": "object", "description": "JSON-RPC 2.0 request or batch.", "additionalProperties": true }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JSON-RPC response(s).",
            "content": {
              "application/json": { "schema": { "type": "object", "additionalProperties": true } },
              "text/event-stream": { "schema": { "type": "string" } }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/api/auth/device/code": {
      "post": {
        "tags": ["Auth"],
        "operationId": "startDeviceLogin",
        "summary": "Start a CLI login (RFC 8628 device flow)",
        "description": "Public, 20 requests/minute per IP. The human opens `verification_uri_complete`, signs in and approves; the CLI polls `/api/auth/device/token`. Optional JSON or form body `{ \"client_name\": \"…\" }` names the key that will be created.",
        "security": [],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": { "type": "object", "properties": { "client_name": { "type": "string", "maxLength": 80 } } }
            },
            "application/x-www-form-urlencoded": {
              "schema": { "type": "object", "properties": { "client_name": { "type": "string", "maxLength": 80 } } }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Device and user codes.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DeviceCodeResponse" } } }
          },
          "429": { "$ref": "#/components/responses/RateLimited" },
          "503": { "$ref": "#/components/responses/Unavailable" }
        }
      }
    },
    "/api/auth/device/token": {
      "post": {
        "tags": ["Auth"],
        "operationId": "pollDeviceLogin",
        "summary": "Poll a CLI login and receive the API key once",
        "description": "Public, 60 requests/minute per IP; poll every `interval` seconds. The key (scopes images:read, account:read, billing:write) is returned exactly once and is never shown again — store it with 0600 permissions.",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "type": "object", "required": ["device_code"], "properties": { "device_code": { "type": "string" } } }
            },
            "application/x-www-form-urlencoded": {
              "schema": { "type": "object", "required": ["device_code"], "properties": { "device_code": { "type": "string" } } }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Approved: the new API key.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DeviceTokenResponse" } } }
          },
          "400": {
            "description": "`authorization_pending` (keep polling), `expired_token` (start over) or `invalid_request`.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DeviceError" } } }
          },
          "429": {
            "description": "`slow_down`: polling too fast; wait `Retry-After` seconds.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DeviceError" } } }
          },
          "503": { "$ref": "#/components/responses/Unavailable" }
        }
      }
    },
    "/images/car.png": {
      "get": {
        "tags": ["Legacy"],
        "operationId": "getEmbeddableImage",
        "summary": "Embeddable image endpoint (API key, signed URL, cached mode or playground)",
        "description": "Same renders as `/api/v1/images/car`, addressed as `brand`/`model`/`year`/`view`. Who may load it, in order: (1) partner-signed URLs carrying `exp` (unix seconds, ≤ 30 days ahead) and `sig` = lowercase hex HMAC-SHA256 over `/images/car.png?<query without sig, sorted by key>` with the partner secret — free, publicly cacheable until `exp`, never redirected; (2) `mode=cached` — public, serves only variants that already exist in the cache, never generates (404 otherwise); (3) the home-page examples — free; (4) an API key in `Authorization`/`x-api-key` — billed 1 credit, private cache; (5) the playground cookie or a signed-in session — free. Anything else is 401. Non-canonical spellings of unsigned requests are redirected (308) to the canonical URL.",
        "security": [{}, { "bearerAuth": [] }, { "apiKeyHeader": [] }],
        "parameters": [
          { "name": "brand", "in": "query", "description": "Make slug or name (alias of `make`; send one of them).", "schema": { "type": "string" } },
          { "name": "make", "in": "query", "schema": { "type": "string" } },
          { "name": "model", "in": "query", "required": true, "schema": { "type": "string" } },
          { "name": "year", "in": "query", "required": true, "schema": { "type": "integer", "minimum": 1990 } },
          { "name": "view", "in": "query", "schema": { "$ref": "#/components/schemas/View" } },
          { "name": "color", "in": "query", "schema": { "$ref": "#/components/schemas/Color" } },
          { "name": "w", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 1024 } },
          { "name": "h", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 1024 } },
          { "name": "size", "in": "query", "schema": { "$ref": "#/components/schemas/SizePreset" } },
          { "name": "format", "in": "query", "schema": { "$ref": "#/components/schemas/Format" } },
          { "name": "mode", "in": "query", "description": "`cached`: public, cache-only, never generates.", "schema": { "type": "string", "enum": ["cached"] } },
          { "name": "exp", "in": "query", "description": "Partner signature expiry, unix seconds.", "schema": { "type": "integer" } },
          { "name": "sig", "in": "query", "description": "Partner signature, 64 lowercase hex chars.", "schema": { "type": "string", "pattern": "^[0-9a-f]{64}$" } },
          { "name": "key", "in": "query", "deprecated": true, "description": "API key in the URL; only honoured when the deployment enables ALLOW_LEGACY_QUERY_KEYS. Use signed URLs instead.", "schema": { "type": "string" } },
          { "$ref": "#/components/parameters/IfNoneMatch" }
        ],
        "responses": {
          "200": {
            "description": "Image bytes. Cache-Control depends on the grant: public for signed/cached/example images, private for keyed, playground and session requests. Keyed responses carry `X-Credits-Charged` and `X-Credits-Remaining`.",
            "headers": {
              "ETag": { "$ref": "#/components/headers/ETag" },
              "X-Image-Source": { "$ref": "#/components/headers/XImageSource" },
              "X-Credits-Charged": { "$ref": "#/components/headers/XCreditsCharged" },
              "X-Credits-Remaining": { "$ref": "#/components/headers/XCreditsRemaining" },
              "X-Api-Key-Warning": { "description": "Present only while the deployment still serves unauthenticated embeds (LEGACY_UNAUTHENTICATED_IMAGES).", "schema": { "type": "string" } },
              "X-Request-Id": { "$ref": "#/components/headers/XRequestId" }
            },
            "content": {
              "image/png": { "schema": { "type": "string", "contentEncoding": "binary" } },
              "image/webp": { "schema": { "type": "string", "contentEncoding": "binary" } },
              "image/jpeg": { "schema": { "type": "string", "contentEncoding": "binary" } }
            }
          },
          "304": { "$ref": "#/components/responses/NotModified" },
          "308": { "description": "Redirect to the canonical spelling of the same image (`mode` and an honoured `key` survive)." },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "402": { "$ref": "#/components/responses/PaymentRequired" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "502": { "$ref": "#/components/responses/RenderFailed" },
          "503": { "$ref": "#/components/responses/Unavailable" }
        },
        "x-agent-notes": "For embeds prefer POST /api/v1/image-urls. Use mode=cached to display only what already exists without any cost or key."
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "cimg_ API key",
        "description": "Preferred. Keys start with `cimg_`; create one at /dashboard or with `npx @meterapp/car-image login`. Scopes: images:read, account:read, billing:write."
      },
      "apiKeyHeader": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key",
        "description": "Compatibility header; `Authorization: Bearer` is preferred."
      }
    },
    "parameters": {
      "Make": { "name": "make", "in": "query", "required": true, "description": "Make name or slug (`brand` is accepted as an alias; not both).", "schema": { "type": "string", "examples": ["porsche", "Mercedes-Benz"] } },
      "Model": { "name": "model", "in": "query", "required": true, "description": "Model name or slug; a unique prefix of a catalog model also matches.", "schema": { "type": "string", "examples": ["911", "model-3"] } },
      "Year": { "name": "year", "in": "query", "required": true, "schema": { "type": "integer", "minimum": 1990, "maximum": 2027, "examples": [2024] } },
      "View": { "name": "view", "in": "query", "schema": { "$ref": "#/components/schemas/View" } },
      "Color": { "name": "color", "in": "query", "schema": { "$ref": "#/components/schemas/Color" } },
      "Width": { "name": "w", "in": "query", "description": "Output width in pixels (fit inside, never enlarged).", "schema": { "type": "integer", "minimum": 1, "maximum": 1024 } },
      "Height": { "name": "h", "in": "query", "description": "Output height in pixels.", "schema": { "type": "integer", "minimum": 1, "maximum": 1024 } },
      "Size": { "name": "size", "in": "query", "description": "Preset shorthand for `w` (ignored when `w`/`h` are given).", "schema": { "$ref": "#/components/schemas/SizePreset" } },
      "Format": { "name": "format", "in": "query", "schema": { "$ref": "#/components/schemas/Format" } },
      "IfNoneMatch": { "name": "If-None-Match", "in": "header", "description": "Previous `ETag`; a match returns a free 304.", "schema": { "type": "string" } },
      "XRequestIdHeader": { "name": "X-Request-Id", "in": "header", "description": "Optional client-supplied id (1–128 chars of A-Z a-z 0-9 . _ : -) echoed back and stored.", "schema": { "type": "string" } }
    },
    "headers": {
      "XRequestId": { "description": "Id of this request; quote it in support reports.", "schema": { "type": "string" } },
      "XCreditsCharged": { "description": "Credits charged by this response (1 for a delivered image, 0 for a 304).", "schema": { "type": "integer" } },
      "XCreditsRemaining": { "description": "Balance after this request.", "schema": { "type": "integer" } },
      "XImageSource": { "description": "`cache` or `generated`; both cost the same.", "schema": { "type": "string", "enum": ["cache", "generated"] } },
      "XImageWidth": { "schema": { "type": "integer" } },
      "XImageHeight": { "schema": { "type": "integer" } },
      "ETag": { "description": "Strong validator for `If-None-Match`.", "schema": { "type": "string" } },
      "RateLimitLimit": { "description": "Requests allowed per minute for this key (default 120).", "schema": { "type": "integer" } },
      "RateLimitRemaining": { "schema": { "type": "integer" } },
      "RateLimitReset": { "description": "Seconds until the window resets.", "schema": { "type": "integer" } }
    },
    "schemas": {
      "View": {
        "type": "string",
        "enum": ["front", "front-3-4", "side", "side-right", "rear", "rear-3-4"],
        "default": "front-3-4",
        "description": "Camera angle. Aliases: front34/hero, rear34, back, profile/side-left, side-r."
      },
      "Color": {
        "type": "string",
        "enum": ["white", "black", "gray", "silver", "blue", "red", "green", "brown", "beige", "tan", "orange", "yellow", "gold", "burgundy", "purple"],
        "default": "silver"
      },
      "Format": { "type": "string", "enum": ["png", "webp", "jpg"], "default": "png", "description": "png and webp keep the transparent background; jpg is flattened on white. `jpeg` is accepted as an alias." },
      "SizePreset": { "type": "string", "enum": ["thumb", "small", "medium", "large"], "description": "thumb=256, small=512, medium=768, large=1024 pixels." },
      "ImageRequest": {
        "type": "object",
        "required": ["make", "model", "year"],
        "properties": {
          "make": { "type": "string", "minLength": 1 },
          "brand": { "type": "string", "description": "Alias of make; do not send both." },
          "model": { "type": "string", "minLength": 1 },
          "year": { "type": "integer", "minimum": 1990 },
          "view": { "$ref": "#/components/schemas/View" },
          "color": { "$ref": "#/components/schemas/Color" },
          "width": { "type": "integer", "minimum": 1, "maximum": 1024 },
          "height": { "type": "integer", "minimum": 1, "maximum": 1024 },
          "size": { "$ref": "#/components/schemas/SizePreset" },
          "format": { "$ref": "#/components/schemas/Format" }
        },
        "additionalProperties": false
      },
      "BatchImageUrlRequest": {
        "type": "object",
        "required": ["images"],
        "properties": {
          "images": { "type": "array", "minItems": 1, "maxItems": 50, "items": { "$ref": "#/components/schemas/ImageRequest" } },
          "ttl_seconds": { "type": "integer", "minimum": 60, "maximum": 604800, "default": 3600, "description": "Lifetime of the URLs; clamped to the deployment's bounds." },
          "max_uses": { "type": "integer", "minimum": 0, "maximum": 1000, "default": 0, "description": "0 = unlimited loads until expiry (publicly cacheable). A positive cap makes responses `private, no-store`." }
        },
        "additionalProperties": false
      },
      "VehicleParams": {
        "type": "object",
        "description": "Normalized parameters of a rendered image (slugs).",
        "required": ["make", "model", "year", "view", "color", "format"],
        "properties": {
          "make": { "type": "string" },
          "model": { "type": "string" },
          "year": { "type": "integer" },
          "view": { "$ref": "#/components/schemas/View" },
          "color": { "$ref": "#/components/schemas/Color" },
          "width": { "type": "integer" },
          "height": { "type": "integer" },
          "format": { "$ref": "#/components/schemas/Format" }
        }
      },
      "DeliveryUrl": {
        "type": "object",
        "required": ["id", "url", "expires_at", "max_uses", "vehicle"],
        "properties": {
          "id": { "type": "string", "format": "uuid" },
          "url": { "type": "string", "format": "uri" },
          "expires_at": { "type": "string", "format": "date-time" },
          "max_uses": { "type": "integer", "description": "0 = unlimited" },
          "vehicle": { "$ref": "#/components/schemas/VehicleParams" }
        }
      },
      "ImageUrlResponse": {
        "type": "object",
        "required": ["data", "billing", "request_id"],
        "properties": {
          "data": {
            "type": "object",
            "required": ["url", "expires_at", "max_uses", "vehicle", "width", "height", "format"],
            "properties": {
              "url": { "type": "string", "format": "uri" },
              "expires_at": { "type": "string", "format": "date-time" },
              "max_uses": { "type": "integer" },
              "vehicle": { "$ref": "#/components/schemas/VehicleParams" },
              "width": { "type": "integer" },
              "height": { "type": "integer" },
              "format": { "$ref": "#/components/schemas/Format" }
            }
          },
          "billing": { "$ref": "#/components/schemas/Billing" },
          "request_id": { "type": "string" }
        }
      },
      "ImageUrlsResponse": {
        "type": "object",
        "required": ["data", "billing", "request_id"],
        "properties": {
          "data": { "type": "array", "items": { "$ref": "#/components/schemas/DeliveryUrl" } },
          "billing": {
            "type": "object",
            "required": ["charged_on", "credits_charged", "credits_remaining"],
            "properties": {
              "charged_on": { "type": "string", "const": "creation" },
              "credits_charged": { "type": "integer", "description": "Number of URLs created." },
              "credits_remaining": { "type": "integer" },
              "credits_per_url": { "type": "integer", "const": 1 }
            }
          },
          "request_id": { "type": "string" }
        }
      },
      "Billing": {
        "type": "object",
        "required": ["credits_charged", "credits_remaining"],
        "properties": {
          "credits_charged": { "type": "integer" },
          "credits_remaining": { "type": "integer" }
        }
      },
      "ImageOptionsResponse": {
        "type": "object",
        "required": ["data", "request_id"],
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "views": { "type": "array", "items": { "type": "object", "properties": { "id": { "$ref": "#/components/schemas/View" }, "label": { "type": "string" }, "yaw_degrees": { "type": "integer" }, "description": { "type": "string" }, "aliases": { "type": "array", "items": { "type": "string" } } } } },
              "colors": { "type": "array", "items": { "type": "object", "properties": { "name": { "$ref": "#/components/schemas/Color" }, "hex": { "type": "string" } } } },
              "sizes": { "type": "object", "properties": { "presets": { "type": "object", "additionalProperties": { "type": "integer" } }, "max": { "type": "integer", "const": 1024 }, "source": { "type": "integer", "const": 1024 } } },
              "formats": { "type": "array", "items": { "type": "object", "properties": { "id": { "$ref": "#/components/schemas/Format" }, "mime": { "type": "string" }, "transparent": { "type": "boolean" } } } },
              "pricing": { "type": "object", "properties": { "credits_per_image": { "type": "integer" }, "credits_per_dollar": { "type": "integer" }, "free_credits": { "type": "integer" }, "packs": { "type": "array", "items": { "$ref": "#/components/schemas/Pack" } } } },
              "catalog": { "type": "object", "properties": { "makes": { "type": "integer" }, "models": { "type": "integer" }, "years": { "type": "object", "properties": { "from": { "type": "integer" }, "to": { "type": "integer" } } }, "sources": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string" }, "name": { "type": "string" }, "region": { "type": "string" }, "license": { "type": "string" } } } } } },
              "limits": { "type": "object", "properties": { "rate_limit_per_minute_default": { "type": "integer" }, "max_batch_urls": { "type": "integer" }, "delivery_ttl": { "type": "object", "properties": { "default": { "type": "integer" }, "min": { "type": "integer" }, "max": { "type": "integer" } } } } },
              "links": { "type": "object", "additionalProperties": { "type": "string" } }
            }
          },
          "request_id": { "type": "string" }
        }
      },
      "Pack": {
        "type": "object",
        "required": ["credits", "cents"],
        "properties": { "credits": { "type": "integer" }, "cents": { "type": "integer" }, "label": { "type": "string" } }
      },
      "ResolveRequest": {
        "type": "object",
        "required": ["query"],
        "properties": {
          "query": { "type": "string", "minLength": 1, "maxLength": 200, "description": "Free text, e.g. \"navy 2019 jeep wrangler front 3/4\"." },
          "year": { "type": "integer", "description": "Overrides any year in the text." },
          "make": { "type": "string", "maxLength": 60, "description": "Known make to narrow the search." },
          "model": { "type": "string", "maxLength": 60 }
        },
        "additionalProperties": false
      },
      "ResolveResponse": {
        "type": "object",
        "required": ["data", "request_id"],
        "properties": {
          "data": {
            "type": "object",
            "required": ["params", "display", "candidates", "confidence", "image_path"],
            "properties": {
              "params": {
                "type": "object",
                "required": ["make", "model", "year", "view", "color"],
                "properties": {
                  "make": { "type": "string", "description": "slug" },
                  "model": { "type": "string", "description": "slug" },
                  "year": { "type": "integer" },
                  "view": { "$ref": "#/components/schemas/View" },
                  "color": { "$ref": "#/components/schemas/Color" },
                  "size": { "$ref": "#/components/schemas/SizePreset" },
                  "width": { "type": "integer" },
                  "format": { "$ref": "#/components/schemas/Format" }
                }
              },
              "display": { "type": "object", "properties": { "make_name": { "type": "string" }, "model_name": { "type": "string" } } },
              "candidates": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "make_name": { "type": "string" },
                    "make_slug": { "type": "string" },
                    "model_name": { "type": "string" },
                    "model_slug": { "type": "string" },
                    "years": { "type": "array", "items": { "type": "integer" } },
                    "match_kind": { "type": "string", "enum": ["exact", "prefix", "token", "contains", "fuzzy"] }
                  }
                }
              },
              "confidence": { "type": "string", "enum": ["high", "medium", "low"] },
              "image_path": { "type": "string", "description": "Ready-to-request path on /api/v1/images/car." },
              "extracted": { "type": "object", "description": "What the parser recognised (year, color, view, size, width, format; null when absent).", "additionalProperties": true }
            }
          },
          "request_id": { "type": "string" }
        }
      },
      "VehiclesResponse": {
        "type": "object",
        "required": ["data", "request_id"],
        "properties": {
          "data": {
            "oneOf": [
              { "type": "object", "title": "Years", "required": ["years"], "properties": { "years": { "type": "array", "items": { "type": "integer" } } } },
              { "type": "object", "title": "Makes for a year", "required": ["year", "makes"], "properties": { "year": { "type": "integer" }, "makes": { "type": "array", "items": { "$ref": "#/components/schemas/CatalogMake" } } } },
              { "type": "object", "title": "Models for a make id and year", "required": ["year", "make_id", "models"], "properties": { "year": { "type": "integer" }, "make_id": { "type": "integer" }, "models": { "type": "array", "items": { "$ref": "#/components/schemas/CatalogModel" } } } },
              { "type": "object", "title": "Search results", "required": ["query", "results"], "properties": { "query": { "type": "string" }, "year": { "type": "integer" }, "results": { "type": "array", "items": { "$ref": "#/components/schemas/CatalogSearchHit" } } } },
              { "type": "object", "title": "Models for a make slug", "required": ["make", "models"], "properties": { "make": { "$ref": "#/components/schemas/CatalogMake" }, "year": { "type": "integer" }, "models": { "type": "array", "items": { "$ref": "#/components/schemas/CatalogModel" } } } },
              { "type": "object", "title": "Years for a make and model slug", "required": ["make", "model", "years"], "properties": { "make": { "$ref": "#/components/schemas/CatalogMake" }, "model": { "$ref": "#/components/schemas/CatalogModel" }, "years": { "type": "array", "items": { "type": "integer" } } } }
            ]
          },
          "request_id": { "type": "string" }
        }
      },
      "CatalogMake": {
        "type": "object",
        "required": ["id", "name", "slug"],
        "properties": { "id": { "type": "integer" }, "name": { "type": "string" }, "slug": { "type": "string" } }
      },
      "CatalogModel": {
        "type": "object",
        "required": ["name", "slug"],
        "properties": { "name": { "type": "string" }, "slug": { "type": "string" }, "vehicle_type": { "type": "string" } }
      },
      "CatalogSearchHit": {
        "type": "object",
        "required": ["kind", "make_name", "make_slug", "years", "match_kind"],
        "properties": {
          "kind": { "type": "string", "enum": ["make", "model"] },
          "make_name": { "type": "string" },
          "make_slug": { "type": "string" },
          "model_name": { "type": "string" },
          "model_slug": { "type": "string" },
          "vehicle_type": { "type": "string" },
          "years": { "type": "array", "items": { "type": "integer" } },
          "match_kind": { "type": "string", "enum": ["exact", "prefix", "token", "contains", "fuzzy"] }
        }
      },
      "FeedbackRequest": {
        "type": "object",
        "description": "Either `request_id` or make/model/year (+ optional view/color) identifies the image; `rating` or `verdict` is required.",
        "properties": {
          "request_id": { "type": "string", "maxLength": 128 },
          "make": { "type": "string" },
          "model": { "type": "string" },
          "year": { "type": "integer" },
          "view": { "$ref": "#/components/schemas/View" },
          "color": { "$ref": "#/components/schemas/Color" },
          "rating": { "type": "integer", "minimum": 1, "maximum": 5 },
          "verdict": { "type": "string", "enum": ["good", "bad"] },
          "reason": { "type": "string", "maxLength": 500 }
        },
        "additionalProperties": false
      },
      "FeedbackResponse": {
        "type": "object",
        "required": ["data", "request_id"],
        "properties": {
          "data": {
            "type": "object",
            "required": ["asset_id", "recorded"],
            "properties": {
              "asset_id": { "type": "string", "format": "uuid" },
              "recorded": { "type": "boolean", "const": true },
              "flagged": { "type": "boolean", "description": "True when this report pushed the render into review." }
            }
          },
          "request_id": { "type": "string" }
        }
      },
      "AccountResponse": {
        "type": "object",
        "required": ["data", "links", "request_id"],
        "properties": {
          "data": {
            "type": "object",
            "required": ["credits", "credits_value_usd", "auto_reload", "has_payment_method", "pricing", "usage_30d", "key"],
            "properties": {
              "credits": { "type": "integer" },
              "credits_value_usd": { "type": "number" },
              "auto_reload": { "type": "boolean" },
              "has_payment_method": { "type": "boolean" },
              "pricing": {
                "type": "object",
                "properties": {
                  "credits_per_image": { "type": "integer", "const": 1 },
                  "credits_per_delivery": { "type": "integer", "const": 1, "deprecated": true },
                  "credits_per_dollar": { "type": "integer", "const": 1000 },
                  "packs": { "type": "array", "items": { "$ref": "#/components/schemas/Pack" } }
                }
              },
              "usage_30d": {
                "type": "object",
                "required": ["requests", "images", "cache_hit_rate", "credits_spent"],
                "properties": {
                  "requests": { "type": "integer" },
                  "images": { "type": "integer" },
                  "cache_hit_rate": { "type": ["number", "null"] },
                  "credits_spent": { "type": "integer" }
                }
              },
              "key": {
                "type": "object",
                "properties": {
                  "id": { "type": "string", "format": "uuid" },
                  "scopes": { "type": "array", "items": { "type": "string", "enum": ["images:read", "account:read", "billing:write"] } },
                  "rate_limit_per_minute": { "type": "integer" }
                }
              }
            }
          },
          "links": { "type": "object", "additionalProperties": { "type": "string" } },
          "request_id": { "type": "string" }
        }
      },
      "CheckoutResponse": {
        "type": "object",
        "required": ["data", "request_id"],
        "properties": {
          "data": {
            "type": "object",
            "required": ["url", "credits", "amount_cents"],
            "properties": {
              "url": { "type": "string", "format": "uri" },
              "credits": { "type": "integer" },
              "amount_cents": { "type": "integer" }
            }
          },
          "request_id": { "type": "string" }
        }
      },
      "PortalResponse": {
        "type": "object",
        "required": ["data", "request_id"],
        "properties": {
          "data": { "type": "object", "required": ["url"], "properties": { "url": { "type": "string", "format": "uri" } } },
          "request_id": { "type": "string" }
        }
      },
      "EventsRequest": {
        "type": "object",
        "required": ["events"],
        "properties": {
          "events": {
            "type": "array",
            "minItems": 1,
            "maxItems": 20,
            "items": {
              "type": "object",
              "required": ["event"],
              "properties": {
                "event": { "type": "string", "description": "Funnel event name, e.g. page_view, cli_install, cli_login, mcp_session, docs_view." },
                "source": { "type": "string", "enum": ["web", "cli", "mcp", "api", "system", "sdk"] },
                "anonymous_id": { "type": "string" },
                "session_id": { "type": "string" },
                "properties": { "type": "object", "additionalProperties": true },
                "url": { "type": "string" },
                "referrer": { "type": "string" },
                "utm": { "type": "object", "additionalProperties": { "type": "string" } }
              }
            }
          }
        }
      },
      "DeviceCodeResponse": {
        "type": "object",
        "required": ["device_code", "user_code", "verification_uri", "verification_uri_complete", "expires_in", "interval"],
        "properties": {
          "device_code": { "type": "string" },
          "user_code": { "type": "string", "examples": ["ABCD-2345"] },
          "verification_uri": { "type": "string", "format": "uri" },
          "verification_uri_complete": { "type": "string", "format": "uri" },
          "expires_in": { "type": "integer", "const": 600 },
          "interval": { "type": "integer", "const": 3 }
        }
      },
      "DeviceTokenResponse": {
        "type": "object",
        "required": ["access_token", "token_type", "scope"],
        "properties": {
          "access_token": { "type": "string", "description": "The API key (cimg_…). Shown once." },
          "token_type": { "type": "string", "const": "Bearer" },
          "scope": { "type": "string", "examples": ["images:read account:read billing:write"] }
        }
      },
      "DeviceError": {
        "type": "object",
        "required": ["error", "request_id"],
        "properties": {
          "error": { "type": "string", "enum": ["authorization_pending", "expired_token", "invalid_request", "slow_down"] },
          "request_id": { "type": "string" }
        }
      },
      "Problem": {
        "type": "object",
        "description": "RFC 9457 problem details. `type` links to https://car-imgs.vercel.app/docs/errors#<status>.",
        "required": ["type", "title", "status", "detail", "request_id"],
        "properties": {
          "type": { "type": "string", "format": "uri" },
          "title": { "type": "string" },
          "status": { "type": "integer" },
          "detail": { "type": "string" },
          "request_id": { "type": "string" },
          "balance": { "type": "integer", "description": "402 only: current credits." },
          "required_credits": { "type": "integer", "description": "402 only: credits this request needed." },
          "index": { "type": "integer", "description": "Batch requests: which item failed." }
        },
        "additionalProperties": true
      }
    },
    "responses": {
      "Problem": {
        "description": "Problem details. Preserve `request_id` for support.",
        "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/Problem" } } }
      },
      "NotModified": {
        "description": "The image behind the supplied `If-None-Match` is unchanged. Free; still rate-limited.",
        "headers": { "ETag": { "$ref": "#/components/headers/ETag" }, "X-Request-Id": { "$ref": "#/components/headers/XRequestId" } }
      },
      "BadRequest": {
        "description": "Invalid parameters or body. Fix the request; do not retry unchanged.",
        "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/Problem" } } }
      },
      "Unauthorized": {
        "description": "Missing, invalid or revoked API key (`WWW-Authenticate: Bearer`).",
        "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/Problem" } } }
      },
      "PaymentRequired": {
        "description": "Not enough credits. Includes `balance` and `required_credits` and `Link: </pricing>; rel=\"payment\"`. Ask the human before buying.",
        "headers": { "Link": { "schema": { "type": "string" } } },
        "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/Problem" } } }
      },
      "Forbidden": {
        "description": "Key lacks the required scope, or a delivery/partner signature is invalid, expired or issued by a revoked key.",
        "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/Problem" } } }
      },
      "NotFound": {
        "description": "No such catalog entry or rendered image.",
        "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/Problem" } } }
      },
      "VehicleNotFound": {
        "description": "The make/model/year is not in the catalog. Search with GET /api/v1/vehicles?q=… or POST /api/v1/images/resolve.",
        "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/Problem" } } }
      },
      "Gone": {
        "description": "A use-capped delivery URL has been redeemed `max_uses` times. Create a new URL.",
        "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/Problem" } } }
      },
      "PayloadTooLarge": {
        "description": "Body exceeds the endpoint's limit (64 KiB for image-urls, 32 KiB for events, 8 KiB for feedback, 4 KiB for resolve, 1 KiB for checkout).",
        "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/Problem" } } }
      },
      "RateLimited": {
        "description": "Per-key (default 120/min) or per-IP limit exceeded. Wait `Retry-After` seconds; `RateLimit-*` headers describe the window.",
        "headers": { "Retry-After": { "schema": { "type": "integer" } } },
        "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/Problem" } } }
      },
      "RenderFailed": {
        "description": "The image could not be rendered. Any charge was refunded (for a delivery URL, its creation credit). Retry later.",
        "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/Problem" } } }
      },
      "ServerError": {
        "description": "Unexpected failure; nothing was charged. Retry with backoff.",
        "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/Problem" } } }
      },
      "Unavailable": {
        "description": "A dependency is temporarily unavailable. Honor `Retry-After`.",
        "headers": { "Retry-After": { "schema": { "type": "integer" } } },
        "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/Problem" } } }
      }
    }
  }
}
