{
  "openapi": "3.1.0",
  "info": {
    "title": "Model Price Watch API",
    "version": "1.0.0",
    "summary": "Verified LLM API token pricing for 237 models across 41 providers.",
    "description": "Read-only JSON feeds behind modelpricewatch.com. Every price traces to the provider's official pricing page and is re-verified on a schedule. Free to use and cite with attribution; no key required at the free tier. Prices are USD per 1,000,000 tokens unless stated otherwise.",
    "termsOfService": "https://modelpricewatch.com/api-pricing/",
    "contact": {
      "name": "Model Price Watch",
      "url": "https://modelpricewatch.com/contact/"
    },
    "license": {
      "name": "Free to use with attribution and a link back",
      "url": "https://modelpricewatch.com/api-pricing/"
    }
  },
  "servers": [
    {
      "url": "https://modelpricewatch.com",
      "description": "Production"
    }
  ],
  "externalDocs": {
    "description": "API documentation",
    "url": "https://modelpricewatch.com/api/"
  },
  "tags": [
    {
      "name": "Catalog",
      "description": "Models, providers and benchmarks."
    },
    {
      "name": "History",
      "description": "Price changes over time."
    },
    {
      "name": "Rankings",
      "description": "Curated per-use-case rankings and the LLM Price Index."
    },
    {
      "name": "Operations",
      "description": "Service health."
    }
  ],
  "paths": {
    "/api/v1/models.json": {
      "get": {
        "tags": [
          "Catalog"
        ],
        "operationId": "listModels",
        "summary": "Every tracked model with its current token prices.",
        "responses": {
          "200": {
            "description": "The full model catalog.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ModelCollection"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/v1/providers.json": {
      "get": {
        "tags": [
          "Catalog"
        ],
        "operationId": "listProviders",
        "summary": "Every tracked provider.",
        "responses": {
          "200": {
            "description": "The provider list.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/v1/benchmarks.json": {
      "get": {
        "tags": [
          "Catalog"
        ],
        "operationId": "listBenchmarks",
        "summary": "Published benchmark scores, keyed by model id.",
        "description": "An object whose keys are model ids. Cells are null where no independent benchmark exists — nulls are honest gaps, not zeroes.",
        "responses": {
          "200": {
            "description": "Benchmark scores by model id.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "type": "object"
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/v1/stats.json": {
      "get": {
        "tags": [
          "Catalog"
        ],
        "operationId": "getStats",
        "summary": "Headline counts and extremes for the whole dataset.",
        "responses": {
          "200": {
            "description": "Dataset summary.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Stats"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/v1/price-history.json": {
      "get": {
        "tags": [
          "History"
        ],
        "operationId": "getPriceHistory",
        "summary": "Recorded price changes over time.",
        "responses": {
          "200": {
            "description": "Price history records.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/v1/changelog.json": {
      "get": {
        "tags": [
          "History"
        ],
        "operationId": "getChangelog",
        "summary": "Dated log of catalog and price changes.",
        "responses": {
          "200": {
            "description": "Changelog entries.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/v1/price-index.json": {
      "get": {
        "tags": [
          "Rankings"
        ],
        "operationId": "getPriceIndex",
        "summary": "The LLM Price Index — one citeable number for the cost of frontier inference.",
        "externalDocs": {
          "description": "Methodology",
          "url": "https://modelpricewatch.com/price-index/methodology/"
        },
        "responses": {
          "200": {
            "description": "Current index value, series and events.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PriceIndex"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/v1/price-index-levels.json": {
      "get": {
        "tags": [
          "Rankings"
        ],
        "operationId": "getPriceIndexLevels",
        "summary": "Price index broken out by capability tier.",
        "responses": {
          "200": {
            "description": "Index levels.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/v1/best-for/{intent}.json": {
      "get": {
        "tags": [
          "Rankings"
        ],
        "operationId": "getBestFor",
        "summary": "Ranked models for a use case.",
        "parameters": [
          {
            "name": "intent",
            "in": "path",
            "required": true,
            "description": "Use-case slug.",
            "schema": {
              "type": "string",
              "enum": [
                "coding",
                "chatbot",
                "cheap-api",
                "prompt-caching",
                "long-context",
                "multimodal",
                "reasoning",
                "open-source",
                "fast-inference",
                "embedding",
                "enterprise"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Ranked models for the requested use case.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "404": {
            "description": "No ranking published for that slug."
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/health": {
      "get": {
        "tags": [
          "Operations"
        ],
        "operationId": "getHealth",
        "summary": "Service health and dataset freshness.",
        "description": "Not rate limited and never requires a key. Referenced as the `status` relation from /.well-known/api-catalog.",
        "responses": {
          "200": {
            "description": "Service is serving data.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Health"
                }
              }
            }
          },
          "503": {
            "description": "The dataset could not be read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Health"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key",
        "description": "Optional. Omit for the free tier; a key raises the daily request limit. See https://modelpricewatch.com/api-pricing/"
      }
    },
    "responses": {
      "RateLimited": {
        "description": "Daily request limit for the tier exceeded.",
        "headers": {
          "X-RateLimit-Limit": {
            "schema": {
              "type": "integer"
            },
            "description": "Requests allowed per day for this tier."
          },
          "X-RateLimit-Remaining": {
            "schema": {
              "type": "integer"
            },
            "description": "Requests left today."
          },
          "X-Tier": {
            "schema": {
              "type": "string"
            },
            "description": "Tier the request was billed against."
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "schemas": {
      "Envelope": {
        "type": "object",
        "description": "Standard collection envelope used by most feeds.",
        "required": [
          "count",
          "updated",
          "data"
        ],
        "properties": {
          "count": {
            "type": "integer",
            "description": "Number of items in `data`."
          },
          "updated": {
            "type": "string",
            "format": "date",
            "description": "Date this feed was last regenerated."
          },
          "data": {
            "type": "array",
            "items": {
              "type": "object"
            }
          }
        }
      },
      "ModelCollection": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Envelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Model"
                }
              }
            }
          }
        ]
      },
      "Model": {
        "type": "object",
        "required": [
          "id",
          "provider",
          "model",
          "input_per_mtok",
          "output_per_mtok"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Stable slug, e.g. anthropic-claude-opus-5."
          },
          "provider": {
            "type": "string"
          },
          "model": {
            "type": "string",
            "description": "Display name."
          },
          "category": {
            "type": "string"
          },
          "input_per_mtok": {
            "type": [
              "number",
              "null"
            ],
            "description": "USD per 1M input tokens."
          },
          "output_per_mtok": {
            "type": [
              "number",
              "null"
            ],
            "description": "USD per 1M output tokens. Null for embedding/rerank models that bill input only."
          },
          "cached_input_per_mtok": {
            "type": [
              "number",
              "null"
            ],
            "description": "USD per 1M cached input tokens, where the provider offers prompt caching."
          },
          "promo": {
            "type": "boolean",
            "description": "True when the served price is a time-limited launch/intro/promotional rate. Budget on the list price, not this number, when true."
          },
          "promo_until": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "ISO date the promotional price is announced to end. Null when the provider has published no end date (the promo can still end at any time)."
          },
          "price_status": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "verifying",
              null
            ],
            "description": "Absent/null on a priced row. \"verifying\" means we are re-verifying this model's current rate and are deliberately publishing no number: input_per_mtok, output_per_mtok, cached_input_per_mtok and blended_cost_per_mtok are all null, and none of them should be read as zero. Distinct from a null price on a priced row, which means that SKU has no such charge (an embedding bills input only)."
          },
          "blended_cost_per_mtok": {
            "type": [
              "number",
              "null"
            ],
            "description": "Weighted input:output blend. See /api/v1/price-index.json for the ratio in force. Null when price_status is \"verifying\"."
          },
          "context_window": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Maximum context in tokens."
          },
          "modality": {
            "type": [
              "string",
              "array",
              "null"
            ]
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "released": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "status": {
            "type": "string",
            "description": "Lifecycle, e.g. Current, Deprecated, Retired."
          },
          "open_source": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "parameters": {
            "type": [
              "string",
              "null"
            ]
          },
          "pricing_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "description": "The provider's official pricing page this row was read from."
          },
          "last_updated": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "evidence": {
            "type": [
              "object",
              "null"
            ],
            "description": "Provenance for the current price, read from our archive of dated captures of provider pricing pages. null means we hold no capture that proves this row's price — either none ever tied the model's name to a published price on the provider's page, or the price has moved since one did. null is a deliberate statement that we cannot prove the number, not missing data.",
            "properties": {
              "basis": {
                "type": "string",
                "enum": [
                  "anchored_capture",
                  "price_change_receipt",
                  "legacy_capture"
                ],
                "description": "Which question this receipt answers. `anchored_capture`: we matched the SKU to a price on the same row of the provider's page — the only basis served for a Current/Preview model. `price_change_receipt` / `legacy_capture`: an older capture predating row-level anchoring, served only for Retired/Deprecated rows whose price is historical and whose SKU the vendor no longer lists."
              },
              "as_of": {
                "type": "string",
                "format": "date",
                "description": "The date we read the provider's page."
              },
              "event": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "What the capture documented (e.g. price_drop, correction, new_model). null when the price simply held, which is the common case: a re-verification that confirms an unchanged price is still a receipt."
              },
              "evidence_url": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "uri",
                "description": "The provider page we read. This is the checkable artefact."
              },
              "captured_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              },
              "sha": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Content hash of the page text we captured."
              },
              "snapshot": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Repository path of the archived page text. Not a public URL."
              },
              "anchor_sku": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The SKU string matched on the provider's page. Present on `anchored_capture` only. This is the derived finding behind the citation."
              },
              "anchor_scope": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Where the price was found relative to the SKU: `row`, `column`, `card`, `tier` (a shared pricing tier that enumerates the SKU on its `Models:` line), `record` (the block the vendor keys with this SKU's machine id — printed as the block's footer, or as the key line above a transposed token-type/price table), `json` (the vendor serves a machine-readable rate list and the price was read from this SKU's own record in it), or `schedule` (the SKU's own card carries a dated rate schedule and the price was read from the window open on the receipt's date)."
              },
              "source": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "confidence": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Capture-time trust label, derived from whether the capture tied the SKU to a price on the provider's page. It therefore restates what `basis: anchored_capture` and `anchor_sku` already tell you; those are the primary fields."
              }
            }
          },
          "detail_url": {
            "type": "string",
            "format": "uri",
            "description": "Human-readable page for this model."
          }
        }
      },
      "Stats": {
        "type": "object",
        "properties": {
          "total_models": {
            "type": "integer"
          },
          "total_providers": {
            "type": "integer"
          },
          "open_source_models": {
            "type": "integer"
          },
          "multimodal_models": {
            "type": "integer"
          },
          "categories": {
            "type": "object"
          },
          "cheapest_input": {
            "type": "object"
          },
          "cheapest_output": {
            "type": "object"
          },
          "largest_context": {
            "type": "object"
          },
          "updated": {
            "type": "string",
            "format": "date"
          }
        }
      },
      "PriceIndex": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "value": {
            "type": "number"
          },
          "unit": {
            "type": "string"
          },
          "asOf": {
            "type": "string",
            "format": "date"
          },
          "blendRatio": {
            "type": "string"
          },
          "weighting": {
            "type": "string"
          },
          "method": {
            "type": "string"
          },
          "change": {
            "type": "object"
          },
          "series": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "events": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "citation": {
            "type": "string"
          }
        }
      },
      "Health": {
        "type": "object",
        "required": [
          "status"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "ok",
              "degraded"
            ]
          },
          "models": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Models currently served."
          },
          "data_updated": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Date the served dataset was generated."
          },
          "checked": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          },
          "limit": {
            "type": "integer"
          },
          "tier": {
            "type": "string"
          }
        }
      }
    }
  },
  "security": [
    {},
    {
      "ApiKeyAuth": []
    }
  ]
}
