# Model Pricing and Policies

## Contents

- Pricing Rule Sets
- Billing Configuration and Estimate Reconciliation
- Runtime Policy Sets
- Runner Policy and Runtime Recovery

## Pricing Rule Sets

Read rule sets and effective rule rows:

```bash
curl --fail-with-body \
  -H "Authorization: Bearer $GATEWAY_ADMIN_TOKEN" \
  "$GATEWAY_BASE_URL/api/admin/pricing/rule-sets"

curl --fail-with-body \
  -H "Authorization: Bearer $GATEWAY_ADMIN_TOKEN" \
  "$GATEWAY_BASE_URL/api/admin/pricing/rules"
```

### Reuse-first pricing decision

Do not create a pricing rule until all existing active rule sets have been compared against the target resource types, units, calculator types, base prices, weights, and conditions.

Evaluate the price that the runtime will actually use:

1. Identify the inherited pricing source from the base model and platform, then check whether the platform-model has an explicit `pricingRuleSetId` or billing override.
2. Reuse the existing rule when it already describes the required raw unit prices and calculators.
3. Apply the effective discount:
   - a positive platform-model `discountFactor` takes precedence;
   - otherwise `pricingMode: "inherit_discount"` uses the platform `defaultDiscountFactor`;
   - AI Gateway does not multiply the platform and platform-model discount factors together.
4. Verify the resulting amount with `/api/v1/pricing/estimate`, simulation billing lines, or an approved test request.
5. Create a new rule set only when no existing rule plus the available platform/platform-model discount can produce the required price or express the required unit/calculator structure.

Do not clone an otherwise identical pricing rule merely to represent a provider or account discount. Keep the reusable base price in the rule and express the instance-specific adjustment with `defaultDiscountFactor` or `discountFactor`.

For the complete binding, estimate, task-charge, and wallet-reconciliation workflow, read `model-billing-configuration-and-estimation.md` before changing billing settings.

Create an example text pricing rule set:

```bash
curl --fail-with-body \
  -H "Authorization: Bearer $GATEWAY_ADMIN_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{
    "ruleSetKey": "example-chat-pricing-v1",
    "name": "Example Chat Pricing",
    "description": "Input and output token pricing",
    "category": "model",
    "currency": "resource",
    "status": "active",
    "metadata": {},
    "rules": [
      {
        "ruleKey": "input",
        "displayName": "Input tokens",
        "resourceType": "text_input",
        "unit": "1k_tokens",
        "basePrice": 0.001,
        "calculatorType": "token_usage",
        "priority": 10,
        "status": "active"
      },
      {
        "ruleKey": "output",
        "displayName": "Output tokens",
        "resourceType": "text_output",
        "unit": "1k_tokens",
        "basePrice": 0.002,
        "calculatorType": "token_usage",
        "priority": 20,
        "status": "active"
      }
    ]
  }' \
  "$GATEWAY_BASE_URL/api/admin/pricing/rule-sets"
```

`PATCH /api/admin/pricing/rule-sets/{ruleSetID}` replaces the stored rules with the supplied list. Preserve every rule that should remain. Delete only non-default rule sets after checking base-model, platform, and platform-model bindings.

## Runtime Policy Sets

Read and create policies:

```bash
curl --fail-with-body \
  -H "Authorization: Bearer $GATEWAY_ADMIN_TOKEN" \
  "$GATEWAY_BASE_URL/api/admin/runtime/policy-sets"
```

Compare the existing policy sets before creating one. Reuse a policy when the effective rate-limit metrics, limits, windows, concurrency lease TTL, retry count, auto-disable behavior, degradation behavior, and scope semantics match the target. A different platform name or model name alone is not a reason to duplicate a policy.

Create a new policy only when at least one required behavior cannot be represented by an existing policy plus the supported platform-model override fields. Record the mismatch that justified the new policy.

```json
{
  "policyKey": "example-balanced-v1",
  "name": "Example Balanced",
  "description": "Retry and concurrency policy",
  "rateLimitPolicy": {
    "rules": [
      {"metric": "rpm", "limit": 60, "windowSeconds": 60},
      {"metric": "concurrent", "limit": 5, "leaseTtlSeconds": 120}
    ]
  },
  "retryPolicy": {"maxRetries": 2},
  "autoDisablePolicy": {},
  "degradePolicy": {},
  "metadata": {},
  "status": "active"
}
```

POST the body to `/api/admin/runtime/policy-sets`. Use PATCH with a complete body. Default policy sets cannot be deleted.

## Runner Policy and Runtime Recovery

Read the current global runner policy before changing it:

```bash
curl --fail-with-body \
  -H "Authorization: Bearer $GATEWAY_ADMIN_TOKEN" \
  "$GATEWAY_BASE_URL/api/admin/runtime/runner-policy"
```

PATCH the same endpoint with the complete current fields plus approved changes to `failoverPolicy`, `hardStopPolicy`, `singleSourcePolicy`, or `cacheAffinityPolicy`.

Operational endpoints:

- `PATCH /api/admin/platforms/{platformID}/dynamic-priority`
- `GET /api/admin/runtime/rate-limit-windows`
- `GET /api/admin/runtime/model-rate-limits`
- `POST /api/admin/runtime/model-rate-limits/{platformModelID}/restore`

Use restore only after identifying whether the model, platform cooldown, or platform disablement was automatic and whether the upstream condition has recovered.
