---
title: "Store an agent-authored category budget plan."
method: POST
path: "/v1/budget/plan"
---

# Store an agent-authored category budget plan.

`POST /v1/budget/plan`

## Request

- Base URL: `https://api.candor.money`
- URL: `https://api.candor.money/v1/budget/plan`
- Auth: HTTP bearer

Store an agent-authored category budget plan.

## Headers

- `Idempotency-Key` string, required

## Request body

- object: The user's spending plan, not an observation. Storing one supersedes the active plan for that period, so read the current plan and the observed spending it is meant to reflect before writing. Build it from what the user said they want to spend; it needs no separate yes, and you can revise it when their plans change.
  - `period` string, required: The month this plan governs, as YYYY-MM.
  - `currency` string, required: Three-letter uppercase ISO code the plan is denominated in, such as USD. Every line amount is read in it, so a plan in the wrong currency compares against the wrong spending.
  - `approval_note` string: What the user said about this plan, in their words, when they said something. Optional.
  - `approval_source` string: Where their words came from, such as the conversation or message, when you pass approval_note.
  - `policy_notes` string
  - `recurs_monthly` boolean: Whether this plan should carry into later months instead of applying to this period alone.
  - `lines` object[], required: Replaces the whole plan as a set. A category left out is unbudgeted, not carried over from the previous plan.
    - `category` string, required: The effective category this line governs, matching the category transactions carry after corrections and rules. A category nothing resolves to allocates money against spending that never arrives.
    - `monthly_amount` string, required: A positive amount in the plan's currency, as a decimal (`250.00`) or money text in that currency (`USD 250.00`); not `$250`.
    - `line_type` 'recurring' | 'flexible' | 'goal' | 'cushion' | 'other', required: How the line behaves against actuals: recurring is a committed obligation, flexible is discretionary, goal funds a saved goal, and cushion is deliberate slack rather than a spending target.
    - `policy_note` string
    - `rollover_enabled` boolean: Whether an underspend carries into the next period instead of resetting. This depends on the plan recurring: with recurs_monthly false there is no next period to carry into, and the request returns a warning saying nothing will accumulate.

## Response `200`

Envelope with the active budget plan, plan lines, and superseded plan ids.

- ResponseEnvelope
  - `schema_version` string, required
  - `generated_at` string, date-time, required
  - `request_id` string, required
  - `status` 'success' | 'partial_success' | 'action_required' | 'error', required
  - `user_message` string: Optional concise user-safe message the calling agent may adapt.
  - `data_freshness` DataFreshness
    - `balances_last_synced_at` string
    - `coverage` 'complete' | 'partial' | 'stale' | 'unavailable', required
    - `holdings_last_synced_at` string
    - `transactions_last_synced_at` string
  - `metadata` object: Response-level protocol metadata such as package compatibility and workspace opening identity or timing. It is not financial workspace data and must not be treated as attention.
    - `view_url` string, uri: Authenticated dashboard destination related to this response. May open a section rather than reproduce the returned records or filters. Per-record view_url values identify exact supported record views. Use returned URLs instead of constructing paths.
  - `warnings` object[], required
  - `errors` AgentError[], required
    - `code` string, required
    - `expires_at` string
    - `idempotency_key` string: Stable key to reuse when retrying this identical logical operation.
    - `message` string, required
    - `recovery_url` string, uri
    - `required_capability` string
    - `retry_after_seconds` integer: Machine-actionable delay before retrying the identical logical operation.
    - `retryable` boolean, required
    - `suggested_command` string
  - `next_actions` AgentAction[], required
    - `intent` string, required
    - `command` string, required
    - `args` object, required
    - `shell` string, required
  - `action` WorkspaceAction
    - `id` string, required
    - `operation` string, required
    - `reason` string, required
    - `root_action_id` string, required
    - `parent_action_id` string
    - `task_key` string
    - `status` 'started' | 'succeeded' | 'refused' | 'failed', required
    - `created_at` string, date-time, required
    - `completed_at` string, date-time
  - `data` object, nullable, required: Operation-specific result data, or null when the request ends in an error.

## Other responses

- `default`: Structured Candor error envelope with machine-readable codes, recovery guidance, and retry timing when applicable.

---

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