---
title: "List budgets"
method: GET
path: "/v2/budgets"
tags: ["Budgets"]
---

# List budgets

`GET /v2/budgets`

Returns budgets visible to the current workspace, ordered by creation time with the newest first. Supports filtering by scope kind, scope target id, period, and active state, plus an optional free-text query that searches across denormalized target names via Typesense.

## Query parameters

- `limit` integer
- `starting_after` string
- `ending_before` string
- `scope_kind` BudgetScopeKind[]
- `scope_target_id` string
- `is_active` boolean
- `period` BudgetPeriod[]
- `query` string
- `sort_by` 'BUDGET_SORT_FIELD_UNSPECIFIED' | 'BUDGET_SORT_FIELD_EXPIRES_AT' | 'BUDGET_SORT_FIELD_CREATED_AT' | 'BUDGET_SORT_FIELD_UPDATED_AT'

## Response `200`

OK

- ListBudgetsResponse
  - `object` string, required — Object discriminator for list responses; always `list`.
  - `data` BudgetRestResponse[], required — Page of budgets, ordered newest first.
    - `budgetId` string, required
    - `scope` BudgetScopeRestResponse — BudgetScope is a closed oneof. Exactly one variant must be set. The six variants are ordered by enforcement precedence (most specific to most general) and mirror the BudgetScopeKind filter enum.
      - `workspace` WorkspaceBudgetScope — Workspace-wide ceiling. The implicit target is the caller's workspace.
      - `project` ProjectBudgetScopeRestResponse — Per-project cap.
        - `projectId` string
      - `identity` IdentityBudgetScopeRestResponse — Per-identity cap. Keyed by the contact's external_id (not the internal Mongo `_id`) so the scope is stable across imports.
        - `identityExternalId` string
      - `apiKey` ApiKeyBudgetScopeRestResponse — Per-api-key cap. Replaces the legacy embedded `constraints.budget` on auth.apiKeys.
        - `apiKeyId` string
      - `provider` ProviderBudgetScope — Per-provider cap. The value is the provider enum string (e.g. "openai", "anthropic") drawn from ModelIntegrationIdentifier.
        - `provider` string
      - `model` ModelBudgetScopeRestResponse — Per-model cap. The value is the FULL model reference as callers send it ("openai/gpt-4o", or "workspaceKey@openai/gpt-4o" for private models) — NOT the Mongo `_id` of the model master-data document.
        - `modelId` string, required
    - `match` BudgetMatch — BudgetMatch carries the CEL expression that decides whether a budget applies to a request. Available variables: `model`, `provider`, `model_id`, `api_key`, `identity`, `project`, `metadata` (map), `headers` (map, lowercase keys). An empty expression always matches. Expressions are syntax-validated at write time.
      - `cel` string
    - `limits` BudgetLimitsRestResponse, required — BudgetLimits is the per-period spend and token ceiling. At least one of `amount`, `token_limit`, or RateLimit.requests_per_minute MUST be set on a Budget; that invariant is enforced by the handler.
      - `period` 'BUDGET_PERIOD_UNSPECIFIED' | 'BUDGET_PERIOD_DAILY' | 'BUDGET_PERIOD_WEEKLY' | 'BUDGET_PERIOD_MONTHLY' | 'BUDGET_PERIOD_YEARLY' | 'BUDGET_PERIOD_ONE_TIME'
      - `amount` number, double
      - `tokenLimit` number, double — Token ceiling. Carried as a double so it serializes as a JSON number (proto int64 would serialize as a quoted string); token counts are whole and well within double's exact-integer range (2^53). Stored as an integer server-side.
    - `rateLimit` RateLimitRestResponse — RateLimit is the per-minute request ceiling. Enforced via atomic increment-first semantics in the enforcement middleware.
      - `requestsPerMinute` integer
    - `isActive` boolean
    - `expiresAt` string, date-time
    - `createdAt` string, date-time, required
    - `updatedAt` string, date-time, required
    - `usage` BudgetUsage — BudgetUsage is the current-period consumption of a budget, sourced from the live Redis counters (not the exact ledger). Each dimension is the consumed side of the matching limit dimension: `amount` is the accumulated cost in USD (vs limits.amount), `tokens` is the accumulated token count (vs limits.token_limit), and `requests` is the count in the rolling 60-second window (vs rate_limit.requests_per_minute). All three are explicit-presence so the triple is always emitted in full, zeros included — a never-spent budget serializes {amount:0, tokens:0, requests:0} rather than dropping its zero dimensions.
      - `amount` number, double
      - `tokens` number, double — Carried as a double (not int64) so it serializes as a JSON number rather than a quoted string, matching limits.token_limit.
      - `requests` integer
    - `alerts` BudgetAlertRestResponse[] — Threshold notifications. Absent when the budget has none.
      - `id` string — Assigned by ORQ. Supply an existing id to edit that alert in place.
      - `thresholdPercent` integer, required — Percentage of the dimension's limit at which the alert fires, 1–100.
      - `notifierIds` string[], required — Must be workspace-scoped; project-scoped notifiers are rejected.
      - `dimension` 'BUDGET_ALERT_DIMENSION_UNSPECIFIED' | 'BUDGET_ALERT_DIMENSION_COST' | 'BUDGET_ALERT_DIMENSION_TOKENS'
  - `hasMore` boolean — Whether more budgets are available in the selected pagination direction.

---

[API](https://skmtc.net/orq-ai/apis/orq-ai-api.md) · [All operations](https://skmtc.net/orq-ai/apis/orq-ai-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/orq-ai/orq-ai-api/revisions/f7a624eccddb/schema)
