
## Company AI quota

`GET /v1/ai/quota`

Returns the monthly AI quota state of the Bitrix24 account the API key is bound to: the percentage of the limit consumed, the reset date, and a per-model breakdown — how many requests and tokens each model accounted for and what share of the monthly limit it consumed.

The quota is account-wide: the limit is shared across the whole Bitrix24 account, not per key. The API does not expose the absolute limit values (in Vibe credits) — percentages only.

## Parameters

None.

## Examples

### curl — personal key

```bash
curl "https://vibecode.bitrix24.com/v1/ai/quota" \
  -H "X-Api-Key: YOUR_API_KEY"
```

### curl — OAuth application

```bash
curl "https://vibecode.bitrix24.com/v1/ai/quota" \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN"
```

### JavaScript — personal key

```javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/ai/quota', {
  headers: { 'X-Api-Key': 'YOUR_API_KEY' },
})

const { data } = await res.json()
console.log(`Quota used: ${data.pctUsed}%, resets at ${data.resetAt}`)
data.byModel.forEach((m) => {
  console.log(`  ${m.modelId}: ${m.calls} requests, ${m.pctOfLimit ?? 0}% of the limit`)
})
```

### JavaScript — OAuth application

```javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/ai/quota', {
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
  },
})

const { data } = await res.json()
console.log(`Quota used: ${data.pctUsed}%, resets at ${data.resetAt}`)
```

## Response fields

| Field | Type | Description |
|------|-----|----------|
| `success` | boolean | Always `true` on success |
| `data.pctUsed` | number | Percentage of the monthly quota consumed. Honest value — not clamped at 100: overspend is shown as-is (for example, `150`) |
| `data.exhausted` | boolean | `true` when the quota is exhausted |
| `data.resetAt` | string \| null | Quota reset date in `ISO 8601` (rolling 30-day window). `null` until the account has made its first metered AI call |
| `data.pacing` | object \| null | Quota pacing state (day/week smoothing). `null` when pacing is off for the account — not enabled by the platform or the admin (see "Pacing (day/week smoothing)" below) |
| `data.pacing.mode` | string | Enforcement behavior on a tripped window: `wallet`, `block`, or `ignore` |
| `data.pacing.active` | boolean | `true` only when tripping a window will actually reject a call right now: platform enforcement is on and the mode is not `ignore`. `false` — observation mode or `ignore`: windows are informational only, with no blocking and no charges |
| `data.pacing.day.pctUsed` | number | Daily window usage as a percentage of ITS OWN limit (not of the monthly quota) |
| `data.pacing.day.resetAt` | string | Daily window reset instant in `ISO 8601` |
| `data.pacing.week.pctUsed` | number | Weekly window usage as a percentage of its own limit |
| `data.pacing.week.resetAt` | string | Weekly window reset instant in `ISO 8601` |
| `data.period.start` | string | Start of the current quota window in `ISO 8601` |
| `data.byModel` | array | Per-model breakdown for the current window, sorted by call count descending |
| `data.byModel[].modelId` | string | Model ID |
| `data.byModel[].calls` | number | Successful call count |
| `data.byModel[].tokensIn` | number | Prompt tokens |
| `data.byModel[].tokensOut` | number | Completion tokens |
| `data.byModel[].audioSeconds` | number | Seconds of transcribed audio (Whisper). `0` for text models |
| `data.byModel[].pctOfLimit` | number \| null | Share of the monthly limit consumed by this model, in percent (one decimal place). `null` when the Bitrix24 account has no positive limit |

## Response example

```json
{
  "success": true,
  "data": {
    "pctUsed": 12,
    "exhausted": false,
    "resetAt": "2026-07-31T18:50:39.633Z",
    "pacing": {
      "mode": "wallet",
      "active": false,
      "day": { "pctUsed": 42, "resetAt": "2026-07-10T21:00:00.000Z" },
      "week": { "pctUsed": 18, "resetAt": "2026-07-13T21:00:00.000Z" }
    },
    "period": { "start": "2026-07-01T18:50:39.633Z" },
    "byModel": [
      {
        "modelId": "bitrix/openai/gpt-oss-120b",
        "calls": 63017,
        "tokensIn": 58000000,
        "tokensOut": 43000000,
        "audioSeconds": 0,
        "pctOfLimit": 10.9
      },
      {
        "modelId": "bitrix/bitrixgpt-5.5",
        "calls": 1240,
        "tokensIn": 800000,
        "tokensOut": 350000,
        "audioSeconds": 0,
        "pctOfLimit": 1.2
      }
    ]
  }
}
```

## Pacing (day/week smoothing)

Pacing is a pair of extra daily and weekly limits on AI-quota spend, each expressed as a percentage of the overall monthly limit. The platform can enable pacing for an account by default (no admin action required); the rollout is staged, so not every account is covered yet. The account admin can enable pacing themselves from the `/ai` cabinet page; if the account is under the platform default-on — they can only tighten the limits: loosening them or turning pacing off is not possible while the account is managed by the platform defaults. Pacing does not change the monthly quota itself — it smooths out spikes, preventing the whole monthly limit from being spent in a single day or hour.

The enforcement behavior on a tripped window is configured by the admin and reported in the `pacing.mode` field:

| Mode | Behavior when a window is tripped |
|-------|-------------------------------|
| `wallet` | The call proceeds as paid overage — charged against the account's money balance, when funds are available and the hourly overage cap has headroom |
| `block` | The call is rejected with `429` until the window resets — paid overage is not available |
| `ignore` | The window is tracked for monitoring only, calls are never blocked |

### The `pacing` field in the response

Current pacing state is returned in `data.pacing` (see "Response fields" above) — `null` when pacing is off for the account (not enabled by the platform or the admin):

```json
{
  "mode": "wallet",
  "active": false,
  "day": { "pctUsed": 42, "resetAt": "2026-07-10T21:00:00.000Z" },
  "week": { "pctUsed": 18, "resetAt": "2026-07-13T21:00:00.000Z" }
}
```

`active: false` means tripping a window does not trigger a `429` — an informational mode: window limits are shown in the response but never reject requests (`429` is impossible in this state). This happens both under platform-enforcement demo mode and under `mode: "ignore"` — the default mode the platform applies to accounts under default-on. `active: true` means tripping a window will reject a call right now. Like the rest of the `GET /v1/ai/quota` response, pacing state is cached — the status can lag by up to 30 seconds.

### Error when a window is exceeded

When pacing is active and the daily or weekly limit is tripped, calls to [chat completions](/docs/ai/chat/completions), [embeddings](/docs/ai/embeddings), and [audio transcription](/docs/ai/audio/transcriptions) respond with `429`:

```json
{
  "success": false,
  "error": {
    "code": "ai_pacing_limited",
    "type": "rate_limit_exceeded",
    "message": "AI pacing window exceeded for this portal. Wait for the window reset or adjust pacing settings in the cabinet.",
    "reason": "day_window",
    "overageDenied": "wallet_empty",
    "resetAt": "2026-07-11T00:00:00.000Z",
    "retryAfter": 3600
  }
}
```

| Field | Type | Description |
|------|-----|----------|
| `reason` | string | Which window tripped: `day_window` or `week_window` |
| `overageDenied` | string \| null | Why paid overage was refused. Always present in the response: `wallet_empty` — the account's money balance has insufficient funds, `breaker` — the hourly overage-spend circuit breaker tripped, `wallet_off` — the account cannot spend past the limit at all. `null` — under `block` mode, where paid overage is never available |
| `resetAt` | string | When the window resets and calls start succeeding again, in `ISO 8601` |
| `retryAfter` | number | The same instant in seconds — matches the `Retry-After` response header |

### How to react

- **Honor `Retry-After` and `resetAt`.** Retrying before that time will not help — the quota won't become available any sooner.
- **In `wallet` mode, read `overageDenied`.** A `429` in this mode does not mean "pacing blocks calls outright" — it means "paid overage was specifically refused." `wallet_empty`, for instance, signals that the account's money balance needs a top-up.
- **This is not the same as `402 ai_quota_exhausted`.** Pacing limits the SPEED of spend within a monthly quota that is not yet exhausted; `402` signals that the quota itself is fully exhausted. See [chat error reference](/docs/ai/chat/completions) for `402`.

## Error response example

`403 scope_missing` — the API key lacks the `vibe:ai` scope:

```json
{
  "error": {
    "message": "API key does not have the vibe:ai scope required for AI endpoints. Add vibe:ai scope to your API key in portal settings.",
    "type": "invalid_request_error",
    "code": "scope_missing"
  }
}
```

## Errors

| HTTP | Code | Description |
|------|-----|----------|
| 403 | `scope_missing` | The API key lacks the `vibe:ai` scope |
| 401 | `MISSING_API_KEY` | The `X-Api-Key` header is missing |
| 401 | `INVALID_API_KEY` | Key not found or revoked |
| 429 | `rate_limit_exceeded` | AI endpoint request limit exceeded. Time until reset is in the `Retry-After` header |

The full list of common API errors — [Errors](/docs/errors).

## Known specifics

**`pctOfLimit` is computed over the quota program's models.** A model outside the quota program (with no pricing policy configured) appears in `byModel` with call and token counters, but its `pctOfLimit` is `0` — it does not consume the quota.

**The breakdown excludes Cowork traffic.** Calls billed against a personal Cowork/Code subscription do not consume the company quota and are not included in the breakdown.

**The sum of `pctOfLimit` may differ from `pctUsed`.** `pctUsed` is read from the quota ledger and reflects the billing conditions at call time (including the off-peak discount when it is active), whereas `pctOfLimit` is a peak estimate: a recompute over the window against the current pricing policies, without discounts. If policies change mid-window, the values can diverge.

**The response is cached for 30 seconds.** Counters update with a delay of up to 30 seconds — sufficient for quota monitoring, polling more often makes no sense.

**When the quota is exhausted, model calls return `402 ai_quota_exhausted`.** For details, see the error reference of [chat](/docs/ai/chat). To warn the user in advance, poll `pctUsed` and `exhausted` before calling the model rather than waiting for a rejection.

**When pacing trips, model calls return `429 ai_pacing_limited`.** Distinct from `402 ai_quota_exhausted` — pacing limits the speed of spend within a quota that is not yet exhausted. See "Pacing (day/week smoothing)" above.

## See also

- [Off-peak schedule](/docs/ai/consumption/off-peak)
- [Usage statistics](/docs/ai/consumption/usage)
- [Model list](/docs/ai/models/list)
- [AI Router](/docs/ai)
