# Check usage

> Usage of your key or team member by model and date, from /v1/usage or the OpenAI legacy usage endpoint.

Usage of your API key, or of every key of its team member, by model and date. `GET /v1/dashboard/billing/usage` returns the key's all-time usage in the OpenAI legacy format.

## Method and path

`GET /v1/usage`

`GET /v1/dashboard/billing/usage`

Base URL `https://api.relayvia.dev/v1`. Send the key as `Authorization: Bearer sk-...`.

## Common parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `start` | `integer \| string` | No | Start time, Unix seconds or RFC 3339. Default: 24 hours before `end`. Rounded down to the hour. |
| `end` | `integer \| string` | No | End time (exclusive), Unix seconds or RFC 3339. Default: now. Rounded up to the hour; at most 31 days after `start`. |
| `model` | `string` | No | Comma-separated model names, up to 50; exact match, case-insensitive. |
| `group_by` | `string` | No | `none` (default), `model`, `date` or `model,date`. |
| `tz` | `string` | No | IANA time zone for `date` grouping and the times in the response. Default `UTC`. |
| `scope` | `string` | No | `key` (default) for this key, or `member` for every key of the team member who owns it. |

## Differences from the original API

- Numbers come from hourly totals, so `approximate` is always true and `done_through` says up to when the totals are complete; usage after that is not counted yet, which is not the same as zero. For exact charges, use the ledger on the console's Billing page.
- Read-only and free, with the same limit of 60 requests per minute per key as `/v1/balance`. Invalid parameters return 400 `invalid_request` with `param` naming the field; a range longer than 31 days is reported on `start`.
- The legacy endpoint returns `total_usage` in US cents for the key's whole lifetime and ignores `start_date` and `end_date`.

## Request examples

**cURL**

```bash
curl "https://api.relayvia.dev/v1/usage?group_by=model&tz=Asia/Taipei" \
  -H "Authorization: Bearer sk-..."
```

**Python**

```python
import requests

resp = requests.get("https://api.relayvia.dev/v1/usage", headers={"Authorization": "Bearer sk-..."}, params={"group_by": "model", "tz": "Asia/Taipei"})
print(resp.json())
```

**JavaScript**

```javascript
const resp = await fetch("https://api.relayvia.dev/v1/usage?group_by=model&tz=Asia/Taipei", {
  headers: { Authorization: "Bearer sk-..." },
});
console.log(await resp.json());
```

## Response examples

| Field | Type | Description |
| --- | --- | --- |
| `total` | `object` | Totals over the whole range. |
| `items` | `array` | One row per `group_by` value, with `model` and `date` (`YYYY-MM-DD` in `tz`) as grouped, sorted by `amount_usd` from high to low. Empty when `group_by` is `none`. |
| `amount_usd` | `number` | Amount charged, in US dollars. Failed requests are free. |
| `requests` | `integer` | Successful requests. |
| `failed_requests` | `integer` | Failed requests, not charged. |
| `done_through` | `string` | The time up to which the totals are complete. |

**Response**

```json
{
  "object": "usage",
  "scope": "key",
  "start": "2026-11-03T00:00:00+08:00",
  "end": "2026-11-04T00:00:00+08:00",
  "tz": "Asia/Taipei",
  "group_by": "model",
  "approximate": true,
  "done_through": "2026-11-03T23:00:00+08:00",
  "total": {
    "amount_usd": 3.12,
    "requests": 120,
    "failed_requests": 0,
    "prompt_tokens": 216000,
    "completion_tokens": 50400,
    "cache_read_tokens": 108000,
    "cache_write_tokens": 0,
    "reasoning_tokens": 0
  },
  "items": [
    {
      "model": "claude-opus-5",
      "amount_usd": 2.4,
      "requests": 80,
      "failed_requests": 0,
      "prompt_tokens": 144000,
      "completion_tokens": 33600,
      "cache_read_tokens": 72000,
      "cache_write_tokens": 0,
      "reasoning_tokens": 0
    },
    {
      "model": "gpt-5.5",
      "amount_usd": 0.72,
      "requests": 40,
      "failed_requests": 0,
      "prompt_tokens": 72000,
      "completion_tokens": 16800,
      "cache_read_tokens": 36000,
      "cache_write_tokens": 0,
      "reasoning_tokens": 0
    }
  ]
}
```

**OpenAI legacy format**

```json
{
  "object": "list",
  "total_usage": 3120
}
```

## Errors this endpoint returns

| HTTP | code | When |
| --- | --- | --- |
| `400` | `invalid_request` | A parameter is invalid. If the model rejected it, the message is this sentence, or `Invalid value for parameter <param>.` with `param` set. |
| `401` | `invalid_api_key` | The API key does not exist, is disabled or has expired. |
| `403` | `forbidden` | The key may not use this model, the source IP is not on the allowlist, or the account is disabled. |
| `429` | `rate_limited` | Too many requests: per IP, per key, per account, or too many requests in progress at once. |

Every code, its fixed message and what to do are on the [error codes](https://relayvia.dev/docs/errors) page.
