Skip to content

Budgets

Budgets let you set spending targets by account and compare actual performance against plan. This feature requires the CFO Suite add-on.

Create a Budget

bash
curl -X POST "https://api.ondayzero.com/api/v1/budgets" \
  -H "Authorization: Bearer dz_your_token_here" \
  -H "x-business-id: YOUR_BUSINESS_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "FY2026 Operating Budget",
    "fiscal_year": 2026,
    "start_date": "2026-01-01",
    "end_date": "2026-12-31",
    "period_type": "monthly",
    "description": "Board-approved operating plan"
  }'

name (up to 255 characters), fiscal_year (2000-2100), start_date and end_date are required, and end_date must be after start_date. period_type is monthly (default), quarterly or annual. Optional: description, notes and source_scenario_id (the CFO projection scenario that generated the budget). The response is 201 with the budget in draft status, plus summary fields line_count, total_budgeted_revenue, total_budgeted_expenses and budgeted_net_income (cents). GET /api/v1/budgets/{budget_id} returns the budget with all its lines.

Add Budget Lines

Each line ties a ledger account to twelve calendar-month amounts (in cents). ledger_id must be a ledger of your business (404 otherwise):

bash
curl -X POST "https://api.ondayzero.com/api/v1/budgets/{budget_id}/lines" \
  -H "Authorization: Bearer dz_your_token_here" \
  -H "x-business-id: YOUR_BUSINESS_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "ledger_id": "EXPENSE_LEDGER_UUID",
    "jan_amount": 500000,
    "feb_amount": 500000,
    "mar_amount": 500000,
    "apr_amount": 550000,
    "may_amount": 550000,
    "jun_amount": 550000,
    "jul_amount": 600000,
    "aug_amount": 600000,
    "sep_amount": 600000,
    "oct_amount": 650000,
    "nov_amount": 650000,
    "dec_amount": 650000,
    "notes": "Includes planned Q3 headcount"
  }'

Amounts are in cents. 500000 = $5,000.00 for that month. Months you omit default to 0. jan_amount is January of whichever calendar year a date falls in, regardless of fiscal_year.

A line in the response also carries ledger_name, ledger_type, annual_amount and quarterly_amounts (q1 to q4).

GET /api/v1/budgets/{budget_id}/lines lists lines; PATCH / DELETE /api/v1/budgets/{budget_id}/lines/{line_id} change or remove one. PATCH takes the twelve month amounts and notes (not ledger_id). A ledger can appear on a budget only once (VALIDATION_085), and lines can only be added, edited or removed while the budget is a draft (VALIDATION_084 / VALIDATION_086 / VALIDATION_087) — copy an active budget to revise it. Adding a line is 201.

List Budgets

bash
curl "https://api.ondayzero.com/api/v1/budgets?fiscal_year=2026&status=active" \
  -H "Authorization: Bearer dz_your_token_here" \
  -H "x-business-id: YOUR_BUSINESS_ID"

Filter Parameters

Parameter Type Description
status string draft, active, closed. Any other value returns 400 (GEN_002)
fiscal_year integer Filter by year (e.g., 2026)
search string Match on budget name

Plus the standard pagination parameters.

Activate a Budget

Only one budget is active at a time. Activating a budget makes it the working budget and sets the previously active one to closed. Activating a budget that is already active is a 400 (VALIDATION_083):

bash
curl -X POST "https://api.ondayzero.com/api/v1/budgets/{budget_id}/activate" \
  -H "Authorization: Bearer dz_your_token_here" \
  -H "x-business-id: YOUR_BUSINESS_ID"

PATCH /api/v1/budgets/{budget_id} edits name, description, notes, start_date and end_date, and DELETE removes a budget; both work on a draft only (VALIDATION_081 / VALIDATION_082). fiscal_year and period_type cannot be changed after creation.

Budget vs. Actual

Compare budgeted amounts to actual spending for a date range:

bash
curl "https://api.ondayzero.com/api/v1/budgets/{budget_id}/vs-actual?start_date=2026-04-01&end_date=2026-06-30" \
  -H "Authorization: Bearer dz_your_token_here" \
  -H "x-business-id: YOUR_BUSINESS_ID"

Both dates are required. The response has a revenue and an expenses section (only revenue and expense ledgers are included), each with items, total_budget, total_actual, total_variance and total_variance_percent, plus budgeted_net_income, actual_net_income, net_income_variance, net_income_variance_percent and net_income_variance_type.

Each item has budget_amount, actual_amount, variance_amount, variance_percent and variance_type (favorable, unfavorable or neutral). The budgeted amount sums the line's calendar-month amounts for every month that starts inside both your date range and the budget's own start_date to end_date; a partial month counts in full. variance_amount is budget minus actual, so a positive number means under budget, and variance_percent is that variance as a percentage of the budgeted amount (null when the budget is 0). An expense under budget is favorable; revenue above budget is favorable. actual_amount is the net of debits minus credits posted to the ledger in the range.

Forecasts

Generate spending forecasts from historical actuals:

bash
curl -X POST "https://api.ondayzero.com/api/v1/budgets/forecast" \
  -H "Authorization: Bearer dz_your_token_here" \
  -H "x-business-id: YOUR_BUSINESS_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "method": "seasonal",
    "lookback_months": 24,
    "forecast_months": 12,
    "growth_rate_percent": 5,
    "use_seasonality": true,
    "include_cash_flow": true
  }'

All fields are optional. method is linear_trend (default), moving_average, seasonal or year_over_year; lookback_months (3-60) and forecast_months (1-36) default to 12; growth_rate_percent is an integer from -50 to 100 (default 0); use_seasonality defaults to false and include_cash_flow to true. The forecast starts at the first day of the current month and covers revenue and expense ledgers. The response has forecast_start, forecast_end, revenue_items and expense_items (each ledger with historical_average, historical_trend and monthly periods of forecasted_amount, confidence_low and confidence_high), totals, forecasted_net_income, a monthly cash_flow_forecast when requested, and projected_ending_cash.

Save a reusable set of parameters with POST /api/v1/budgets/forecast/configs (201; name is required, plus the same method, lookback_months, forecast_months, growth_rate_percent, use_seasonality and an optional notes) and list them with GET /api/v1/budgets/forecast/configs. Saved configs are not applied automatically; pass their values to POST /budgets/forecast.

Copy a Budget

Duplicate an existing budget — lines included — as the starting point for the next period, optionally scaling every amount:

bash
curl -X POST "https://api.ondayzero.com/api/v1/budgets/{budget_id}/copy" \
  -H "Authorization: Bearer dz_your_token_here" \
  -H "x-business-id: YOUR_BUSINESS_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "FY2027 Operating Budget",
    "fiscal_year": 2027,
    "start_date": "2027-01-01",
    "end_date": "2027-12-31",
    "adjustment_percent": 5
  }'

name, fiscal_year, start_date and end_date are required; adjustment_percent (an integer from -100 to 1000, default 0) applies to all amounts (5 = +5%, -10 = −10%). The copy is created as a draft with the source's period_type and description, and the response (201) includes its lines. The source budget can be in any status.