# Model Pricing API

The Model Pricing API resolves model names to token prices and manages project-specific overrides.
Provon uses the resolved definition to calculate Gateway and telemetry cost fields.

Base URL:

```text
https://api.provon.dev/v1
```

Public routes use a project API key:

```http
Authorization: Bearer <PROVON_API_KEY>
```

| Capability            | Access                                              |
| --------------------- | --------------------------------------------------- |
| `model-pricing:read`  | List resolved prices and test model matching        |
| `model-pricing:write` | Create, update, reset, and delete project overrides |

The default project key includes `model-pricing:read`.

## Endpoints

| Method   | Path                      | Purpose                                    |
| -------- | ------------------------- | ------------------------------------------ |
| `GET`    | `/model-prices`           | List defaults plus project-resolved prices |
| `GET`    | `/model-prices/match`     | Resolve one model/provider pair            |
| `POST`   | `/model-prices`           | Create or replace a project definition     |
| `PATCH`  | `/model-prices/:id`       | Update one project definition              |
| `POST`   | `/model-prices/:id/reset` | Reset an overridden default                |
| `DELETE` | `/model-prices/:id`       | Delete a project-custom definition         |

Signed-in Workbench calls use `/v1/projects/:projectId/model-prices...`. API integrations should
normally use the routes above, where the key selects the project.

## List Resolved Prices

```http
GET /v1/model-prices
Authorization: Bearer <PROVON_API_KEY>
```

Response:

```json
{
  "models": [
    {
      "id": "openai:gpt-5-mini",
      "provider": "openai",
      "modelName": "gpt-5-mini",
      "matchPattern": "^gpt-5-mini(?:-|$)",
      "pricingTiers": [
        {
          "id": "standard",
          "name": "Standard",
          "isDefault": true,
          "priority": 0,
          "conditions": [],
          "prices": {
            "input_tokens": 2.5e-7,
            "output_tokens": 2e-6
          }
        }
      ],
      "source": "default",
      "editable": true,
      "resettable": false
    }
  ]
}
```

The list is already resolved for the project. A project override replaces or extends its base
definition before the response is returned.

Prices are USD per chargeable unit. Token keys are normally per token, not per million tokens.
For example, `$0.25 / 1M` input tokens is represented as `0.00000025`.

## Match A Model

Use the match endpoint before relying on cost projections for a new model:

```http
GET /v1/model-prices/match?provider=openai&model=gpt-5-mini-2026-06-01
Authorization: Bearer <PROVON_API_KEY>
```

Response:

```json
{
  "match": {
    "model": {
      "id": "openai:gpt-5-mini",
      "provider": "openai",
      "modelName": "gpt-5-mini"
    },
    "pricingTier": {
      "id": "standard",
      "name": "Standard"
    },
    "source": "default"
  }
}
```

`match` is `null` when no definition matches. `model` is required; `provider` is optional but
recommended when different providers reuse a model name.

## Create A Custom Definition

```http
POST /v1/model-prices
Content-Type: application/json
```

```json
{
  "provider": "external",
  "modelName": "acme-reasoner-v2",
  "matchPattern": "^acme-reasoner-v2(?:-|$)",
  "pricingTiers": [
    {
      "id": "standard",
      "name": "Standard",
      "isDefault": true,
      "priority": 0,
      "conditions": [],
      "prices": {
        "input_tokens": 8e-7,
        "output_tokens": 3.2e-6,
        "reasoning_output_tokens": 3.2e-6,
        "cache_read_input_tokens": 8e-8
      }
    }
  ]
}
```

Supported providers are:

```text
openai
external
anthropic
google
xai
deepseek
alibaba
mistral
moonshot
minimax
zai
```

Common price keys are `input_tokens`, `output_tokens`, `reasoning_output_tokens`,
`cache_creation_input_tokens`, and `cache_read_input_tokens`. Additional non-negative numeric keys
are preserved for provider-specific usage detail.

Successful creation returns `201` with `{ "model": ... }`.

## Pricing Tiers

Use tiers when price depends on a usage detail such as context length:

```json
{
  "id": "long-context",
  "name": "Long context",
  "isDefault": false,
  "priority": 100,
  "conditions": [
    {
      "usageDetailPattern": "input_tokens",
      "operator": "gte",
      "value": 200000
    }
  ],
  "prices": {
    "input_tokens": 1.6e-6,
    "output_tokens": 6.4e-6
  }
}
```

Condition operators are `gt`, `gte`, `lt`, `lte`, `eq`, and `neq`. Non-default tiers are evaluated
from the smallest `priority` number to the largest; one tier should be marked as the default
fallback.

## Override And Reset

To override an existing default, create a project definition with `baseModelPriceId` set to the
default definition ID. The returned source becomes `project_override`.

Update the project definition:

```http
PATCH /v1/model-prices/:id
```

The update body uses the same complete shape as creation: `provider`, `modelName`, and a non-empty
`pricingTiers` array are required.

Reset an override to its default:

```http
POST /v1/model-prices/:id/reset
```

Delete a project-custom definition:

```http
DELETE /v1/model-prices/:id
```

Both operations return:

```json
{
  "ok": true
}
```

## Cost Resolution

Provon resolves cost in this order:

1. choose the project-resolved model definition by provider, exact name, or match pattern;
2. choose the highest-priority pricing tier whose conditions match usage details;
3. multiply each normalized usage bucket by its unit price;
4. write the model, tier, source, and cost breakdown into normalized telemetry.

If no model or required price key matches, the corresponding cost remains `null`. Provon does not
invent a zero cost for unknown pricing.

## Errors

| Status | Meaning                                                         |
| ------ | --------------------------------------------------------------- |
| `400`  | Missing model/provider, invalid JSON, tier, or condition        |
| `401`  | Missing or invalid project API key                              |
| `403`  | Key lacks `model-pricing:read` or `model-pricing:write`         |
| `501`  | This runtime supports reads but has no pricing store for writes |

## Related Docs

- [Model providers](./model-providers.md)
- [Gateway API](./gateway-api.md)
- [Gateway observability](./gateway-observability.md)
- [Tracing attribute reference](./tracing-attributes.md)
- [API reference](./api-reference.md)
