# quotas (/docs/reference/api/quotas)

> API usage plans: throttles (a token bucket of ratePerSecond holding at most burst) and period limits (per minute, hour, day, week or month) on a meter you name…



API usage plans: throttles (a token bucket of `ratePerSecond` holding at most `burst`) and period limits (per minute,
hour, day, week or month) on a **meter** you name, such as `requests` or `exports`. Plans apply to API keys, agents,
identities and groups, or to everyone in the tenant as the meter's default. Applications count use with
`iam.quotas.consume` / `enforce` (the request's credential) or `consumeFor` (a subject your code identified), and
callers read what is left with `status`. Counters are stored in the database, so every server instance agrees. The
repository guide is `docs/quotas.md`.

## Which plan applies [#which-plan-applies]

For each meter, the most specific plan wins: the API key the request presents, then the acting agent of a delegated
session, the identity, one of its groups (highest `priority`, then name), and finally the tenant's `default` plan. A
meter no plan covers is unlimited (`plan: null`). With `scope: 'tenant'` everyone the plan covers shares one set of
counters; with `scope: 'subject'` each API key, agent or person has their own.

| Method                                | What it does                                                                                                                                                                                                                                                                            | Access     |
| ------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| [`assign`](#assign)                   | Assigns a plan to an API key (`subjectType: 'apiKey'` with the key's `credentialId`), an identity, or a group, replacing the subject's plan for the same meter.                                                                                                                         | Credential |
| [`consume`](#consume)                 | Counts `cost` (default 1) units of a meter for the caller's own session, or refuses without counting anything when the throttle or a period limit would be exceeded: `allowed: false` with `reason` (`throttle` or the period) and `retryAfterMs` (absent when the cost can never fit). | Credential |
| [`createPlan`](#createplan)           | Defines a plan for a meter with a `throttle`, `limits`, or both.                                                                                                                                                                                                                        | Credential |
| [`deletePlan`](#deleteplan)           | Deletes a plan with its assignments and counters.                                                                                                                                                                                                                                       | Credential |
| [`getPlan`](#getplan)                 | One plan.                                                                                                                                                                                                                                                                               | Credential |
| [`listAssignments`](#listassignments) | Assignments, optionally of one `plan`, with each subject's name (an API key's label).                                                                                                                                                                                                   | Credential |
| [`listPlans`](#listplans)             | Every plan of the tenant, by name, with how many subjects are assigned to each.                                                                                                                                                                                                         | Credential |
| [`reset`](#reset)                     | Starts one `subject`'s counters and throttle over (as `usage` names it), or every subject's when none is given.                                                                                                                                                                         | Credential |
| [`status`](#status)                   | The caller's own plan for a meter and what is left in each window, without counting.                                                                                                                                                                                                    | Credential |
| [`unassign`](#unassign)               | Removes a subject's plan for a meter; `removed` says whether there was one.                                                                                                                                                                                                             | Credential |
| [`updatePlan`](#updateplan)           | Changes a plan; fields left out keep their value, `throttle: null` and `description: null` clear them, and `limits` replaces the list. The meter cannot change. Windows in progress keep their counts under the new limits.                                                             | Credential |
| [`usage`](#usage)                     | Every subject's use of a plan in the current windows, the most used first. Subjects are named `identity:{id}`, `key:{credentialId}`, or `tenant` for a tenant-scoped plan.                                                                                                              | Credential |

## assign [#assign]

Assigns a plan to an API key (`subjectType: 'apiKey'` with the key's `credentialId`), an identity, or a group, replacing the subject's plan for the same meter.

**HTTP:** `POST /api/iam/quotas/assign` (requires a credential) · **Browser client:** `client.quotas.assign()`

* **Permission:** `iam:quotas:manage` on `iam/quotas/{plan}`.
* **Audited as:** `quota:assign`.
* **Errors:** `NOT_FOUND` (404) for an unknown plan, a subject outside the tenant, a deleted identity, or a session
  that is not an API key; `INVALID_INPUT` for another `subjectType`.

```ts title="Signature"
iam.api.quotas.assign(
  credential: CredentialInput,
  input: {
    tenantId: string;
    plan: string;
    subjectType: QuotaSubjectType;
    subjectId: string;
  },
): Promise<QuotaAssignmentView>
```

## consume [#consume]

Counts `cost` (default 1) units of a meter for the caller's own session, or refuses without counting anything when the throttle or a period limit would be exceeded: `allowed: false` with `reason` (`throttle` or the period) and `retryAfterMs` (absent when the cost can never fit).

**HTTP:** `POST /api/iam/quotas/consume` (requires a credential) · **Browser client:** `client.quotas.consume()`

* **Permission:** None beyond a session of the tenant.
* **Audited as:** `quota:threshold` when use first reaches an alert threshold in a window, and `quota:exceeded`
  (outcome `deny`) at a window's first refusal.
* **Errors:** `ACCESS_DENIED` for a session of another tenant; `INVALID_INPUT` for a malformed meter or a cost outside
  1 to 1,000,000,000.

```ts title="Signature"
iam.api.quotas.consume(
  credential: CredentialInput,
  input: { tenantId: string; meter: string; cost?: number },
): Promise<QuotaDecision>
```

## createPlan [#createplan]

Defines a plan for a meter with a `throttle`, `limits`, or both.

**HTTP:** `POST /api/iam/quotas/createPlan` (requires a credential) · **Browser client:** `client.quotas.createPlan()`

* **Permission:** `iam:quotas:manage` on `iam/quotas/{name}`.
* **Audited as:** `quota:plan-create`.
* **Errors:** `CONFLICT` (409) when the name is taken or the tenant already has a default plan for the meter;
  `INVALID_INPUT` without a throttle or limits, for two limits of one period, a limit below 1, an unknown period or time
  zone, a malformed name or meter, or more than five `alertThresholds`.

Day, week (Monday to Sunday) and month windows start at local midnight in `timeZone` (default `UTC`); minutes and hours
are UTC. `alertThresholds` are percentages of each period limit recorded once per window as `quota:threshold`.

```ts title="Signature"
iam.api.quotas.createPlan(
  credential: CredentialInput,
  input: {
    tenantId: string;
    name: string;
    meter: string;
    description?: string;
    throttle?: QuotaThrottle;
    limits?: QuotaLimit[];
    scope?: QuotaPlan['scope'];
    default?: boolean;
    priority?: number;
    timeZone?: string;
    alertThresholds?: number[];
  },
): Promise<QuotaPlanView>
```

## deletePlan [#deleteplan]

Deletes a plan with its assignments and counters.

**HTTP:** `POST /api/iam/quotas/deletePlan` (requires a credential) · **Browser client:** `client.quotas.deletePlan()`

* **Permission:** `iam:quotas:manage` on `iam/quotas/{name}`.
* **Audited as:** `quota:plan-delete`, with how many assignments went.

```ts title="Signature"
iam.api.quotas.deletePlan(
  credential: CredentialInput,
  input: { tenantId: string; name: string },
): Promise<{ deleted: true; assignments: number }>
```

## getPlan [#getplan]

One plan.

**HTTP:** `POST /api/iam/quotas/getPlan` (requires a credential) · **Browser client:** `client.quotas.getPlan()`

* **Permission:** `iam:quotas:read` on `iam/quotas/{name}`.
* **Errors:** `NOT_FOUND` (404).

```ts title="Signature"
iam.api.quotas.getPlan(
  credential: CredentialInput,
  input: { tenantId: string; name: string },
): Promise<QuotaPlanView>
```

## listAssignments [#listassignments]

Assignments, optionally of one `plan`, with each subject's name (an API key's label).

**HTTP:** `POST /api/iam/quotas/listAssignments` (requires a credential) · **Browser client:** `client.quotas.listAssignments()`

* **Permission:** `iam:quotas:read` on `iam/quotas`.

```ts title="Signature"
iam.api.quotas.listAssignments(
  credential: CredentialInput,
  input: { tenantId: string; plan?: string },
): Promise<QuotaAssignmentView[]>
```

## listPlans [#listplans]

Every plan of the tenant, by name, with how many subjects are assigned to each.

**HTTP:** `POST /api/iam/quotas/listPlans` (requires a credential) · **Browser client:** `client.quotas.listPlans()`

* **Permission:** `iam:quotas:read` on `iam/quotas`.

```ts title="Signature"
iam.api.quotas.listPlans(
  credential: CredentialInput,
  input: { tenantId: string },
): Promise<QuotaPlanView[]>
```

## reset [#reset]

Starts one `subject`'s counters and throttle over (as `usage` names it), or every subject's when none is given.

**HTTP:** `POST /api/iam/quotas/reset` (requires a credential) · **Browser client:** `client.quotas.reset()`

* **Permission:** `iam:quotas:manage` on `iam/quotas/{plan}`.
* **Audited as:** `quota:reset`, with how many counters went.

```ts title="Signature"
iam.api.quotas.reset(
  credential: CredentialInput,
  input: { tenantId: string; plan: string; subject?: string },
): Promise<{ reset: number }>
```

## status [#status]

The caller's own plan for a meter and what is left in each window, without counting.

**HTTP:** `POST /api/iam/quotas/status` (requires a credential) · **Browser client:** `client.quotas.status()`

* **Permission:** None beyond a session of the tenant.
* **Audited as:** Not audited.
* **Errors:** `ACCESS_DENIED` for a session of another tenant.

```ts title="Signature"
iam.api.quotas.status(
  credential: CredentialInput,
  input: { tenantId: string; meter: string },
): Promise<QuotaDecision>
```

## unassign [#unassign]

Removes a subject's plan for a meter; `removed` says whether there was one.

**HTTP:** `POST /api/iam/quotas/unassign` (requires a credential) · **Browser client:** `client.quotas.unassign()`

* **Permission:** `iam:quotas:manage` on `iam/quotas`.
* **Audited as:** `quota:unassign` when something was removed.

```ts title="Signature"
iam.api.quotas.unassign(
  credential: CredentialInput,
  input: {
    tenantId: string;
    meter: string;
    subjectType: QuotaSubjectType;
    subjectId: string;
  },
): Promise<{ removed: boolean }>
```

## updatePlan [#updateplan]

Changes a plan; fields left out keep their value, `throttle: null` and `description: null` clear them, and `limits` replaces the list. The meter cannot change. Windows in progress keep their counts under the new limits.

**HTTP:** `POST /api/iam/quotas/updatePlan` (requires a credential) · **Browser client:** `client.quotas.updatePlan()`

* **Permission:** `iam:quotas:manage` on `iam/quotas/{name}`.
* **Audited as:** `quota:plan-update`.
* **Errors:** `NOT_FOUND` (404); `CONFLICT` (409) when making it the default and another plan already is;
  `INVALID_INPUT` as for `createPlan`.

```ts title="Signature"
iam.api.quotas.updatePlan(
  credential: CredentialInput,
  input: {
    tenantId: string;
    name: string;
    description?: string | null;
    throttle?: QuotaThrottle | null;
    limits?: QuotaLimit[];
    scope?: QuotaPlan['scope'];
    default?: boolean;
    priority?: number;
    timeZone?: string;
    alertThresholds?: number[];
  },
): Promise<QuotaPlanView>
```

## usage [#usage]

Every subject's use of a plan in the current windows, the most used first. Subjects are named `identity:{id}`, `key:{credentialId}`, or `tenant` for a tenant-scoped plan.

**HTTP:** `POST /api/iam/quotas/usage` (requires a credential) · **Browser client:** `client.quotas.usage()`

* **Permission:** `iam:quotas:read` on `iam/quotas/{plan}`.

```ts title="Signature"
iam.api.quotas.usage(
  credential: CredentialInput,
  input: { tenantId: string; plan: string },
): Promise<QuotaUsageView[]>
```
