---
title: "Revise named lines of the budget plan."
method: POST
path: "/v1/budget/plan/update"
---

# Revise named lines of the budget plan.

`POST /v1/budget/plan/update`

## Request

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

Revise named lines of the budget plan while every other line carries forward.

## Headers

- `Idempotency-Key` string, required

## Request body

- union: A line-level revision of the active plan for the period. Only the lines named here change; every other line of the active plan is copied into the new version, which supersedes the old one. Name at least one line to set or one category to remove. The active plan may be a recurring plan set for an earlier month; the revision then applies from this period and recurs the same way unless recurs_monthly says otherwise.
  - object
    - `period` string, required: The month whose active plan is revised, as YYYY-MM.
    - `currency` string, required: Three-letter uppercase ISO code every line amount is read in; it must match the active plan's currency.
    - `approval_note` string: What the user said about this change, in their words, when they said something. Optional.
    - `approval_source` string: Where their words came from, when you pass approval_note.
    - `policy_notes` string, nullable: Plan-level policy notes for the revised version. Omitted keeps the active plan's notes; null clears them; a blank string is refused.
    - `recurs_monthly` boolean: Whether the revised plan carries into later months. Defaults to the active plan's setting. When the active plan is a recurring plan from an earlier month, false writes a one-month exception for this period only; the recurring plan applies again from the next month. Stopping a recurrence is not a revision.
    - `basis` object: Evidence behind the revision as a whole. Omitted keeps the active plan's basis; supplying one replaces it, so restate the handles you want kept. Unknown keys are refused rather than stripped.
      - `transaction_ids` string[]: Canonical transaction ids from this workspace that the revision rests on. Omitted or empty keeps none; ids from another workspace are refused.
      - `recurring_candidate_ids` string[]: Recurring candidate ids the revision rests on.
      - `notes` string: Why this evidence supports the revision, in the agent's words.
    - `lines` object[], required: At least one line to set, when no category is removed.
      - `category` string, required: The effective category this line governs, matching the category transactions carry after corrections and rules and matching the existing line exactly to revise it. 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 (`400.00`) or money text in that currency (`USD 400.00`); not `$400`.
      - `line_type` 'recurring' | 'flexible' | 'goal' | 'cushion' | 'other': 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. Omitted keeps the existing line's type; a new line defaults to other.
      - `policy_note` string, nullable: The line's policy in the user's terms. Omitted keeps the existing note; null clears it; a blank string is refused.
      - `rollover_enabled` boolean: Whether an underspend carries into the next period instead of resetting. Omitted keeps the existing setting. Depends on the plan recurring; with recurs_monthly false the response warns that nothing will accumulate.
      - `basis` object: Evidence handles behind this line. Omitted keeps the existing line's basis; supplying one replaces it. Unknown keys are refused rather than stripped.
        - `transaction_ids` string[]: Canonical transaction ids from this workspace that the revision rests on. Omitted or empty keeps none; ids from another workspace are refused.
        - `recurring_candidate_ids` string[]: Recurring candidate ids the revision rests on.
        - `notes` string: Why this evidence supports the revision, in the agent's words.
    - `remove` string[]: Categories whose lines are dropped from the plan; spending in them becomes unbudgeted. Every name must match an existing line exactly, or the revision is refused with budget_revision_unmatched_categories so a misspelling cannot pass as a no-op.
  - object
    - `period` string, required: The month whose active plan is revised, as YYYY-MM.
    - `currency` string, required: Three-letter uppercase ISO code every line amount is read in; it must match the active plan's currency.
    - `approval_note` string: What the user said about this change, in their words, when they said something. Optional.
    - `approval_source` string: Where their words came from, when you pass approval_note.
    - `policy_notes` string, nullable: Plan-level policy notes for the revised version. Omitted keeps the active plan's notes; null clears them; a blank string is refused.
    - `recurs_monthly` boolean: Whether the revised plan carries into later months. Defaults to the active plan's setting. When the active plan is a recurring plan from an earlier month, false writes a one-month exception for this period only; the recurring plan applies again from the next month. Stopping a recurrence is not a revision.
    - `basis` object: Evidence behind the revision as a whole. Omitted keeps the active plan's basis; supplying one replaces it, so restate the handles you want kept. Unknown keys are refused rather than stripped.
      - `transaction_ids` string[]: Canonical transaction ids from this workspace that the revision rests on. Omitted or empty keeps none; ids from another workspace are refused.
      - `recurring_candidate_ids` string[]: Recurring candidate ids the revision rests on.
      - `notes` string: Why this evidence supports the revision, in the agent's words.
    - `lines` object[]: Lines to set. An existing category takes the new amount and keeps its line type, rollover, policy note, and evidence basis unless they are restated; a new category is added with line_type defaulting to other. A line whose values all match the existing line is not reported as a change.
      - `category` string, required: The effective category this line governs, matching the category transactions carry after corrections and rules and matching the existing line exactly to revise it. 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 (`400.00`) or money text in that currency (`USD 400.00`); not `$400`.
      - `line_type` 'recurring' | 'flexible' | 'goal' | 'cushion' | 'other': 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. Omitted keeps the existing line's type; a new line defaults to other.
      - `policy_note` string, nullable: The line's policy in the user's terms. Omitted keeps the existing note; null clears it; a blank string is refused.
      - `rollover_enabled` boolean: Whether an underspend carries into the next period instead of resetting. Omitted keeps the existing setting. Depends on the plan recurring; with recurs_monthly false the response warns that nothing will accumulate.
      - `basis` object: Evidence handles behind this line. Omitted keeps the existing line's basis; supplying one replaces it. Unknown keys are refused rather than stripped.
        - `transaction_ids` string[]: Canonical transaction ids from this workspace that the revision rests on. Omitted or empty keeps none; ids from another workspace are refused.
        - `recurring_candidate_ids` string[]: Recurring candidate ids the revision rests on.
        - `notes` string: Why this evidence supports the revision, in the agent's words.
    - `remove` string[], required: At least one category to remove, when no line is set.

## Response `200`

Envelope with the revised active budget plan, its lines, the superseded plan ids, and the per-line changes made (each naming the fields that changed). A revision that cannot be applied as stated returns 400 with budget_plan_missing, budget_currency_mismatch, budget_revision_unmatched_categories, or invalid_budget_plan_revision.

- 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)
