> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lupin.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Usage ledger and spending limits

> Durable activity records, explicit cost provenance and admission controls for new paid actions.

The **Budgets & costs** console page shows permanent activity accounting and
monthly limits for a workspace, project or agent API key. Deleting an email,
project, browser session or container does not delete its ledger entries.
`GET /v0/usage/ledger` returns product quantities, estimated and provider-confirmed
USD costs, outstanding reservations, unpriced activity and the coverage start.
`GET /v0/usage/events` exposes recent individual records.

## Coverage and cost provenance

Accounting starts when migration `0023_usage_budgets.sql` is applied. Historical
messages are never reconstructed as authoritative charges. Email delivery is
counted per recipient; inbound email/SMS per message and outbound SMS per complete
send (not per segment); proxy allocation in
MB; browser/container/call runtime in seconds. Runtime observations can be upper
bounds when the provider's exact termination time is unavailable.

Every amount is integer microUSD (`1 USD = 1,000,000 micros`). Activity without a
verified unit rate remains **unpriced**, not zero cost. No price is hardcoded.
Configure the operator-only `USAGE_VERIFIED_RATES_JSON` binding with verified
maximum unit charges from the appropriate provider contract:

```json theme={null}
{
  "email.sent": {
    "unit_cost_micros": 100,
    "currency": "USD",
    "source": "EXAMPLE ONLY: replace with your verified provider rate source",
    "verified_at": "2026-10-25T00:00:00Z"
  }
}
```

The number above is an example, not a Lupin or provider price. Operators must
verify destination, carrier, segment and other applicable fees when determining
a safe maximum rate. For `sms.sent`, the configuration additionally requires
`rate_basis: "max_total_send_cost_including_segments_media_and_all_destinations"`.
Its `unit_cost_micros` must bound the **entire send**: the maximum accepted
1,600-character input including Unicode, all resulting segments, up to ten media
URLs, carrier fees and every destination the workspace can send to. A per-segment
or base-message price is insufficient. Missing or different `rate_basis` keeps
SMS activity unpriced and blocks new sends under a matching spending limit.
Lupin does not guess segment counts, destination rates or media surcharges. Configured amounts are labeled `configured_estimate`.
Signed Telnyx `message.finalized` callbacks can replace SMS estimates with the
provider's reported USD `cost.amount`, labeled `provider_confirmed`. Other
currencies, absent amounts and unsupported precision remain unpriced; no
exchange rate or missing fee is invented. Subscription invoices and recurring
provider fees are separate, so the summary explicitly remains partial.

## Limits and alerts

`POST /v0/budgets` accepts `scope_type` (`workspace`, `project`, `api_key`), a
`scope_id` for project/key scopes and positive integer `limit_micros`.
`GET /v0/budgets` lists spent/reserved amounts, unknown activity and durable
80%/100% threshold alerts. `DELETE /v0/budgets/:budget_id` disables a limit;
existing history remains. Management requires a workspace key with
`api_key_create`. Financial reads require `api_key_read`; project-scoped keys
only see their project and cannot change budgets. Inbox keys are rejected.

Limits reset by UTC calendar month. Outstanding reservations from earlier
months continue counting until resolved. Unattributed activity conservatively
counts toward matching project/key limits, including scheduled work whose
original agent identity is unavailable. This prevents missing attribution from
bypassing an agent's limit.

Admission checking and reservation insertion happen in one serialized SQL
statement, so concurrent isolates cannot both spend the same remaining budget.
A definitive provider rejection releases the reservation. Timeouts and unknown
outcomes keep it until provider reconciliation; retries never silently issue
another paid action. Known provider acceptance can recover the local resource
projection without repeating the external operation. Browser creation requires
an `Idempotency-Key`, as do the other journaled paid resource mutations.

An active matching limit blocks unpriced paid actions. Browser/call/container
runtime and number recurring charges currently have no enforceable maximum
charge in Lupin's adapters, so new allocations/resumes are blocked under a cap.
A limit cannot be enabled around outstanding unpriced or unbounded activity.
These limits gate **new actions using verified estimates**; they do not promise
that an invoice cannot exceed the cap. Existing running resources, inbound
traffic and recurring provider charges are not automatically stopped. Reads,
known-result recovery and cleanup/hangup/stop actions remain available.

## Signed phone callbacks

Set `TELNYX_PUBLIC_KEY` to the account's base64 Ed25519 webhook signing key.
Without this binding, Lupin retrieves the account key over authenticated
`GET https://api.telnyx.com/v2/public_key` using `TELNYX_API_KEY`, cached for five
minutes. Missing/unavailable verification returns 503; missing, stale or invalid
signatures return 401 before processing. The signature covers the exact
`timestamp|raw_body` bytes and accepts a five-minute timestamp window. See
[Telnyx webhook signing](https://support.telnyx.com/en/articles/4334722-how-to-leverage-webhooks).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.