# Leases

> Lease a block of a customer's prepaid credits, meter high-frequency usage against it in your own service, and settle in batches, with a clear outcome if your service crashes.

A **lease** reserves a block of a customer's wallet, say 5.00, for a few minutes. Your service meters usage against it locally, in memory or in its own fast store, and settles what it used every few seconds. Use leases when usage is too frequent for a call to Ownrecord per charge: model calls, API requests, tokens. For an occasional charge, a single [reservation](https://ownrecord.io/docs/concepts/wallets.md) is simpler.

Leases draw on a customer's **prepaid credits** in their wallet. Usage billed in arrears with metered prices is a separate path, described in [usage billing](https://ownrecord.io/docs/concepts/usage.md). One customer can have both, on different meters.

## Lease

```http
POST /api/v1/wallets/{walletId}/leases
Idempotency-Key: 8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21

{ "amount": { "amount": "5000000", "currency": "EUR" }, "ttlSeconds": 300 }
```

The funds come out of the wallet's spendable credits in spend order: promo credits first, then credits included in a subscription, then purchased credits, each soonest expiry first. They stay reserved until you settle the lease. A lease lives at most 900 seconds (`ttlSeconds`). If the wallet has less than `amount`, the request fails with `insufficient_funds` (402). A frozen or closed wallet can't be leased from.

**Never consume more than the lease's `remaining`.** Your service is the meter, and the lease is the most it may spend.

## Settle

```http
POST /api/v1/leases/{leaseId}/settle

{
  "consumed": { "amount": "1250000", "currency": "EUR" },
  "usageSummary": [
    { "meter": "api.calls", "quantity": "1000", "amount": { "amount": "1000000", "currency": "EUR" } },
    { "meter": "tokens.out", "quantity": "25000", "amount": { "amount": "250000", "currency": "EUR" } }
  ],
  "settleSeq": 1
}
```

A settle charges what you used since the previous settle (`consumed`) and books it as usage revenue per meter. The `usageSummary` lines say what it was for: one line per meter, and per set of `attributes` if you use them. Their amounts add up to `consumed`. Each line is stored as a usage event and counted in the [daily usage aggregates](https://ownrecord.io/docs/concepts/usage.md#daily-aggregates), with its amount.

After the charge, the lease:

- **stays open** when you send neither `final` nor `renew`. Settle as often as you like, every few seconds or every so many units;
- **closes** with `final: true`. What it still holds goes back to the wallet. Send this when your service shuts down;
- **is renewed** with `renew`. The lease closes and a new one, with a new ID and a fresh TTL, takes its place in the same request. It keeps the expiry terms; `renew.amount` and `renew.ttlSeconds` change its size and length. Renew before `expiresAt`. If the wallet has less than the amount, the new lease gets what there is; `renewedLease` is null if there's nothing, or if the wallet was frozen.

Meters for prepaid usage are names you choose, such as `api.calls`. A meter that a metered price bills in arrears can't be used here, because that usage would be charged twice.

### Retries and ordering

Settles are safe to retry. Send the same request with the same `Idempotency-Key` and you get the same answer, `duplicate: true` once it's applied, and nothing is charged twice.

If your service can send settles of one lease concurrently or out of order, number them with `settleSeq`: 1 for the first settle of a lease, then 2, 3 and so on. Ownrecord applies settle _n_ only after settle _n − 1_. One that arrives early gets `lease_settle_out_of_order`, which is retryable, so a `final` settle can never close a lease before earlier usage is charged. A settle numbered at or below the lease's `settleSeq` was applied already and is answered as a duplicate.

## When a lease runs out

If a lease reaches `expiresAt` without a closing settle, because your service crashed or lost its connection, its **expiry policy** applies. You choose it per lease with `expiryPolicy`:

| Policy                 | What happens                                                                                                                                                                                                                                                                             |
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `release` (default)    | What the lease still holds goes back to the wallet. A later settle gets `lease_expired`: usage that wasn't settled is free.                                                                                                                                                              |
| `capture`              | All of what the lease still holds is charged, as if it was used. Its revenue is booked on the meter `lease.unsettled`.                                                                                                                                                                   |
| `hold_for_late_settle` | The lease becomes `expired_pending` and its funds stay reserved for `lateSettleWindowSeconds` (one day by default, at most seven). One settle in that window charges what was used and releases the rest. If none comes, `lateSettleFallback` applies: `release` (default) or `capture`. |

Choose `hold_for_late_settle` if your service keeps a durable log of its consumption and can settle after it restarts. Choose `capture` when unsettled usage must never be free, and `release` when it may be.

Ownrecord applies the policies every minute and sends a `lease.expired` [webhook](https://ownrecord.io/docs/concepts/webhooks.md) once per lease. A settle after `expiresAt` is refused even before that happens, except within a late-settle window.

## Sizing

Every lease in a response has `suggestedNextAmount`: what a lease of the same TTL would need at the rate your service is consuming now, with 25% headroom. It moves at most tenfold up or down from the current amount in one step. Pass it as `renew.amount`, or as the `amount` of your next lease, to keep leases from running out early or holding more of the wallet than they need.

## With the TypeScript SDK

The SDK's `LeaseManager` does all of this for you: it meters locally against the lease, settles every few seconds, renews before expiry with `suggestedNextAmount`, and settles with `final: true` when your service stops. With a durable store it settles a crashed process's usage late. See [Metering high-frequency usage with the SDK](https://ownrecord.io/docs/guides/lease-manager.md).

## In the ledger

A lease moves the funds from the wallet's spendable balance into its reserved balance. Settles are charged at once: they count in the lease's `captured`, its `remaining` goes down, and each usage line is recorded. The ledger books them together, once per lease: when the lease closes, is renewed or expires, what its settles charged moves from reserved to usage revenue per meter, and the remaining amount of the credit grants it came from goes down. That keeps the ledger small however often you settle, and lets thousands of settles a minute run side by side. Closing or expiring returns the rest to the account it came from: promo credits to the promo balance, other credits to the available balance. The wallet's balance always equals what its grants have left. See [the ledger](https://ownrecord.io/docs/concepts/ledger.md).
