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

# Report usage

> Report billable usage for Distribution Platform inference so Baseten can bill customers and calculate your proceeds.

Baseten meters standard token-based traffic at the Distribution Platform
inference gateway. Report usage that only your model can measure, such as usage
from streaming, WebSocket, or custom protocol traffic, with the Usage Reporting
API.

For each inference request attributed to a Distribution Platform customer,
Baseten sends a signed identity token in the `X-Baseten-Identity-Token` header.
Copy that token exactly into each usage event. Baseten injects the reporting URL
into your model container as the `BASETEN_USAGE_ENDPOINT` environment variable.

## Report one usage event

<Tabs>
  <Tab title="cURL">
    **To report one token-usage event with cURL**:

    Set `BASETEN_IDENTITY_TOKEN` to the exact value of the
    `X-Baseten-Identity-Token` header from a distribution-attributed request.
    Set `ts` to the RFC 3339 timestamp when the usage occurred. Set each usage
    value to the measured, non-negative delta for this event, not a cumulative
    total.

    <CodeGroup>
      ```bash Request theme={"system"}
      curl --silent --show-error \
        --request POST \
        --url "$BASETEN_USAGE_ENDPOINT" \
        --header "Content-Type: application/json" \
        --data '{
          "events": [
            {
              "identity_token": "'"$BASETEN_IDENTITY_TOKEN"'",
              "ts": "2026-07-28T12:00:00Z",
              "usage": {
                "uncached_input_tokens": 9273,
                "cached_input_tokens": 5,
                "output_tokens": 703
              }
            }
          ]
        }'
      ```

      ```json Response theme={"system"}
      {
        "accepted": 1,
        "rejected": 0
      }
      ```
    </CodeGroup>
  </Tab>

  <Tab title="Python">
    **To smoke-test a standalone reporting helper with Python**:

    Set `BASETEN_IDENTITY_TOKEN` to the exact identity token from a
    distribution-attributed request before running this standalone script. The
    script passes the environment-variable value to `report_usage`; it does not
    read request headers. The helper constructs the event once, then retries
    that same payload and timestamp up to three times with backoff for `429` and
    `5xx` responses.

    <CodeGroup>
      ```python report_usage.py theme={"system"}
      import json
      import logging
      import os
      from typing import Optional

      import requests
      from requests.adapters import HTTPAdapter
      from urllib3.util import Retry

      logger = logging.getLogger(__name__)
      USAGE_ENDPOINT = os.environ["BASETEN_USAGE_ENDPOINT"]

      retry = Retry(
          total=3,
          backoff_factor=0.5,
          status_forcelist=(429, 500, 502, 503, 504),
          allowed_methods=frozenset({"POST"}),
          respect_retry_after_header=True,
          raise_on_status=False,
      )
      adapter = HTTPAdapter(max_retries=retry)
      session = requests.Session()
      session.mount("http://", adapter)
      session.mount("https://", adapter)


      def report_usage(
          identity_token: str,
          ts: str,
          usage: dict[str, int],
      ) -> Optional[dict]:
          event = {
              "identity_token": identity_token,
              "ts": ts,
              "usage": usage,
          }

          try:
              response = session.post(
                  USAGE_ENDPOINT,
                  json={"events": [event]},
                  timeout=2,
              )
              response.raise_for_status()

              result = response.json()
              if result["rejected"]:
                  logger.warning("Usage event rejected: %s", result["results"])
              return result
          except (requests.RequestException, KeyError, ValueError) as error:
              logger.warning("Usage reporting failed after retries: %s", error)
              return None


      if __name__ == "__main__":
          result = report_usage(
              identity_token=os.environ["BASETEN_IDENTITY_TOKEN"],
              ts="2026-07-28T12:00:00Z",
              usage={
                  "uncached_input_tokens": 9273,
                  "cached_input_tokens": 5,
                  "output_tokens": 703,
              },
          )
          print(json.dumps(result, indent=2))
      ```

      ```json Response theme={"system"}
      {
        "accepted": 1,
        "rejected": 0
      }
      ```
    </CodeGroup>
  </Tab>
</Tabs>

In a production handler, pass the per-request
`X-Baseten-Identity-Token` value to `report_usage` after inference succeeds.
If the header is absent, skip usage reporting for that request. The helper logs
the final failure without failing inference. Monitor this warning so that
persistent reporting failures don't leave usage unreported.

## Use supported metrics

Every usage value is a non-negative integer delta for that event, not a
cumulative total.

| Metric                  | Unit       | Event requirements                                                       |
| ----------------------- | ---------- | ------------------------------------------------------------------------ |
| `uncached_input_tokens` | Tokens     | Can be combined with other token metrics. Defaults to zero when omitted. |
| `cached_input_tokens`   | Tokens     | Can be combined with other token metrics. Defaults to zero when omitted. |
| `output_tokens`         | Tokens     | Can be combined with other token metrics. Defaults to zero when omitted. |
| `input_characters`      | Characters | Use this as the event's only metric.                                     |
| `audio_seconds`         | Seconds    | Use this as the event's only metric.                                     |
| `image_generations`     | Images     | Use this as the event's only metric.                                     |

A token event includes one or more of `uncached_input_tokens`,
`cached_input_tokens`, and `output_tokens`. You can combine token fields, and
omitted token fields default to `0`. A non-token event uses exactly one of
`input_characters`, `audio_seconds`, or `image_generations`.

Send separate events for token usage and for each non-token metric type. Baseten
sums the deltas from all accepted events for a request or session.

## Batch events

A batch can contain events from multiple distribution-attributed inference
requests. Each event carries the identity token from its corresponding request.

**To inspect partial acceptance in a two-event batch**:

Set `FIRST_BASETEN_IDENTITY_TOKEN` from a distribution-attributed request. This
integration example deliberately uses an invalid identity token for the second
event:

<CodeGroup>
  ```bash Request theme={"system"}
  SECOND_BASETEN_IDENTITY_TOKEN="invalid-token"

  curl --silent --show-error \
    --request POST \
    --url "$BASETEN_USAGE_ENDPOINT" \
    --header "Content-Type: application/json" \
    --data '{
      "events": [
        {
          "identity_token": "'"$FIRST_BASETEN_IDENTITY_TOKEN"'",
          "ts": "2026-07-28T12:00:00Z",
          "usage": {
            "uncached_input_tokens": 9273,
            "cached_input_tokens": 5,
            "output_tokens": 703
          }
        },
        {
          "identity_token": "'"$SECOND_BASETEN_IDENTITY_TOKEN"'",
          "ts": "2026-07-28T12:00:05Z",
          "usage": {
            "audio_seconds": 42
          }
        }
      ]
    }'
  ```

  ```json Response theme={"system"}
  {
    "accepted": 1,
    "rejected": 1,
    "results": [
      {
        "index": 1,
        "status": "rejected",
        "error": "invalid identity token"
      }
    ]
  }
  ```
</CodeGroup>

The endpoint validates events independently.

A `200 OK` response means the endpoint processed the request envelope, but it
may still reject some events. Check
`rejected` and use each entry's `index` in `results` to identify rejected
events.

`results` contains only rejected events. A `400 Bad Request` response means the
request envelope is invalid, such as malformed JSON or an `events` value that
isn't an array. The endpoint processes no events.

## Retry events

In production integrations, always include `ts` and format it as RFC 3339. It
records when the usage occurred and participates in deduplication. Reuse the
exact original `ts` on every retry. If an event omits `ts`, the server uses its
receive time; retrying that event isn't idempotent and may double-bill the same
usage.

After partial acceptance, resend only the rejected events. Don't resend
accepted events as part of the retry.

## Limits

The JSON request body must not exceed 1 MiB. The endpoint rejects unknown
fields: unknown envelope fields invalidate the request, while unknown event
fields reject that event independently.

## Next steps

* **[Insights](/labs/platform/insights)**: Review customers, models, and
  estimated gross proceeds associated with accepted usage.
* **[Manage your model](/labs/platform/manage)**: Complete the other
  requirements before your listing goes live.
