---
title: Overage
description: What happens when a customer spends past their balance — the three policies, the overage record, and how to reconcile arrears.
order: 12
---

# Overage

Overage is what happens when a customer's usage costs more than their balance holds. Your policy decides whether that call is refused, or allowed and written down as a debt. Balances never go negative. The debt lives in its own record.

> **Mental Model:** Overage is a **tab at the bar**. When the customer's prepaid card runs dry, your policy decides what happens: refuse the round (`block`), or pour it and write the difference on the tab (`allow`). The tab is a separate record — the card never goes negative.

## Quick Take

- Three policies: `block` refuses, `allow` pours and records, `notify` is **identical to allow today**
- A customer's own policy wins when set; the **tenant default** applies otherwise
- Balance never goes negative; the shortfall is written to its own **overage record**
- Amounts are millicredits, one record per over-spending call
- Read arrears with `GET /v1/customers/{id}/overage?from=&to=` — both bounds required

## Diagram

A usage event costing more than the balance splits three ways by policy: block refuses it entirely, while allow and notify debit the balance to zero and write the remainder to the overage record.

```mermaid
flowchart TD
    U[Usage event costs more<br/>than the balance] --> P{Effective overage policy}
    P -->|block| R[Refused<br/>nothing debited]
    P -->|allow / notify| D[Debit what exists<br/>balance to zero]
    D --> O[Overage record<br/>the shortfall in millicredits]
```

## The three policies

| Policy | What happens to the call | What is recorded |
|---|---|---|
| `block` | Refused. Nothing is debited. | Nothing. |
| `allow` | Allowed. The balance is spent down to zero. | The shortfall, as an overage record. |
| `notify` | Allowed. The balance is spent down to zero. | The shortfall, as an overage record. |

**`notify` behaves exactly like `allow` today.** The engine treats the two words the same. There is no overage notification webhook yet. Pick `notify` if you want to record the intent, but do not wait for a message that is not sent.

## Configuring the policy

Your tenant sets a default policy in the dashboard, under Organization settings. It applies when a customer has no value of its own.

A customer can set its own `overage_policy` field. When set, it wins over the tenant default. Send an empty string to clear it, and the tenant default applies again.

This works both ways. A tenant that allows overage can still block one risky customer. A tenant that blocks overage can still allow one trusted customer.

On the customer endpoint, a bad value now returns `422` and names the field. It used to return a database error.

## What `block` does

`block` is all-or-nothing. If the call costs more than the balance holds, nothing is debited and the usage is refused. No partial spend. No overage record.

A refused call is a settled answer, not a failure to retry. QuotaStack does not keep retrying an unaffordable usage event, because a customer who cannot pay today may not be able to pay in an hour either, and a retry loop would block every event behind it.

## What `allow` does

`allow` spends what is there and records the rest.

Say a customer has **3,000 millicredits** and makes a call that costs **5,000**:

- 3,000 millicredits are debited. The balance is now 0.
- The remaining **2,000** is written to the overage record.
- The balance is 0, not -2,000. Balances stop at zero.

You bill the 2,000 later, from the overage record.

## The overage record

Every over-spending call writes one row. Each row holds:

- the billable metric that was used,
- the amount in millicredits, always greater than zero,
- the environment,
- the idempotency key of the call that caused it,
- when it happened.

The idempotency key matters. A retried call cannot be counted twice, because the record is unique on your tenant, the environment, and that key.

## Reading arrears back

Ask for a customer's overage over a window:

```bash
curl "https://api.quotastack.io/v1/customers/{customer_id}/overage?from=2026-07-01T00:00:00Z&to=2026-08-01T00:00:00Z" \
  -H "X-API-Key: qs_live_..."
```

Four rules, all enforced:

1. `from` and `to` are **both required**. Without them the call returns `422`.
2. The window is half-open, written `[from, to)`. A row created exactly at `to` is **not** included.
3. `to` must be after `from`.
4. An unknown customer returns `404`. Reading never creates a customer.

The response groups by metric and gives you a total:

```json
{
  "data": [
    { "billable_metric_key": "image_generation", "overage_mc": 2000 },
    { "billable_metric_key": "tokens", "overage_mc": 450 }
  ],
  "total_overage_mc": 2450,
  "period": { "from": "2026-07-01T00:00:00Z", "to": "2026-08-01T00:00:00Z" }
}
```

Amounts are millicredits. Rows are sorted by metric key.

## Reconciling at the end of a period

For postpaid subscriptions, the `subscription.renewed` webhook carries a usage summary for the period that just closed. That is the push side.

The read endpoint above is the pull side. Use it when you want to reconcile without waiting for the webhook, or when you need the numbers again and do not want to replay a delivery. Both read the same records, so they agree.

The full billing recipe is in [Bill overage in arrears](/docs/cookbook/overage-billing-in-arrears).

## Seeing it in the dashboard

The customer page has an Overage tab. Pick a window — the current billing period, the last 7 days, or the last 30 days — and it shows the per-metric totals and the sum.

The tab also shows which policy is in force: the customer's own value if it has one, or the tenant default.

## Common Mistakes

**✗ Don't send `null` expecting to clear a customer's overage_policy override**

`null` leaves the stored value unchanged. Send an empty string to clear it — the same rule `display_name` already follows.

**✗ Don't pick `notify` expecting a notification**

It behaves exactly like `allow`. No overage webhook is emitted yet.

**✗ Don't call the overage endpoint without `from` and `to`**

Both are required and the call returns `422` without them. The window is half-open — `to` is excluded.

**✗ Don't expect a negative balance to represent arrears**

Balances stop at zero. Arrears live in the overage record, and that is what you bill from.

## Related

- [Credits](/docs/concepts/credits) — Blocks, balances, and the ledger the debit comes out of.
- [Subscriptions](/docs/concepts/subscriptions) — Postpaid renewal carries the period usage summary.
- [Metering](/docs/concepts/metering) — Metering rules decide what a unit of usage costs.
- [Bill overage in arrears](/docs/cookbook/overage-billing-in-arrears) — The end-to-end recipe for charging what was consumed past the balance.
