# Read token usage

Read customer-visible traffic for one owned token.

```http
GET /api/v1/tokens/{tokenId}/usage
Authorization: Bearer lit_...
```

## Query parameters

| Parameter | Rules |
| --- | --- |
| `from` | Inclusive canonical UTC ISO-8601 timestamp. |
| `to` | Exclusive canonical UTC ISO-8601 timestamp; must be after `from`. |
| `groupBy` | `hour`, `day`, or `month`; default `day`. |
| `include` | Comma-separated `domains` and/or `charges`. `charges` requires `groupBy=hour`. |

When the range is omitted, the API uses the 30 complete UTC days before the current UTC day. Hour ranges are limited to 31 days, day ranges to 366 days, and month ranges to 36 months.

## Example

```bash
curl --get 'https://litport.net/api/v1/tokens/12345/usage' \
  -H "Authorization: Bearer $LITPORT_API_KEY" \
  --data-urlencode 'from=2026-08-01T00:00:00Z' \
  --data-urlencode 'to=2026-08-03T00:00:00Z' \
  --data-urlencode 'groupBy=day'
```

```json
{
  "data": {
    "tokenId": 12345,
    "range": {
      "from": "2026-08-01T00:00:00.000Z",
      "to": "2026-08-03T00:00:00.000Z",
      "groupBy": "day",
      "timezone": "UTC"
    },
    "trafficBasis": "customer_chargeable",
    "summary": {
      "requests": 42,
      "uploadedBytes": "12000",
      "downloadedBytes": "88000",
      "totalBytes": "100000"
    },
    "buckets": [
      {
        "start": "2026-08-01T00:00:00.000Z",
        "end": "2026-08-02T00:00:00.000Z",
        "requests": 42,
        "uploadedBytes": "12000",
        "downloadedBytes": "88000",
        "totalBytes": "100000"
      }
    ]
  }
}
```

## Usage semantics

The interval is half-open: `[from, to)`. Buckets are ordered by start time and are sparse; a missing bucket means no stored aggregate row, not an API error.

`trafficBasis` is `customer_chargeable`, so the totals match the traffic shown to the customer. Large byte totals are decimal strings so clients can preserve exact values. `requests` is a JSON integer.

The token must belong to the authenticated user. An unknown or unowned token returns the same `404 TOKEN_NOT_FOUND` response.

## Charge breakdown

For a PPG token, request `include=charges&groupBy=hour` to add the persisted charge to each hourly bucket. The expansion is rejected for unlimited tokens. A versioned charge contains the pool's public key and name, raw and charged upload/download bytes, contributing hubs and protocols, snapshotted base/effective rates and discount, and the exact amount deducted. A row without snapshots is labeled `Legacy PPG usage`; the API does not guess its pool or rate from current token settings.

Charge components are the billing record. Upload and download are both charged. A `reserved` charge can grow while late traffic for the hour arrives; a `finished` charge is final.

## Domain breakdown

Request `include=domains` to add `domainBreakdown` to `data`:

```json
{
  "domainBreakdown": {
    "limit": 150,
    "totalDestinationCount": 151,
    "displayedCount": 150,
    "truncated": true,
    "range": {
      "from": "2026-08-01T00:00:00.000Z",
      "to": "2026-08-03T00:00:00.000Z",
      "timezone": "UTC",
      "periodClamped": false,
      "endClamped": false
    },
    "items": [{
      "protocol": "tcp",
      "destination": "example.com",
      "port": 443,
      "requests": 42,
      "uploadedBytes": "12000",
      "downloadedBytes": "88000",
      "totalBytes": "100000",
      "lastSeenAt": "2026-08-01T12:00:00.000Z",
      "firstSeenAt": "2026-08-01T00:00:00.000Z"
    }],
    "other": {
      "protocol": null,
      "destination": "Other",
      "port": null,
      "requests": 1,
      "uploadedBytes": "1",
      "downloadedBytes": "2",
      "totalBytes": "3",
      "lastSeenAt": null,
      "firstSeenAt": null
    }
  }
}
```

The response includes at most the 150 destinations with the highest total traffic. Every remaining destination and telemetry overflow is combined into `other`; `truncated` reports when that grouping occurred. TCP `requests` are successful request counts and UDP `requests` are inbound datagrams. Domain data is stored as whole-hour UTC buckets and is limited to the most recent 31 days of the requested interval. The returned UTC `range` is the effective bucket interval: a past partial start is rounded down to its hour and a past partial end is rounded up to its next hour. An end clamped to the current time remains at that exact time, so the response does not claim coverage past the current time. The range also reports `periodClamped` or `endClamped` when adjusted.
