# get_capacity_plan

## What it answers

Read the account's weekly capacity and planned hours. Requires range.from and range.to (real calendar dates, years 0100–9998; earliest start 0100-01-04), at most 156 intersecting Monday-start weeks. The window expands to Monday through Sunday. Optional breakdowns: role, task. Pending projects are off by default, as on the Capacity Plan page: planned hours count Active, Complete and blank-Status projects (a blank Status counts as Active). includePendingProjects true also counts Pending. Optional scenarioId (from list_scenarios) applies that saved scenario's Included payroll rows exactly as the page does; omitted includePendingProjects then takes the scenario's stored Include pending setting, and the scenario's model-input overrides do not change this report (an overrides-not-applied caveat says so). Optional statuses: Pending, Active, Complete; takes precedence over the default, filters included projects' planned hours and counts blank statuses as Active; it cannot be combined with includePendingProjects. An empty list means no planned projects. Payroll capacity is unchanged. Omit account only when the key reaches exactly one account. No person-level or compensation data is returned. 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` | — |
| `range` | object | yes | — | — |
| `range.from` | string | yes | — | pattern `^\d{4}-\d{2}-\d{2}$` |
| `range.to` | string | yes | — | pattern `^\d{4}-\d{2}-\d{2}$` |
| `statuses` | array of string | no | — | — |
| `breakdowns` | array of string | no | — | — |
| `scenarioId` | string (uuid) | no | — | — |
| `includePendingProjects` | boolean | no | — | — |

## 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.window`: object
    - `data.window.startDate`: string (pattern `^\d{4}-\d{2}-\d{2}$`)
    - `data.window.endDate`: string (pattern `^\d{4}-\d{2}-\d{2}$`)
  - `data.weeks`: array of object
    - `data.weeks[].weekStart`: string (pattern `^\d{4}-\d{2}-\d{2}$`)
    - `data.weeks[].overall`: object
      - `data.weeks[].overall.grossCapacity`: string, optional (pattern `^-?\d+(?:\.\d+)?$`)
      - `data.weeks[].overall.deliveryCapacity`: string (pattern `^-?\d+(?:\.\d+)?$`)
      - `data.weeks[].overall.plannedHours`: string (pattern `^-?\d+(?:\.\d+)?$`)
  - `data.breakdowns`: object, optional
    - `data.breakdowns.role`: object, optional
      - `data.breakdowns.role.categories`: array of string
      - `data.breakdowns.role.weeks`: array of object
        - `data.breakdowns.role.weeks[].weekStart`: string (pattern `^\d{4}-\d{2}-\d{2}$`)
        - `data.breakdowns.role.weeks[].overall`: same shape as `data.weeks[].overall`
        - `data.breakdowns.role.weeks[].categories`: array of object
          - `data.breakdowns.role.weeks[].categories[].grossCapacity`: string, optional (pattern `^-?\d+(?:\.\d+)?$`)
          - `data.breakdowns.role.weeks[].categories[].deliveryCapacity`: string (pattern `^-?\d+(?:\.\d+)?$`)
          - `data.breakdowns.role.weeks[].categories[].plannedHours`: string (pattern `^-?\d+(?:\.\d+)?$`)
          - `data.breakdowns.role.weeks[].categories[].category`: string
    - `data.breakdowns.task`: same shape as `data.breakdowns.role`, optional
  - `data.projectStatusFilter`: object
    - One of:
      - Variant 1 (`mode` is `"all"`, `includesBlank` is `true`):
        - `data.projectStatusFilter.mode`: string (`"all"`)
        - `data.projectStatusFilter.includesBlank`: boolean (`true`)
      - Variant 2 (`mode` is `"filtered"`):
        - `data.projectStatusFilter.mode`: string (`"filtered"`)
        - `data.projectStatusFilter.statuses`: array of string
        - `data.projectStatusFilter.includesBlank`: boolean
  - `data.includesPendingProjects`: boolean
  - `data.scenario`: object, optional
    - `data.scenario.id`: string (uuid)
    - `data.scenario.name`: string
    - `data.scenario.revision`: string
    - `data.scenario.includePending`: boolean
    - `data.scenario.overrides`: object
      - `data.scenario.overrides.grossCapacity`: string, optional (pattern `^-?\d+(?:\.\d+)?$`)
      - `data.scenario.overrides.modelAbr`: string, optional (pattern `^-?\d+(?:\.\d+)?$`)
      - `data.scenario.overrides.modelUtilization`: string, optional (pattern `^-?\d+(?:\.\d+)?$`)
      - `data.scenario.overrides.deliveryPayrollBudget`: string, optional (pattern `^-?\d+(?:\.\d+)?$`)
      - `data.scenario.overrides.deliveryExpenseBudget`: string, optional (pattern `^-?\d+(?:\.\d+)?$`)
      - `data.scenario.overrides.smPayrollBudget`: string, optional (pattern `^-?\d+(?:\.\d+)?$`)
      - `data.scenario.overrides.smExpenseBudget`: string, optional (pattern `^-?\d+(?:\.\d+)?$`)
      - `data.scenario.overrides.adminPayrollBudget`: string, optional (pattern `^-?\d+(?:\.\d+)?$`)
      - `data.scenario.overrides.adminExpenseBudget`: string, optional (pattern `^-?\d+(?:\.\d+)?$`)
      - `data.scenario.overrides.facilitiesExpenseBudget`: string, optional (pattern `^-?\d+(?:\.\d+)?$`)
    - `data.scenario.missingRows`: string (pattern `^-?\d+(?:\.\d+)?$`)
  - `data.hasPlannedActivity`: boolean
  - `data.message`: string
  - `data.definitions`: object, optional
    - `data.definitions.presentation`: string
    - `data.definitions.capacity`: string
    - `data.definitions.plannedHours`: string
    - `data.definitions.grossCapacity`: string
    - `data.definitions.comparisons`: string
    - `data.definitions.categoryOrder`: string
  - `data.inputs`: array (`minItems: 2`; `maxItems: 2`)
  - `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.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.freshnessExplanation`: string
  - `data.caveats`: array of object
    - One of:
      - Variant 1 (`code` is `"allocation-mismatch"`, `source` is `"payroll"`):
        - `data.caveats[].code`: string (`"allocation-mismatch"`)
        - `data.caveats[].message`: string
        - `data.caveats[].source`: string (`"payroll"`)
      - Variant 2 (`code` is `"category-order"`, `source` is `"capacity-plan"`):
        - `data.caveats[].code`: string (`"category-order"`)
        - `data.caveats[].source`: string (`"capacity-plan"`)
        - `data.caveats[].message`: string
        - `data.caveats[].role`: string (`"source"`, `"deterministic-fallback"`)
        - `data.caveats[].task`: string (`"source"`, `"deterministic-fallback"`)
        - `data.caveats[].roleExplanation`: string
        - `data.caveats[].taskExplanation`: string
      - Variant 3 (`code` is `"overrides-not-applied"`):
        - `data.caveats[].code`: string (`"overrides-not-applied"`)
        - `data.caveats[].message`: string
      - Variant 4 (`code` is `"scenario-rows-missing"`):
        - `data.caveats[].code`: string (`"scenario-rows-missing"`)
        - `data.caveats[].message`: string

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). Each value is the definition text for that field.

- `presentation`
- `capacity`
- `plannedHours`
- `grossCapacity`
- `comparisons`
- `categoryOrder`

## Caveats

- `allocation-mismatch`. Also carries `source`.
- `category-order`. Also carries `source`, `role`, `task`, `roleExplanation`, `taskExplanation`.
- `overrides-not-applied`.
- `scenario-rows-missing`.

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_capacity_plan",
  "arguments": {
    "range": {
      "from": "2026-09-01",
      "to": "2026-09-30"
    }
  }
}
```

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