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 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. One customer can have both, on different meters.
Lease
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
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, with its amount.
After the charge, the lease:
- stays open when you send neither
finalnorrenew. 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.amountandrenew.ttlSecondschange its size and length. Renew beforeexpiresAt. If the wallet has less than the amount, the new lease gets what there is;renewedLeaseis 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 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.
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.