# Get this month's usage

Source: https://docs.coderhelm.com/api/reference/usage/get-usage

`GET /api/usage`

Returns the tokens the team used this calendar month (UTC), split into new input, output, cache reads and cache writes, per feature, and against each limit the team set. When a limit is reached, endpoints that start work answer `429` with `token_limit_reached` until the month turns or an admin raises it.

## Authentication

A team API key: `Authorization: Bearer chk_...`. The key needs the `view` scope. See [Authentication](https://docs.coderhelm.com/api/authentication).

## Responses

### 200

This month's usage.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `cache_hit_rate` | number | yes | Cache reads divided by all input, from 0 to 1. |
| `cache_read_tokens` | integer | yes | Tokens read from the prompt cache. |
| `cache_write_tokens` | integer | yes | Tokens written to the prompt cache. |
| `counted_tokens` | integer | yes | What the older single limit counts (kept for older clients). |
| `features` | array of UsageFeature | yes | Usage per feature. |
| `features[].cache_read_tokens` | integer | yes | Tokens read from the prompt cache. |
| `features[].cache_write_tokens` | integer | yes | Tokens written to the prompt cache. |
| `features[].feature` | string | yes | The feature, such as `coder`, `reviewer`, `plan_chat` or `log_analyzer`. |
| `features[].tokens_in` | integer | yes | New input tokens (not from the cache). |
| `features[].tokens_out` | integer | yes | Output tokens. |
| `features[].total_tokens` | integer | yes | All four parts together. |
| `limit_counts_cache` | boolean | yes | Whether the older single limit counts cache tokens (kept for older clients). |
| `limits` | array of UsageLimit | yes | Each limit that is set, in display order. Empty when none is. |
| `limits[].kind` | string | yes | What it counts: `new_tokens` (new input and output), `cache_read`, `cache_write`, or `all_tokens` (an older single limit that counts cache too). |
| `limits[].max` | integer | yes | The limit. |
| `limits[].used` | integer | yes | What it counts so far this month. |
| `limits_legacy` | boolean | yes | True when the limits were read from the older single-limit setting. |
| `max_tokens` | integer | yes | The older single limit, 0 when it isn't used (kept for older clients). |
| `month` | string | yes | The month, `YYYY-MM` (UTC). |
| `new_tokens` | integer | yes | New input plus output: what the `new_tokens` limit counts. |
| `tokens_in` | integer | yes | New input tokens (not from the cache). |
| `tokens_out` | integer | yes | Output tokens. |
| `total_runs` | integer | yes | Runs started this month. |
| `total_tokens` | integer | yes | All tokens: new input, cache reads, cache writes and output. |

Headers: `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`.

### 401

The key is missing, malformed, revoked or expired, or the person who made it left the team.

### 403

The key lacks the scope this endpoint needs (`missing_scope`).

### 429

Over the key's rate limit (`rate_limited`), or, for endpoints that start work, over the team's monthly token limit (`token_limit_reached`).

Headers: `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, `Retry-After`.

### 500

Something failed on CoderHelm's side. Safe to retry reads.

## Example request

cURL:

```bash
curl -X GET 'https://api.coderhelm.com/api/usage' \
  -H "Authorization: Bearer $CODERHELM_API_KEY"
```

TypeScript:

```ts
const res = await fetch("https://api.coderhelm.com/api/usage", {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${process.env.CODERHELM_API_KEY}`,
  },
});
if (!res.ok) {
  const { error, code } = await res.json();
  throw new Error(`${res.status} ${code}: ${error}`);
}
const data = await res.json();
```

Python:

```python
import os
import requests

headers = {
    "Authorization": f"Bearer {os.environ['CODERHELM_API_KEY']}",
}
res = requests.request("GET", "https://api.coderhelm.com/api/usage", headers=headers)
if not res.ok:
    raise RuntimeError(f"{res.status_code}: {res.json().get('error')}")
data = res.json()
```

## Example response

```json
{
  "cache_hit_rate": 0.77,
  "cache_read_tokens": 13100400,
  "cache_write_tokens": 822392,
  "counted_tokens": 4310227,
  "features": [
    {
      "cache_read_tokens": 1900410,
      "cache_write_tokens": 151002,
      "feature": "reviewer",
      "tokens_in": 301200,
      "tokens_out": 57410,
      "total_tokens": 2410022
    }
  ],
  "limit_counts_cache": false,
  "limits": [
    {
      "kind": "new_tokens",
      "max": 20000000,
      "used": 4310227
    }
  ],
  "limits_legacy": false,
  "max_tokens": 0,
  "month": "2026-10",
  "new_tokens": 4310227,
  "tokens_in": 3011022,
  "tokens_out": 1299205,
  "total_runs": 37,
  "total_tokens": 18233019
}
```
