> ## Documentation Index
> Fetch the complete documentation index at: https://docs.qobra.co/llms.txt
> Use this file to discover all available pages before exploring further.

# recalculate_statements

> Recalculate the statements of some users over months, quarters or years, so they reflect the data as it stands now.

Recalculate the statements of some users over months, quarters or years, so
they reflect the data as it stands now.

Edits made through the other write tools reach no statement until it is
recalculated. This covers
[`create_record`](https://docs.qobra.co/mcp_documentation/tools/create_record),
[`update_record`](https://docs.qobra.co/mcp_documentation/tools/update_record),
[`split_record`](https://docs.qobra.co/mcp_documentation/tools/split_record),
[`update_quota_values`](https://docs.qobra.co/mcp_documentation/tools/update_quota_values) and
[`update_exchange_rates`](https://docs.qobra.co/mcp_documentation/tools/update_exchange_rates). Call
this tool after them, with the users and the periods the change touches.

A change in one month moves the months after it too, such as a carried balance
or a year-to-date total. Cover every month it affects in the same call: Qobra
computes the months of a call oldest first, while separate calls run side by
side.

A call takes one period for any number of users, or several periods for a
single user. Several periods are recalculated as one span from the first month
to the last, since a month reads its balance from the one before. When a change
reaches past one period for several users, such as past a year end, call once
per user with all their periods, never once per period.

The recalculation runs in the background and the call returns at once, with
what became of each user's statement for each month:

* `queued`: its recalculation is launched.
* `unlicensed`: recalculated, but its compensations stay empty until the user
  gets a license.
* `locked`: left as it is. A locked statement is never recalculated.
* `not_found`: no statement you can see for this month.

To know when the recalculation is done, read the statements'
`calculation_status` with
[`list_statements`](https://docs.qobra.co/mcp_documentation/tools/list_statements) or
[`get_statement`](https://docs.qobra.co/mcp_documentation/tools/get_statement). It reads
`need_refresh` or `calculating` while it runs, and `ready` once the amounts are
current.

`user_ids` takes user ids or exact emails. Only users you can see can be named,
and a month where you cannot see the statement reads `not_found`. Pass
`sandbox_id` to recalculate a sandbox's statements instead of the live ones.

Available only where the Qobra write tools beta is enabled.

## Parameters

> [accordion] Body
>
> **periods** `string[]` *required*
>
> The periods to recalculate, each a month (YYYY-MM, e.g. 2026-03), a quarter
> (YYYY-QX, e.g. 2026-Q3) or a year (YYYY, e.g. 2026). Quarters and years
> follow the company's fiscal calendar, as get\_identity reports it. Several
> periods only when `user_ids` names a single user; the months between them
> are recalculated too.
>
> **user\_ids** `string[]` *required*
>
> The users whose statements to recalculate: the ids list\_users returns, or
> their exact emails. As many as needed over one period; a single one when
> `periods` lists several.
>
> **sandbox\_id** `string`
>
> Id of the sandbox whose statements to recalculate instead of the live ones —
> the id list\_sandboxes returns. Omit it to recalculate the live statements,
> the company's real compensation data. Only a sandbox id is accepted here —
> never a sandbox name, and never the live environment's own id.

## Example

Recalculate two users over the third quarter:

```json theme={null}
{
  "periods": ["2026-Q3"],
  "user_ids": ["66a0b1c2d3e4f50012340001", "jane.doe@example.com"]
}
```

## Response

> [accordion] Body
>
> **total** `integer`
>
> Statements the call covers: one per user and month.
>
> **counts\_by\_outcome** `object[]`
>
> Per-outcome rollup of all `total` statements, listed in `recalculations` or
> not.
>
> **object properties**
>
> **outcome** `string`
>
> One of: `queued`, `unlicensed`, `locked`, `not_found`.
>
> **count** `integer`
>
> Statements with this outcome. An outcome absent from the list has none.
>
> **recalculations** `object[]`
>
> One row per user and month, the statements not queued first, then the queued
> ones, each in the order you passed the users, months oldest first. At most
> 100 rows: past them, counts\_by\_outcome still counts the rest, and
> list\_statements reads their calculation\_status.
>
> **object properties**
>
> **user** `object`
>
> **object properties**
>
> **id** `string`
>
> **email** `string`
>
> **name** `string`
>
> **period** `string`
>
> **outcome** `string`
>
> What became of this user's statement for this month: queued (its
> recalculation is launched), unlicensed (recalculated, but its
> compensations stay empty until the user gets a license), locked (left as
> it is: a locked statement is never recalculated), not\_found (no
> statement you can see for this month, so nothing to recalculate). One
> of: `queued`, `unlicensed`, `locked`, `not_found`.
>
> **statement\_id** `string`
>
> The statement's id, to follow its calculation\_status with get\_statement.
> Null when outcome is not\_found, and while the statement has no line:
> list\_statements and get\_statement show it once its recalculation gives
> it one.
>
> **resource\_url** `string`
>
> Deep link to the statement in the Qobra web app. Null whenever
> statement\_id is.
