---
title: "Create a hierarchical budget (owner or admin only)"
method: POST
path: "/api/budgets"
tags: ["budgets"]
---

# Create a hierarchical budget (owner or admin only)

`POST /api/budgets`

## Request

- Base URL: `https://www.spendline.ai`
- URL: `https://www.spendline.ai/api/budgets`
- Auth: API key in header `x-spendline-key`

Requires OWNER or ADMIN authority. A scoped child key cannot do this and receives 403 permission_denied. To have a budget created from an agent-initiated flow, propose it in the onboarding request so a human approves the exact numbers.

## Request body

- Budget: A hierarchical budget. The tightest applicable scope wins.
  - `id` string, uuid
  - `scope_type` 'org' | 'team' | 'agent' | 'customer', required: org = whole account. team = x-spendline-tags cost-centre key. agent = x-agent-id. customer = x-customer-id.
  - `scope_id` string, nullable: Required unless scope_type is "org". Must match the attribution value exactly.
  - `monthly_limit_usd` number, required: Calendar-month cap in USD, UTC.
  - `strict_mode` boolean: true blocks over-cap calls with 402; false records only.
  - `require_approval_on_exceed` boolean
  - `created_at` string, date-time
  - `updated_at` string, date-time

## Response `201`

Created.

- Budget: A hierarchical budget. The tightest applicable scope wins.
  - `id` string, uuid
  - `scope_type` 'org' | 'team' | 'agent' | 'customer', required: org = whole account. team = x-spendline-tags cost-centre key. agent = x-agent-id. customer = x-customer-id.
  - `scope_id` string, nullable: Required unless scope_type is "org". Must match the attribution value exactly.
  - `monthly_limit_usd` number, required: Calendar-month cap in USD, UTC.
  - `strict_mode` boolean: true blocks over-cap calls with 402; false records only.
  - `require_approval_on_exceed` boolean
  - `created_at` string, date-time
  - `updated_at` string, date-time

## Other responses

- `400`: Invalid scope_type, missing scope_id, or negative limit.
- `403`: Insufficient authority.
- `409`: A budget already exists for this scope. Use PUT /api/budgets/{id}.

---

[API](https://skmtc.dev/spendline/apis/spendline-api.md) · [All operations](https://skmtc.dev/spendline/apis/spendline-api/llms.txt) · [OpenAPI document](https://skmtc.dev/spendline/apis/spendline-api/revisions/eb22b9415a28?raw)
