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

# Track usage and cost

> Read what a session cost, including its helper agents, tools, and sandbox compute, and token usage for many sessions at once.

Every session has one cost: what your credit balance is charged for its whole session tree. It covers the session and every subagent and teammate it started, and all of their model calls, provider tools such as a provider's web search, and sandbox compute. Read it in the console or as `costUsd` on the session, and use `costState` to tell a final cost from one that can still grow.

<Note>
  Any organization role that can read sessions can read their cost: user, developer, or admin. The billing role cannot see sessions. See [Organizations and roles](/recursion/organizations-and-roles) and [API keys](/recursion/api-keys). Credits are bought separately on the **Billing** screen; see [Billing](/recursion/billing).
</Note>

<Tip>
  To estimate cost before a session, open an agent in the console. Its **Estimated cost per session hour** section shows what one session hour typically costs, priced on the compute you choose. Pick a model first to see an estimate. [Pricing](/recursion/pricing) explains what that price covers.
</Tip>

| Question | Operation |
| - | - |
| What did this session cost, and is that final? | `getSession` |
| What did each run in a list cost? | `listSessions` with `root_only=true` |
| How many events and tokens did each session in a list use? | `listSessionUsage` |

## Read one session's cost

`getSession` returns `costUsd` and `costState` with the rest of the session, in both the `full` and `summary` views.

<Tabs>
  <Tab title="Console">
    The console shows one figure for the whole session tree: the session and every subagent and teammate under it.

    1. In **Sessions**, read the **Cost** column.
    2. Open the session. The session header and the **Session** tab of its details show the same **Cost**.
    3. While the figure can still change, it reads **so far**. Session costs can take up to an hour to settle.
  </Tab>

  <Tab title="cURL">
    ```bash theme={"theme":"css-variables"}
    curl 'https://api.recursion.labelbox.com/managed-agents/v1/sessions/b7e1c9a4-3d62-4f15-8a07-5c2e9f6d1b38?view=summary' \
      -H "Authorization: Bearer $RECURSION_API_KEY"
    ```
  </Tab>
</Tabs>

Some fields are omitted from this response.

```json theme={"theme":"css-variables"}
{
  "session_id": "b7e1c9a4-3d62-4f15-8a07-5c2e9f6d1b38",
  "root_session_id": "b7e1c9a4-3d62-4f15-8a07-5c2e9f6d1b38",
  "session_path": "/",
  "status": "completed",
  "execution_state": "idle",
  "stop_reason": "end_turn",
  "costUsd": "1.234567",
  "costState": "final"
}
```

Record `costUsd` once `costState` is `final` (see [Know when a figure is final](#know-when-a-figure-is-final)).

<Accordion title="Cost fields">
  | Field | Description |
  | - | - |
  | `costUsd` | The billed cost of the whole session tree in US dollars: model calls, tools, and sandbox compute. This is what your balance is charged. Compute that is still running is included as an estimate. |
  | `costState` | `final` or `so_far`. Present exactly when `costUsd` is. |

  A subagent or teammate session returns the cost of its whole tree, the same figure as its root. The cost is one total; it is not split by session, model call, or kind of charge.

  Both fields are absent when the cost can't be read right now. An absent cost is not zero; read the session again later.
</Accordion>

## Compare many sessions

Rows from `listSessions` carry `costUsd` and `costState` too. Send `root_only=true` to get one row per run. A child session repeats its tree's cost, so adding child rows counts the same cost twice.

<Tabs>
  <Tab title="cURL">
    ```bash theme={"theme":"css-variables"}
    curl 'https://api.recursion.labelbox.com/managed-agents/v1/sessions?root_only=true&limit=50' \
      -H "Authorization: Bearer $RECURSION_API_KEY"
    ```
  </Tab>
</Tabs>

For token counts, `listSessionUsage` takes `session_ids`, a comma-separated list of up to 1000 ids.

<Tabs>
  <Tab title="cURL">
    ```bash theme={"theme":"css-variables"}
    curl 'https://api.recursion.labelbox.com/managed-agents/v1/sessions/usage?session_ids=b7e1c9a4-3d62-4f15-8a07-5c2e9f6d1b38,0c6f2b9e-4d17-4a38-b5e2-9f1a3c7d8e06' \
      -H "Authorization: Bearer $RECURSION_API_KEY"
    ```
  </Tab>
</Tabs>

```json theme={"theme":"css-variables"}
{
  "session_usage": [
    {
      "session_id": "b7e1c9a4-3d62-4f15-8a07-5c2e9f6d1b38",
      "event_count": 214,
      "input_tokens": 182340,
      "output_tokens": 9215,
      "cache_read_tokens": 140112,
      "cache_write_tokens": 21480,
      "cost_micros": 420000
    }
  ]
}
```

<Accordion title="Usage rows">
  * `listSessionUsage` returns `session_usage`: the event count and token counts for each session's own events. Children are not included. Unknown ids and sessions with no events are left out, so compare the number of rows with the number of ids you sent.
  * `cost_micros` is the cost the session's own model events reported, in millionths of a US dollar. It is for diagnostics, not what your balance is charged: it leaves out child sessions and sandbox compute. Use `costUsd` on the session for what you are charged.
</Accordion>

## Know when a figure is final

| `costState` | Meaning |
| - | - |
| `so_far` | The cost can still grow. |
| `final` | The session has ended, its sandbox has stopped, and every charge has settled. `costUsd` won't change unless you resume the session. |

<Accordion title="Why a cost can still grow">
  1. **The session is still running.** The session or one of its subagents or teammates is working or waiting for you.
  2. **The sandbox is still running.** A sandbox can keep running after the session ends, until the environment's idle stop. Its compute is included as an estimate until it stops.
  3. **Charges are still settling.** Session costs can take up to an hour to settle.
  4. **You resumed the session.** A message that starts a new turn makes a `final` cost `so_far` again.
</Accordion>

`costUsd` is an exact decimal string, such as `"1.234567"`. Add costs with a decimal type, such as `Decimal` in Python or a decimal library in TypeScript. Floating-point sums drift.

<Accordion title="Amount format">
  * All amounts are in US dollars. No other currency is used.
  * `costUsd` has up to nine decimal places and no trailing zeros. A zero cost is `"0"`.
  * `cost_micros` in usage rows is an integer in millionths of a dollar.
</Accordion>

## What can go wrong

The most common problems:

* **The cost changed after you recorded it.** `costState` was `so_far`. Record the cost once it is `final`.
* **A list adds up to more than the runs cost.** Child rows repeat their tree's cost. Send `root_only=true`.
* **Usage `cost_micros` and `costUsd` differ.** `cost_micros` covers only the session's own model events and is for diagnostics. Use `costUsd`.

<Accordion title="Every usage and cost error">
  | Symptom or code | Cause | Fix |
  | - | - | - |
  | `costUsd` and `costState` are missing | The cost can't be read right now. | Read the session again later. Don't treat it as zero. |
  | The cost changed after you recorded it | `costState` was `so_far`: the session, its sandbox, or its charges hadn't settled, or it was resumed. | Record the cost once `costState` is `final`. See [Know when a figure is final](#know-when-a-figure-is-final). |
  | A list adds up to more than the runs cost | Child rows repeat their tree's cost. | Send `root_only=true` and add root rows only. |
  | Usage `cost_micros` and `costUsd` differ | `cost_micros` covers only the session's own model events and is for diagnostics. | Use `costUsd`. |
  | `400 invalid_request` on `session_ids` | The list is missing or has more than 1000 ids. | Split the list into batches of 1000. |
  | `listSessionUsage` returns fewer rows than ids | Unknown ids and sessions with no events are left out. | Match rows by `session_id`. |
  | `404 not_found` | The session does not exist or is outside your organization. | Check the id and your API key's organization. |
  | `429 rate_limit_exceeded` | Too many requests. | Wait for the time in `Retry-After`, then retry. |

  The full list of codes is in [Errors](/recursion/errors).
</Accordion>

## Limits

| Limit | Value |
| - | - |
| Ids in one `listSessionUsage` request | 1000 |
| Time for a session's cost to settle | Up to an hour |

Every other limit is on [Limits](/recursion/limits).

## Next steps

<CardGroup cols={2}>
  <Card title="Billing" href="/recursion/billing">
    Buy the credits that session costs are charged to.
  </Card>

  <Card title="Teams" href="/recursion/teams">
    See why a team costs more than one agent.
  </Card>

  <Card title="Multi-agent" href="/recursion/multi-agent">
    Understand the session trees behind one session cost.
  </Card>

  <Card title="Limits" href="/recursion/limits">
    Check quotas and request limits.
  </Card>
</CardGroup>
