# get_finance_forecast

## What it answers

Read the Finance Forecast: planned AGI, AGI capacity, expenses and the cascade (delivery profit, overhead, profit, margins) per month or quarter with a period total, and each month's delivery margin target with its source. Same arithmetic as the Finance Forecast page. Figures are planned from the Projects, Payroll and Expenses grids, not actuals. Required range.from and range.to are inclusive YYYY-MM months; basis is month (default) or quarter; at most 60 periods. Pending projects are excluded unless includePendingProjects is true. Requires the current connection owner to have view access to the Projects grid on this account; choose projectGridId when PROJECT_GRID_REQUIRED lists several. Every ratio is a ratio of summed parts and is null when an input is missing. No per-person compensation is returned. Sheet-backed input grids carry an INPUTS_NOT_VERIFIED caveat. Read definitions and caveats before interpreting figures. Read parakeeto://methodology for shared response conventions and INVALID_ARGUMENT guidance.

Read-only.

## Arguments

| Argument | Type | Required | Default | Allowed values |
| --- | --- | --- | --- | --- |
| `account` | string (uuid) | no | — | — |
| `includeDefinitions` | boolean | no | `true` | — |
| `projectGridId` | string (uuid) | no | — | — |
| `range` | object | yes | — | — |
| `range.from` | string | yes | — | pattern `^\d{4}-(?:0[1-9]\|1[0-2])$` |
| `range.to` | string | yes | — | pattern `^\d{4}-(?:0[1-9]\|1[0-2])$` |
| `includePendingProjects` | boolean | no | `false` | — |
| `basis` | string | no | `"month"` | `"month"`, `"quarter"` |

## Returned fields

The result is an envelope: `ok: true` with `data`, or `ok: false` with `error`. Error codes: `MODEL_CALCULATOR_ACCESS_REQUIRED`, `PAYROLL_GRID_MISSING`, `PAYROLL_GRID_REQUIRED`, `PROJECT_GRID_REQUIRED`, `EXPENSE_GRID_REQUIRED`, `PAYROLL_ENTRY_REFERENCE_STALE`, `ACCOUNT_NOT_FOUND`, `ACCOUNT_CONFIGURATION_MISSING`, `NO_IMPORTED_TIME`, `NOTHING_IMPORTED`, `ACCOUNT_REQUIRED`, `NO_REACHABLE_ACCOUNTS`, `FEATURE_NOT_ENTITLED`, `PERMISSION_DENIED`, `CALCULATION_FAILED`, `INTERNAL_ERROR`, `INVALID_ARGUMENT`.

- `data`: object
  - `data.account`: string (uuid)
  - `data.projectGrid`: object
    - `data.projectGrid.id`: string (uuid)
    - `data.projectGrid.name`: string
  - `data.range`: object
    - `data.range.from`: string (pattern `^\d{4}-(?:0[1-9]|1[0-2])$`)
    - `data.range.to`: string (pattern `^\d{4}-(?:0[1-9]|1[0-2])$`)
  - `data.includesPendingProjects`: boolean
  - `data.gridFreshness`: array of object
    - `data.gridFreshness[].kind`: string (`"payroll"`, `"expense"`, `"project"`)
    - `data.gridFreshness[].gridId`: string (uuid)
    - `data.gridFreshness[].name`: string
    - `data.gridFreshness[].storage`: string (`"sheet"`, `"database"`)
    - `data.gridFreshness[].sheetRefreshedAt`: string (date-time) or null
  - `data.definitions`: map of string to string, optional
    - `data.definitions.*`: string
  - `data.caveats`: array of object
    - `data.caveats[].code`: string
    - `data.caveats[].message`: string
  - `data.basis`: string (`"month"`, `"quarter"`)
  - `data.freshness`: array of object
    - `data.freshness[].source`: string (`"time-entries"`, `"role-task-mappings"`, `"annual-days"`, `"dashboard-inputs"`)
    - `data.freshness[].everCompleted`: boolean
    - `data.freshness[].completedAt`: string (date-time) or null
  - `data.periods`: array of object
    - `data.periods[].label`: string
    - `data.periods[].startDate`: string (pattern `^\d{4}-\d{2}-\d{2}$`)
    - `data.periods[].endDate`: string (pattern `^\d{4}-\d{2}-\d{2}$`)
    - `data.periods[].agi`: string or null (pattern `^-?\d+(?:\.\d+)?$`)
    - `data.periods[].agiCapacity`: string or null (pattern `^-?\d+(?:\.\d+)?$`)
    - `data.periods[].expenses`: string or null (pattern `^-?\d+(?:\.\d+)?$`)
    - `data.periods[].deliveryExpenses`: string or null (pattern `^-?\d+(?:\.\d+)?$`)
    - `data.periods[].profit`: string or null (pattern `^-?\d+(?:\.\d+)?$`)
    - `data.periods[].profitAtCapacity`: string or null (pattern `^-?\d+(?:\.\d+)?$`)
    - `data.periods[].deliveryMargin`: string or null (pattern `^-?\d+(?:\.\d+)?$`)
    - `data.periods[].deliveryMarginAtCapacity`: string or null (pattern `^-?\d+(?:\.\d+)?$`)
    - `data.periods[].capacityFilled`: string or null (pattern `^-?\d+(?:\.\d+)?$`)
    - `data.periods[].deliveryProfit`: string or null (pattern `^-?\d+(?:\.\d+)?$`)
    - `data.periods[].overhead`: string or null (pattern `^-?\d+(?:\.\d+)?$`)
    - `data.periods[].profitMargin`: string or null (pattern `^-?\d+(?:\.\d+)?$`)
    - `data.periods[].profitShare`: string or null (pattern `^-?\d+(?:\.\d+)?$`)
    - `data.periods[].deliveryMarginTarget`: string or null (pattern `^-?\d+(?:\.\d+)?$`)
  - `data.total`: object
    - `data.total.agi`: string or null (pattern `^-?\d+(?:\.\d+)?$`)
    - `data.total.agiCapacity`: string or null (pattern `^-?\d+(?:\.\d+)?$`)
    - `data.total.expenses`: string or null (pattern `^-?\d+(?:\.\d+)?$`)
    - `data.total.deliveryExpenses`: string or null (pattern `^-?\d+(?:\.\d+)?$`)
    - `data.total.profit`: string or null (pattern `^-?\d+(?:\.\d+)?$`)
    - `data.total.profitAtCapacity`: string or null (pattern `^-?\d+(?:\.\d+)?$`)
    - `data.total.deliveryMargin`: string or null (pattern `^-?\d+(?:\.\d+)?$`)
    - `data.total.deliveryMarginAtCapacity`: string or null (pattern `^-?\d+(?:\.\d+)?$`)
    - `data.total.capacityFilled`: string or null (pattern `^-?\d+(?:\.\d+)?$`)
    - `data.total.deliveryProfit`: string or null (pattern `^-?\d+(?:\.\d+)?$`)
    - `data.total.overhead`: string or null (pattern `^-?\d+(?:\.\d+)?$`)
    - `data.total.profitMargin`: string or null (pattern `^-?\d+(?:\.\d+)?$`)
    - `data.total.profitShare`: string or null (pattern `^-?\d+(?:\.\d+)?$`)
    - `data.total.deliveryMarginTarget`: string or null (pattern `^-?\d+(?:\.\d+)?$`)
  - `data.targets`: object
    - `data.targets.profitMargin`: string (pattern `^-?\d+(?:\.\d+)?$`)
    - `data.targets.deliveryMargin`: object
      - `data.targets.deliveryMargin.months`: array of object
        - `data.targets.deliveryMargin.months[].month`: string (pattern `^\d{4}-(?:0[1-9]|1[0-2])$`)
        - `data.targets.deliveryMargin.months[].target`: string (pattern `^-?\d+(?:\.\d+)?$`)
        - `data.targets.deliveryMargin.months[].source`: string (`"imported"`, `"account-settings"`, `"benchmark"`)

On failure:

- `error`: object
  - `error.code`: string (`"MODEL_CALCULATOR_ACCESS_REQUIRED"`, `"PAYROLL_GRID_MISSING"`, `"PAYROLL_GRID_REQUIRED"`, `"PROJECT_GRID_REQUIRED"`, `"EXPENSE_GRID_REQUIRED"`, `"PAYROLL_ENTRY_REFERENCE_STALE"`, `"ACCOUNT_NOT_FOUND"`, `"ACCOUNT_CONFIGURATION_MISSING"`, `"NO_IMPORTED_TIME"`, `"NOTHING_IMPORTED"`, `"ACCOUNT_REQUIRED"`, `"NO_REACHABLE_ACCOUNTS"`, `"FEATURE_NOT_ENTITLED"`, `"PERMISSION_DENIED"`, `"CALCULATION_FAILED"`, `"INTERNAL_ERROR"`, `"INVALID_ARGUMENT"`)
  - `error.argument`: string, optional (`minLength: 1`)
  - `error.message`: string
  - `error.accounts`: array of object, optional
    - `error.accounts[].id`: string (uuid)
    - `error.accounts[].name`: string
  - `error.payrollGrids`: array of object, optional
    - `error.payrollGrids[]`: same shape as `error.accounts[]`
  - `error.projectGrids`: array of object, optional
    - `error.projectGrids[]`: same shape as `error.accounts[]`
  - `error.expenseGrids`: array of object, optional
    - `error.expenseGrids[]`: same shape as `error.accounts[]`
  - `error.context`: object, optional
    - `error.context.account`: object
      - Further fields: see the response.
    - `error.context.imports`: array of object
      - Further fields: see the response.
    - `error.context.hasTimeEntries`: boolean
    - `error.context.reports`: array of object
      - Further fields: see the response.

## Definitions

Returned in `definitions` when `includeDefinitions` is true (the default). It is a map of string to string: each key names a field and each value is its definition text.

## Caveats

Codes are not enumerated in the schema; read each `code` and `message`.

Read every caveat before interpreting a figure. See [methodology](</methodology.md>) on how to communicate caveats and data-quality conditions.

## Example call

```json
{
  "name": "get_finance_forecast",
  "arguments": {
    "range": {
      "from": "2026-01",
      "to": "2026-03"
    }
  }
}
```

Add `account` with an identifier from `list_accounts`; omit it only when the connection reaches exactly one account.
