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

# Attribute authoritative Usage

> Attribute metered work to a Principal, query authoritative Usage, and enforce Budgets without relying on traces.

Use a **Principal** to attribute an Agent's work to one of your end users or
services. Your backend authenticates the user and selects the authorized
Principal, then passes its ID as `acted_as` when creating the Session.
Checkfu validates that delegation at admission. Keep API keys server-side;
do not forward an unchecked Principal ID from a browser or model.

<Note>
  Usage is `alpha` and intended for the hosted control plane, but live
  readiness is deployment- and Workspace-specific. Check
  [capability status](/getting-started/status) before making Usage or Budget
  availability part of your application's contract.
</Note>

<Note>
  Plain HTTP against the Checkfu API needs no private package.
  The documented path is usable as written for an admitted Workspace.
  Confirm [capability status](/getting-started/status) before making availability part of your application's contract.
</Note>

## Create a Session for a Principal

Set `CHECKFU_PRINCIPAL_ID` to an active Principal in the API key's Workspace.
That Principal needs effective `act_as` permission on the selected Agent.
The Agent also needs permission to use `CHECKFU_ENVIRONMENT_ID`. See
[Session identity](/reference/access#session-identity) and
[Permissions](/concepts/tenancy-and-governance) for setup and delegation checks.

Choose a unique idempotency key for this logical Session; `usage-session-482`
below is an example. Keep that key and the complete request body unchanged
when retrying, including after a lost response. Use a new key only to create
a separate Session.

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl --fail-with-body --request POST https://api.checkfu.com/v1/sessions \
  --header "Authorization: Bearer $CHECKFU_API_KEY" \
  --header "Checkfu-Version: 2026-08-31" \
  --header "Idempotency-Key: usage-session-482" \
  --header "Content-Type: application/json" \
  --data '{
    "agent": {
      "type": "agent",
      "id": "'"$CHECKFU_AGENT_ID"'"
    },
    "environment_id": "'"$CHECKFU_ENVIRONMENT_ID"'",
    "acted_as": "'"$CHECKFU_PRINCIPAL_ID"'"
  }'
```

A Workspace-key Session with authorized `acted_as` retains that Principal for
Usage attribution and Principal-scoped Budgets. Without `acted_as`, a direct
Workspace-key Session has no Principal attribution. If the Agent has governed
Connection bindings, omitting `acted_as` is refused. An unknown, inactive, or
unauthorized Principal is also refused with `403 policy.denied`.

Delegation does not change the API key's Workspace or grant access to a
Connection. Resource permissions, policy, approval, and current authority still
apply. The unsupported `principal` body field remains rejected with
`400 validation.malformed`; use the authorized `acted_as` field instead.

The Session freezes the selected AgentVersion and Environment. Its Runs,
governance decisions, Audit records, and Usage facts retain the same
attribution lineage.

## Read authoritative Usage

`GET /v1/usage` returns immutable metering facts. Filter by the dimensions
defined by the current wire contract, including Principal, Agent, surface,
Automation, Session, and Run, and follow the opaque `next_page` cursor.

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl --get "https://api.checkfu.com/v1/usage" \
  --header "Authorization: Bearer $CHECKFU_API_KEY" \
  --header "Checkfu-Version: 2026-08-31" \
  --data-urlencode "principal_id=$CHECKFU_PRINCIPAL_ID" \
  --data-urlencode "limit=100"
```

Each row contains one measurement kind:

| Measurement | Authoritative fact |
| - | - |
| Model | Provider-reported counters normalized into the model Usage contract, including authoritative `total_tokens` |
| Model units | Provider-reported usage in the admitted unit dimension, such as images or media duration |
| Session runtime | Exact closed running intervals, with the retained producer version identifying their accounting semantics |
| Sandbox compute | Observed active compute used for unit economics |
| Snapshot retention | Observed retained storage over time |
| Governed web search | Requests counted at the governed search dispatch boundary, rather than inferred from a transcript |
| Managed Tool | Original invocation, parent, frozen customer price and billing basis, and recorded result or failure outcome |

These are customer wire variants, not a promise that every capability is available
to your Workspace. Managed Tool supplier costs stay in internal accounting and
are omitted from the customer Usage response. A recorded measurement is separate
from its charge and payment; see [Billing and Usage](/concepts/billing-and-platform-supply).

For Session runtime, producer versions 2 and 3 record the union of the Session's
running intervals. Overlapping Runs in one Session count once; different Sessions
count separately. Retained version 1 facts use historical per-Run intervals and
are not rewritten into union facts.

Native runtime uses producer version 3 and placement `cloudflare_durable_object`.
Its Usage retains the actual Run with `attempt: null`; its matching runtime charge
retains that Run with `attempt_id: null`. A null attempt does not mean that the work
was unpriced or unrecorded. The runtime charge's formula and amount remain separate
from Usage and from supplier compute costs. This wire contract does not establish
that runtime billing is enabled for your Workspace.

Lightweight Check calls use the same model measurement. Their `evaluation`
field identifies the owning parent and operation slot; `run` and `attempt`
are null. Session and Agent attribution is present only when the evaluation
belongs to an existing Session. A standalone classification does not create
an Agent Run just to account for model usage.

Supply classification, candidate identity, provider counters, rate identity,
and monetary facts are server-owned fields. Do not rebuild them from model
messages or client labels.

## Read the charge for a Usage fact

Use the original Usage row's `id` to read its retained customer charge:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl --get "https://api.checkfu.com/v1/usage/$CHECKFU_USAGE_ENTRY_ID/charge" \
  --header "Authorization: Bearer $CHECKFU_API_KEY" \
  --header "Checkfu-Version: 2026-08-31"
```

The response binds `usage_entry_id` to its `charge`, linked `corrections`, and
optional billing `projection`. A charge retains its original pricing identity,
amount in micro-USD, and fractional remainder. It does not select today's rate or
expose supplier credentials or supplier invoices.

Corrections are paginated separately: pass `corrections.next_page` as the opaque
`page` query parameter on this same route; `limit` accepts 1–100. A correction
retains the original charge id, absolute target amount, and signed adjustment.
It does not overwrite the original charge or establish a completed cash refund.

`charge: null` means no customer charge is present in this readback; it does not
establish that all work was free. BYOK removes managed-model charges, while runtime
and separately priced tools follow their own terms. A projection's mutable
`state` describes Autumn delivery, not invoice or payment completion. Check live
[capability status](/getting-started/status) before relying on deployment readiness.

## Read Usage series coverage

Usage series separate metering totals from monetary totals. The
`spend_coverage` fields are coverage counts, not dollars or token counts:

| Field | Meaning |
| - | - |
| `charged` | Model Usage facts linked to a retained customer charge |
| `unpriced` | Model Usage whose measurement has no price coverage |
| `byok` | Model Usage classified as using a customer credential |
| `unknown` | Model Usage whose supply or matching customer charge remains unresolved |

These counters describe model coverage; they are not a census of every runtime,
tool, or storage fact. A priced measurement can remain `unknown` until its
customer charge is linked. BYOK excludes managed-model charges, not unrelated
platform charges. Coverage does not establish payment or supplier settlement.

A Usage bucket has `spend_status: partial` when its projection is partial or it
contains unpriced or unknown coverage. Otherwise it is `complete` when charged
coverage exists, and `not_applicable` when it does not. Monetary buckets expose
`complete` or `partial` separately. Missing money is not proof of zero spend;
check coverage and projection freshness before interpreting totals.

With `group_by: agent_definition`, the `group` value is the immutable Agent id,
not an Agent version id or display name. `none` means the fact has no Agent
attribution; `not_applicable` means a dimension does not describe that fact.

Failures, cancellation, and later erasure do not delete work that was actually
metered. Principal erasure removes direct Principal attribution and replaces it
with a generated subject reference. Retained accounting identifiers and links to
the Workspace, Session or Run may remain identifiable or pseudonymous; historical
accounting facts and Workspace totals are preserved.

## Read time series

`GET /v1/usage/series` returns server-owned UTC-day buckets for its bounded
range. Spend and Usage are separate projections. Treat a partial watermark,
incomplete result, or partial spend status as **known data**, not as zero and
not as a complete invoice.

The route combines qualified rollups with a bounded raw tail. It fails closed
when the required projection cannot be established; it does not silently ask
the client to scan an unbounded history. Use the generated API reference for
the current grouping values rather than persisting a retired resource name in
your product model.

## Usage, traces, and invoices

| Surface | Authority |
| - | - |
| Usage ledger | Metering and Budget settlement |
| Budget reservation | Capacity held before admitted work |
| Commercial ledger | Entitlement, payment, and invoice state |
| Trace | Diagnostic projection only |

A trace can be useful for debugging latency or model behavior. It cannot
enforce a Budget, quota, bill, PermissionAssignment, ActionPolicy, or
ActionApproval. Missing trace spans do not reduce Usage, and duplicate-looking
trace spans do not create Usage.

## Enforce a Principal Budget

A Principal-scoped Budget applies the same limit to every Session attributed to
that Principal.

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl --request POST https://api.checkfu.com/v1/budgets \
  --header "Authorization: Bearer $CHECKFU_API_KEY" \
  --header "Checkfu-Version: 2026-08-31" \
  --header "Content-Type: application/json" \
  --data '{
    "scope": {
      "kind": "principal",
      "principal_id": "'"$CHECKFU_PRINCIPAL_ID"'"
    },
    "metric": "model_tokens",
    "window": { "kind": "calendar_month" },
    "soft_threshold": {
      "limit": 800000,
      "action": "notify"
    },
    "hard_threshold": {
      "limit": 1000000,
      "breach_action": "block_admission"
    }
  }'
```

The soft threshold must be below the hard threshold. Current Budget metrics
include:

| Metric | Unit |
| - | - |
| `model_tokens` | Normalized model tokens |
| `model_spend` | Integer micro-USD |
| `session_runtime_ms` | Running milliseconds |
| `total_spend` | Customer-billable spend, with thresholds in integer micro-USD |

`model_spend` tracks model cost where price coverage is available, including
Usage with a Workspace credential. These costs can differ from the customer charge.
Use `total_spend` for customer-billable spend; admission also counts unresolved
original customer exposure. BYOK excludes managed-model charges from this total,
while runtime and separately priced tools follow their own admitted terms.
Neither metric establishes supplier payment or customer invoice payment.

A hard threshold can block admission. Where the typed Budget action permits it,
the configuration can also interrupt an in-flight turn. Reservation and
settlement use the authoritative Usage path, not traces.

Admission checks also account for unresolved original customer exposure where
needed to preserve the cap. This held capacity is not an invoice, charge or
payment. Matching original financial settlement replaces the exposure; an
expired execution lease alone does not establish that the work was free.

`429 budget.exceeded` is a shared capacity error. It can represent a Budget,
Workspace quota, ToolInvocation ceiling, or API-key rate limit. Present it as
"limit reached" unless the structured response identifies the exact source.

## Keep the gates separate

| Gate | Error | Who can resolve it |
| - | - | - |
| Customer Budget or quota | `budget.exceeded` | Workspace administrator |
| Commercial entitlement | `billing.usage_limit_reached` | Organization administrator |
| Payment state | `billing.payment_required` | Organization administrator |
| Platform model capacity | `model.platform_capacity_reached` | Operator, or use an admitted Workspace credential |

Remaining Budget does not grant permission. Permission does not extend
commercial entitlement. Every applicable gate must allow the work.

## Erasure boundary

Usage can retain identifiable or pseudonymous accounting facts after a direct
Principal link is removed. Generated subject references and retained Workspace,
Session, Run, and original accounting identifiers do not establish anonymity.
That is distinct from retaining Session content. Current end-to-end
erasure completion is not fully established across every sink and in-flight
release; see
[Retention and zero-data retention](/concepts/retention-and-zdr) before using
Usage export as evidence that a data-subject workflow is complete.


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