# Usage for the key's partner

> GET /v1/usage: Usage for the key's partner.

Source: https://docs.voice.kheelona.com/reference/generated/api/getusage/

`GET /v1/usage`

| Property | Value |
| --- | --- |
| Operation | `getUsage` |
| Scope | `usage:read` |

## Parameters

| Name | In | Type | Required | Description | Rules |
| --- | --- | --- | --- | --- | --- |
| `from` | query | string | no | First day (`YYYY-MM-DD`); default: the 1st of this month. | format `date` |
| `to` | query | string | no | Last day, inclusive (`YYYY-MM-DD`); default: today. At most 366 days after `from`. | format `date` |
| `granularity` | query | string | no | `day` (default) or `month`. | one of `day`, `month` |
| `group_by` | query | string | no | `none` (default), `voice` or `api_key`. | one of `none`, `voice`, `api_key` |

## Responses

### 200

Usage rows

| Header | Type | Description |
| --- | --- | --- |
| `RateLimit-Limit` | integer | Requests allowed at once for this key |
| `RateLimit-Remaining` | integer | Requests left right now |
| `RateLimit-Reset` | integer | Seconds until the limit is full again |
| `X-Request-Id` | string | The request's ID (`req_…`); quote it in reports. |

| Field | Type | Required | Description | Rules |
| --- | --- | --- | --- | --- |
| `from` | string | yes | First day. | format `date` |
| `to` | string | yes | Last day (inclusive). | format `date` |
| `granularity` | string | yes | Day or month rows. Rows per day or per month. | one of `day`, `month` |
| `group_by` | string | yes | The extra split. What rows are split by, besides the period and the client kind. | one of `none`, `voice`, `api_key` |
| `data` | array of UsageRowObject | yes | The rows, oldest first. Usage is rolled up every 15 minutes. |  |
| `data[].period` | string | yes | The day, or the month's first day (`YYYY-MM-DD`). | format `date` |
| `data[].client_kind` | string | yes | Who connected. `browser`: your web page, through the SDK; `server`: your server or device relay; `playground`: a session started from your console's playground; `admin`: a Kheelona support or test session (internal tools). | one of `browser`, `server`, `playground`, `admin` |
| `data[].sessions` | integer | yes | Admitted sessions. | format `int64` |
| `data[].rejected_sessions` | integer | yes | Sessions refused at admission. | format `int64` |
| `data[].connected_seconds` | integer | yes | Billable connected seconds (each session rounded up to the next second). | format `int64` |
| `data[].user_speech_seconds` | integer | yes | The people's speech. | format `int64` |
| `data[].reply_audio_seconds` | integer | yes | The voices' audio. | format `int64` |
| `data[].llm_input_tokens` | integer | yes | Reply model input tokens. | format `int64` |
| `data[].llm_output_tokens` | integer | yes | Reply model output tokens. | format `int64` |
| `data[].llm_thinking_tokens` | integer | yes | Reply model thinking tokens. | format `int64` |
| `data[].api_key_id` | string | no | The API key (with `group_by=api_key`; `null` for sessions without one). | may be null |
| `data[].voice_id` | string | no | The voice (with `group_by=voice`). | may be null |

### 400

Invalid dates or span

| Header | Type | Description |
| --- | --- | --- |
| `RateLimit-Limit` | integer | Requests allowed at once for this key |
| `RateLimit-Remaining` | integer | Requests left right now |
| `RateLimit-Reset` | integer | Seconds until the limit is full again |
| `X-Request-Id` | string | The request's ID (`req_…`); quote it in reports. |

| Field | Type | Required | Description | Rules |
| --- | --- | --- | --- | --- |
| `error` | object | yes | The error. |  |
| `error.code` | string | yes |  | one of `invalid_request`, `unauthenticated`, `secret_expired`, `forbidden`, `origin_not_allowed`, `voice_not_found`, `session_not_found`, `capacity_exhausted`, `partner_limit_reached`, `rate_limited`, `internal`, `not_found`, `conflict`, `unavailable` |
| `error.message` | string | yes | A short, fixed description. Never quotes the request. |  |
| `error.request_id` | string | yes | The request's ID (also in the `X-Request-Id` header); quote it when reporting a problem. | pattern `^req_[0-9A-HJKMNP-TV-Z]{26}$` |
| `error.details` | any | no | Structured detail, e.g. `{"field": "languages[1]"}` or `{"reason": "quota_exhausted"}`. |  |

### 401

Missing or invalid API key

| Header | Type | Description |
| --- | --- | --- |
| `RateLimit-Limit` | integer | Requests allowed at once for this key |
| `RateLimit-Remaining` | integer | Requests left right now |
| `RateLimit-Reset` | integer | Seconds until the limit is full again |
| `X-Request-Id` | string | The request's ID (`req_…`); quote it in reports. |

| Field | Type | Required | Description | Rules |
| --- | --- | --- | --- | --- |
| `error` | object | yes | The error. |  |
| `error.code` | string | yes |  | one of `invalid_request`, `unauthenticated`, `secret_expired`, `forbidden`, `origin_not_allowed`, `voice_not_found`, `session_not_found`, `capacity_exhausted`, `partner_limit_reached`, `rate_limited`, `internal`, `not_found`, `conflict`, `unavailable` |
| `error.message` | string | yes | A short, fixed description. Never quotes the request. |  |
| `error.request_id` | string | yes | The request's ID (also in the `X-Request-Id` header); quote it when reporting a problem. | pattern `^req_[0-9A-HJKMNP-TV-Z]{26}$` |
| `error.details` | any | no | Structured detail, e.g. `{"field": "languages[1]"}` or `{"reason": "quota_exhausted"}`. |  |

### 403

The key lacks `usage:read`

| Header | Type | Description |
| --- | --- | --- |
| `RateLimit-Limit` | integer | Requests allowed at once for this key |
| `RateLimit-Remaining` | integer | Requests left right now |
| `RateLimit-Reset` | integer | Seconds until the limit is full again |
| `X-Request-Id` | string | The request's ID (`req_…`); quote it in reports. |

| Field | Type | Required | Description | Rules |
| --- | --- | --- | --- | --- |
| `error` | object | yes | The error. |  |
| `error.code` | string | yes |  | one of `invalid_request`, `unauthenticated`, `secret_expired`, `forbidden`, `origin_not_allowed`, `voice_not_found`, `session_not_found`, `capacity_exhausted`, `partner_limit_reached`, `rate_limited`, `internal`, `not_found`, `conflict`, `unavailable` |
| `error.message` | string | yes | A short, fixed description. Never quotes the request. |  |
| `error.request_id` | string | yes | The request's ID (also in the `X-Request-Id` header); quote it when reporting a problem. | pattern `^req_[0-9A-HJKMNP-TV-Z]{26}$` |
| `error.details` | any | no | Structured detail, e.g. `{"field": "languages[1]"}` or `{"reason": "quota_exhausted"}`. |  |

### 429

Rate limited

| Header | Type | Description |
| --- | --- | --- |
| `RateLimit-Limit` | integer | Requests allowed at once for this key |
| `RateLimit-Remaining` | integer | Requests left right now |
| `RateLimit-Reset` | integer | Seconds until the limit is full again |
| `Retry-After` | integer | Seconds to wait before retrying |
| `X-Request-Id` | string | The request's ID (`req_…`); quote it in reports. |

| Field | Type | Required | Description | Rules |
| --- | --- | --- | --- | --- |
| `error` | object | yes | The error. |  |
| `error.code` | string | yes |  | one of `invalid_request`, `unauthenticated`, `secret_expired`, `forbidden`, `origin_not_allowed`, `voice_not_found`, `session_not_found`, `capacity_exhausted`, `partner_limit_reached`, `rate_limited`, `internal`, `not_found`, `conflict`, `unavailable` |
| `error.message` | string | yes | A short, fixed description. Never quotes the request. |  |
| `error.request_id` | string | yes | The request's ID (also in the `X-Request-Id` header); quote it when reporting a problem. | pattern `^req_[0-9A-HJKMNP-TV-Z]{26}$` |
| `error.details` | any | no | Structured detail, e.g. `{"field": "languages[1]"}` or `{"reason": "quota_exhausted"}`. |  |
