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

# Usage-Based Billing

> Understand how Cyberdesk meters and bills your usage

Cyberdesk uses usage-based billing to charge for automation runs. This page explains how billing works, what counts as billable usage, and how edge cases are handled.

## Step-Based Billing

Step-based billing is the primary billing model. You are charged based on the number of steps executed during your runs. The specific rates per agentic step and cached step are determined by your contract with Cyberdesk.

### What is a Step?

There are two types of billable steps:

<CardGroup cols={2}>
  <Card title="Agentic Steps" icon="robot">
    Each time the AI agent makes a decision and takes action. This includes:

    * Every agent iteration (reasoning + tool calls)
    * Each focused action execution
    * Each extraction prompt (after any LLM retries)

    **Note:** A batch of tool calls in a single agent turn counts as **one** agentic step.
  </Card>

  <Card title="Cached Steps" icon="bolt">
    Each time a previously-learned action is replayed from cache (trajectory replay). This includes:

    * Every step executed from a matched trajectory
    * Replayed batched tool calls count as one cached step **per tool call inside the batch**
    * Steps with `skip_cache_detection` enabled or disabled

    **Note:** Cache detection settings don't affect billing—you're billed the same whether a step uses cache detection or not. Cached steps are faster and cheaper than agentic steps.
  </Card>
</CardGroup>

### Billing by Run Outcome

What gets billed depends on how your run completes:

| Outcome                    | Steps Billed? | Description                                                  |
| -------------------------- | ------------- | ------------------------------------------------------------ |
| **Success**                | ✅ Yes         | Run completed successfully                                   |
| **User Task Failed**       | ✅ Yes         | Agent explicitly failed the task per your instructions       |
| **Cancelled**              | ✅ Yes         | You cancelled the run mid-execution                          |
| **Infrastructure Failure** | ❌ No          | Cyberdesk system error (e.g., worker crash, connection lost) |

<Info>
  **Infrastructure failures are never billed.** If our systems fail (worker crashes, connection timeouts, etc.), you won't be charged for any usage from that run attempt.
</Info>

### Understanding "User Task Failed" vs "Infrastructure Failure"

When a run ends in error, the billing outcome depends on *why* it failed:

<AccordionGroup>
  <Accordion title="User Task Failed (Billable)">
    The agent explicitly called `declare_task_failed` because:

    * The task was impossible to complete (e.g., "file not found")
    * The application was in an unexpected state
    * The user's instructions led to a dead end

    This is billable because the agent did the work of determining the task couldn't be completed.
  </Accordion>

  <Accordion title="Infrastructure Failure (Not Billable)">
    The run failed due to Cyberdesk system issues:

    * Cyberdriver became unresponsive after multiple retries
    * Worker crashed or lost connection
    * Internal service errors

    You are never charged when our infrastructure fails.
  </Accordion>
</AccordionGroup>

### Run Retries

If you retry a failed run, billing accumulates across attempts:

```
Attempt 1: 10 agentic steps, 5 cached steps (Success → billed)
Attempt 2: 3 agentic steps, 0 cached steps (Infra Failure → not billed)
Attempt 3: 7 agentic steps, 2 cached steps (Success → billed)
────────────────────────────────────────────────────────────────
Total billed: 17 agentic steps, 7 cached steps
```

Each attempt's usage is tracked separately, and the totals are cumulative. You can see per-attempt breakdowns in the run's `usage_metadata`.

### Viewing Usage Data

You can view your usage data in multiple ways through the Cyberdesk Dashboard.

#### Individual Run Usage

On any run's detail page, scroll down to the **Run Message History** section. You'll see a **Usage Data Summary** card that displays:

* Total agentic steps billed
* Total cached steps billed
* Billing outcome status (success, cancelled, etc.)

Click **View Details** to see a full breakdown including per-attempt usage for retried runs.

#### Aggregated Usage Across Runs

On the **Runs** table page, select multiple runs using the checkboxes. The toolbar will automatically display the accumulated totals:

* Total agentic steps billed across selected runs
* Total cached steps billed across selected runs

<Tip>
  Use the **Created Date** filter to narrow down runs to a specific time period, and expand **Rows per page** to see more runs at once.
</Tip>

#### API Access

Every run includes a `usage_metadata` field with detailed billing information:

```json theme={null}
{
  "billing_outcome": "success",
  "billing_reason": "Run successful - fully billed",
  "total_agentic_steps_billed": 15,
  "total_cached_steps_billed": 8,
  "total_agentic_steps": 15,
  "total_cached_steps": 8
}
```

For retried runs, you'll also see `individual_tries_metadata` with per-attempt details.

#### Programmatic Usage Data

You can programmatically retrieve aggregated usage data via the SDK. This is the same data that powers the **Billing and Usage** dashboard in Cyberdesk.

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={null}
    import { createCyberdeskClient } from 'cyberdesk';

    const client = createCyberdeskClient(process.env.CYBERDESK_API_KEY!);

    // Get usage for January 2025
    const { data: usage } = await client.usage.aggregate({
      from_date: new Date('2025-01-01'),
      to_date: new Date('2025-01-31'),
      mode: 'simulated'  // or 'billed' for customers on Stripe billing
    });

    if (usage) {
      console.log(`Period: ${usage.period_start} to ${usage.period_end}`);
      console.log(`Runs counted: ${usage.runs_counted}`);
      console.log(`Agentic steps: ${usage.total_agentic_steps}`);
      console.log(`Cached steps: ${usage.total_cached_steps}`);
    }
    ```
  </Tab>

  <Tab title="Python (Async)">
    ```python theme={null}
    from datetime import datetime
    from cyberdesk import CyberdeskClient, UsageMode
    import os

    async with CyberdeskClient(os.environ['CYBERDESK_API_KEY']) as client:
        # Get usage for January 2025
        response = await client.usage.aggregate(
            from_date=datetime(2025, 1, 1),
            to_date=datetime(2025, 1, 31),
            mode=UsageMode.SIMULATED  # or UsageMode.BILLED
        )
        
        if response.data:
            usage = response.data
            print(f"Period: {usage.period_start} to {usage.period_end}")
            print(f"Runs counted: {usage.runs_counted}")
            print(f"Agentic steps: {usage.total_agentic_steps}")
            print(f"Cached steps: {usage.total_cached_steps}")
    ```
  </Tab>

  <Tab title="Python (Sync)">
    ```python theme={null}
    from datetime import datetime
    from cyberdesk import CyberdeskClient, UsageMode
    import os

    client = CyberdeskClient(os.environ['CYBERDESK_API_KEY'])

    # Get usage for January 2025
    response = client.usage.aggregate_sync(
        from_date=datetime(2025, 1, 1),
        to_date=datetime(2025, 1, 31),
        mode=UsageMode.SIMULATED
    )

    if response.data:
        usage = response.data
        print(f"Runs counted: {usage.runs_counted}")
        print(f"Agentic steps: {usage.total_agentic_steps}")
        print(f"Cached steps: {usage.total_cached_steps}")
    ```
  </Tab>
</Tabs>

**Response fields:**

| Field                 | Description                                          |
| --------------------- | ---------------------------------------------------- |
| `total_agentic_steps` | Total agentic steps in the period                    |
| `total_cached_steps`  | Total cached steps in the period                     |
| `runs_counted`        | Number of runs included in the aggregation           |
| `period_start`        | Start of the queried period                          |
| `period_end`          | End of the queried period                            |
| `mode`                | The mode used for counting (`simulated` or `billed`) |

**Usage modes:**

* **`simulated`** (default): Uses `total_agentic_steps` and `total_cached_steps` from each run's `usage_metadata`, but excludes runs where `billing_outcome` is `infra_failure`. Use this for customers not yet on Stripe billing to see what they *would* be charged.
* **`billed`**: Uses `total_agentic_steps_billed` and `total_cached_steps_billed` — the actual amounts sent to Stripe. Use this for customers on active Stripe billing.

<Tip>
  Use this endpoint to build custom usage dashboards, automate billing reconciliation, or integrate usage data into your own systems.
</Tip>

<Warning>
  **For early 2025 customers:** Billed usage data will only appear if you have worked with the Cyberdesk team to migrate your current Stripe invoice to usage-based billing pricing. Please [contact us](mailto:team@cyberdesk.io) if you need help with the migration.
</Warning>

***

## FAQ

<AccordionGroup>
  <Accordion title="What if I cancel a run partway through?">
    You'll be billed for any steps that were executed before cancellation.
  </Accordion>

  <Accordion title="Do retries within a step count as multiple steps?">
    No. If an LLM call fails and retries internally, it still counts as one agentic step. You're only charged once the step completes (successfully or not).
  </Accordion>

  <Accordion title="Are cached steps cheaper than agentic steps?">
    Yes. Cached steps replay previously-learned actions without invoking the AI, making them faster and cheaper.
  </Accordion>

  <Accordion title="How do I know if a failure was infrastructure vs user-related?">
    Check the `billing_outcome` field in `usage_metadata`:

    * `"infra_failure"` = Infrastructure issue (not billed)
    * `"user_task_failed"` = Agent determined task couldn't be completed (billed)
  </Accordion>

  <Accordion title="Where can I see my total usage?">
    Visit the [Cyberdesk Dashboard](https://cyberdesk.io/dashboard/runs) to view your usage. You can see individual run usage in the run detail page, or select multiple runs in the runs table to see aggregated totals.
  </Accordion>
</AccordionGroup>

***

## Run-Based Billing (Legacy)

<Warning>
  Run-based billing is a legacy model. New customers use step-based billing.
</Warning>

In the legacy model, you are charged a flat fee per completed run, regardless of the number of steps.

### How It Works

A `run_completed` billing event is recorded when:

* A run completes with status `success`
* A run completes with status `error` due to explicit task failure (user-initiated via `declare_task_failed`)

A `run_completed` event is **not** recorded when:

* The run is cancelled
* The run fails due to infrastructure issues

### Legacy Usage Metadata

Legacy runs include additional fields in `usage_metadata`:

```json theme={null}
{
  "billing_outcome": "success",
  "billing_reason": "Run successful - fully billed",
  "total_run_completed_billed": 1,
  "total_agentic_steps_billed": 15,
  "total_cached_steps_billed": 8,
  "total_agentic_steps": 15,
  "total_cached_steps": 8
}
```

The `total_run_completed_billed` field indicates whether the run completion was billed (1) or not (0).
