---
title: "Create Information Block"
method: POST
path: "/extensions/roboledger/{graph_id}/operations/create-information-block"
tags: ["RoboLedger: Information Blocks"]
---

# Create Information Block

`POST /extensions/roboledger/{graph_id}/operations/create-information-block`

## Request

- Base URL: `https://api.robosystems.ai` (the document declares no server; this is the origin it was published from)
- URL: `https://api.robosystems.ai/extensions/roboledger/{graph_id}/operations/create-information-block`
- Auth: one of:
  - API key in header `X-API-Key`
  - HTTP bearer

Generic Information Block construction entry. `block_type` selects the registered block type; `payload` is validated against that type's creation schema at dispatch. Schedule dispatches to the existing Schedule machinery; statement block types raise 501 (use create-report instead). Authoring schedules for a close? Call `get-close-playbook` (mode='initiate') first — one schedule is a single debit/credit element pair, so multi-line entries become multiple schedules, and element ids must be real (discover via get-graph-schema / get-unmapped-elements / suggest-mapping).

**Idempotency**: supply an `Idempotency-Key` header to make safe retries; replays within 24 hours return the same envelope. Reusing the key with a different body returns HTTP 409 Conflict.

## Path parameters

- `graph_id` string, required

## Headers

- `Idempotency-Key` string, nullable

## Request body

- union: Create an Information Block. The body is a discriminated union on `block_type`: pick the arm matching the block type you want to create. The schedule arm carries a fully typed payload; statement and metric arms accept an untyped payload but currently return HTTP 501 (statements are constructed via `create-report`; metric construction is pending).
  - CreateScheduleArm: Create-information-block body for `block_type="schedule"`. Carries a typed schedule payload — full schedule shape is exposed inline in the OpenAPI schema so SDK callers see every required field.
    - `block_type` 'schedule', required: Discriminator value selecting this arm.
    - `payload` CreateScheduleRequest, required
      - `name` string, required: Schedule name
      - `entity_id` string, nullable: The entity whose books the schedule belongs to, by id. Omit for the group parent. Its facts, obligations and closing entries land in that entity's books, against that entity's own accounts.
      - `taxonomy_id` string, nullable: Taxonomy ID (auto-creates if omitted)
      - `element_ids` string[], required: CoA element ids the schedule touches (the `id` from get-unmapped-elements, not taxonomy qnames) — typically the same debit + credit ids used in entry_template.
      - `period_start` string, date, required: First period start
      - `period_end` string, date, required: Last period end
      - `monthly_amount` integer, required: Monthly amount in cents
      - `entry_template` EntryTemplateRequest, required
        - `debit_element_id` string, required: CoA element id to debit (e.g. Depreciation Expense). This is a chart-of-accounts element id — the `id` returned by get-unmapped-elements / get-graph-schema — NOT a taxonomy qname.
        - `credit_element_id` string, required: CoA element id to credit (e.g. Accumulated Depreciation). A chart-of-accounts element id (see get-unmapped-elements), not a taxonomy qname. One template = one debit/credit pair; model a multi-account entry as several schedules.
        - `entry_type` 'standard' | 'adjusting' | 'closing' | 'reversing': Entry type for generated entries
        - `memo_template` string: Memo template ({structure_name} is replaced)
        - `auto_reverse` boolean: Auto-generate a reversing entry on the first day of the next period
      - `schedule_metadata` ScheduleMetadataRequest
        - `method` string: Calculation method. 'straight_line' (default) distributes `monthly_amount` evenly across periods with the final period absorbing rounding. 'custom' requires `periodic_amounts` — the generator uses those values verbatim instead of computing. Other strings are labels only; fact values still come from `monthly_amount` or `periodic_amounts`.
        - `original_amount` integer: Cost basis in cents
        - `residual_value` integer: Salvage value in cents. The schedule expenses `original_amount` less this; net book value ends at it.
        - `useful_life_months` integer: Useful life in months
        - `asset_element_id` string, nullable: BS asset element for net book value
        - `booked_on` string, date, nullable: The date the cost went on the books, when that is before the schedule's first period: a policy paid in December that starts amortizing in January, or an asset bought the month before it is placed in service. From this date until the first period the schedule carries its full cost, so the schedule reconciliation does not report that balance as unscheduled. Leave it out when the cost is booked in the first period.
        - `periodic_amounts` integer[], nullable: Explicit per-period amounts in cents. When set, the generator uses these values instead of `monthly_amount` — enabling non-straight-line schedules (effective-interest bond discount amortization, day-count interest accrual, variable lease payments, pre-computed effective-yield curves, etc.). Length must match the number of monthly periods between `period_start` and `period_end`; sum must equal `original_amount` less `residual_value` exactly. The auto-generated SumEquals rule proves that total regardless of the curve shape.
      - `closed_through` string, date, nullable: Watermark for onboarding. Facts with period_end ≤ this date are flagged 'historical' and their schedule_entry_due obligations are emitted 'voided', so the close workflow starts drafting at the first open period. Defaults to the calendar's history end: the last day of its closed_through month (calendar '2026-05' → '2026-05-31'), or the day before its first month when nothing has closed yet. An earlier date is raised to it, since an obligation there could never post; set a later one only to treat more months as already booked.
      - `source_transaction_id` string, nullable: Free-form reference to the originating GL transaction (e.g. an import ID, ledger entry ID, or external system key). Stored in artifact_mechanics for audit; no FK constraint.
  - CreateRollforwardArm: Create-information-block body for `block_type="rollforward"`. Carries a typed rollforward payload. The block decomposes the period change in a BS source element across the declared attribution filters.
    - `block_type` 'rollforward', required: Discriminator value selecting this arm.
    - `payload` CreateRollforwardRequest, required: Create a rollforward Information Block. Mirrors :class:`CreateScheduleRequest` in shape. The block decomposes the period change in `bs_source_qname` across the declared attribution filters. Residual (Δ BS - Σ filter matches) falls back to the default change tag — or, if no default is declared, surfaces as an unattributed fact tagged with a synthetic residual concept.
      - `name` string, required: Human-readable block name.
      - `bs_source_qname` string, required: QName of the balance-sheet element whose period delta this block decomposes. Resolved to `bs_source_element_id` at create time.
      - `default_change_tag_qname` string, nullable: QName of the fallback flow concept (Tier 1 default change tag). Residual amount — Δ BS minus the sum of filter-matched amounts — is attributed to this concept. When omitted, residual surfaces unattributed; the validation_mode setting governs whether that's a hard error.
      - `attribution_filters` AttributionFilter[]: Filter predicates routing LineItems to flow concepts.
        - `target_qname` string, required: QName of the flow concept this filter produces facts for — e.g. `rs-gaap:ProceedsFromIssuanceOfCommonStock`. Resolved to `target_element_id` at create time.
        - `target_element_id` string, nullable: Resolved element id for `target_qname`. Null at create time; populated by the handler before persistence. Round-tripped in the envelope.
        - `predicate` LineItemMetadataPredicate, required: Filter ledger LineItems by flow concept. The single predicate kind shipped to date. `values` are flow-concept qnames — mini's `TransactionDescriptionCode` values, rs-gaap flow concepts (what the enrichment classifier emits for QuickBooks data), future XBRL GL `GenericFlowCategory` codes. The engine resolves them to element_ids and matches the first-class `LineItem.flow_element_id` FK; matched lines aggregate signed into the attributed fact for the period. `field` is accepted but ignored: the flow tag lives in the typed `flow_element_id` FK, not in JSONB metadata. It stays on the wire so existing request bodies keep validating.
          - `kind` 'line_item_metadata_field': Discriminator value selecting this predicate shape.
          - `field` string: Accepted but ignored. The flow tag lives in the typed `flow_element_id` FK, not JSONB metadata. Retained for wire-compatibility.
          - `values` string[], required: Flow-concept qnames that route to this filter's target concept. A LineItem matches when its `flow_element_id` is one of the elements named here AND the line falls within the rollforward's period.
      - `validation_mode` 'strict' | 'residual_as_default' | 'warn_only': How the renderer arbitrates when Σ filter matches != Δ BS. `strict` raises; `residual_as_default` emits the residual as a default-tag fact (the common case); `warn_only` logs and lets the imbalance pass.
      - `taxonomy_id` string, nullable: Owning taxonomy id (auto-resolved from `bs_source_qname` when omitted).
  - CreateForecastArm: Create-information-block body for `block_type="forecast"`. Carries a typed forecast payload — the authored scenario container: scenario identity, horizon, base period, lever assertions on `rs-driver:*` catalog elements. Run `compute-forecast` after creating to derive the forward months.
    - `block_type` 'forecast', required: Discriminator value selecting this arm.
    - `payload` CreateForecastRequest, required: Create a forecast block — the authored scenario container. `base_period` defaults to the fiscal calendar's `closed_through_period` (else the newest actual report month) — the walk projects forward from the last closed actuals. The resolved value is stored in the mechanics so recompute is deterministic.
      - `name` string, required: Human-readable scenario name.
      - `scenario_kind` 'budget' | 'forecast' | 'projection': What kind of scenario this is — metadata for display/filtering, not machinery. All kinds compute identically.
      - `horizon_months` integer: Forward months to project past the base period.
      - `base_period` string, nullable: Seed month (`YYYY-MM`) the walk projects forward from. Defaults to the fiscal calendar's closed-through period, else the newest actual report month. Resolved and stored at create time, and it never moves afterwards — every lever is keyed to a month inside `base_period + 1 … + horizon_months`, so moving it would mean restating all of them. `base_anchor` decides whether the walk still *seeds* here once months close under it.
      - `base_anchor` 'seam' | 'fixed': Where the walk takes its opening balances as periods close. `seam` (default) re-anchors on the newest closed month inside the horizon, so the scenario survives a close untouched and its first forward month rolls off real balances. `fixed` pins the walk to `base_period` — the deliberate counterfactual, whose balances are meant to diverge from actuals.
      - `levers` LeverAssertionRequest[], required: Lever assertions — at least one.
        - `qname` string, required: QName of the rs-driver lever element (e.g. `rs-driver:RevenueGrowthRate`).
        - `value` number, nullable: Uniform value asserted for every month of the horizon.
        - `values_by_period` object, nullable: Per-month overrides keyed by `YYYY-MM`. Wins over `value` for the months it names.
      - `line_assertions` LineAssertionRequest[]: Direct statement-line assertions (manual overrides). Each names a calc-DAG leaf and wins over driver rules and carry-forward for the months it asserts.
        - `qname` string, required: QName of the statement leaf to assert (e.g. `rs-gaap:NonoperatingIncomeExpense`). Must be a calc-DAG leaf; rs-driver concepts belong in `levers`.
        - `value` number, nullable: Uniform value asserted for every month of the horizon.
        - `values_by_period` object, nullable: Per-month overrides keyed by `YYYY-MM`. Wins over `value` for the months it names.
      - `line_growth` LineGrowthRequest[]: Per-line growth trajectories. Each names an income-statement leaf and grows it month-over-month at the asserted rate — the generic form of the revenue growth lever, for lines the catalog doesn't drive (opex trajectories, cost-cut ramps).
        - `qname` string, required: QName of the income-statement leaf to grow (e.g. `rs-gaap:ResearchAndDevelopmentExpense`). Must be a calc-DAG duration leaf.
        - `value` number, nullable: Uniform month-over-month growth rate for every month of the horizon (decimal: 0.02 = +2%/mo, -0.05 = -5%/mo).
        - `values_by_period` object, nullable: Per-month rate overrides keyed by `YYYY-MM`. Wins over `value` for the months it names; months named by neither carry the line's prior value (rate 0).
      - `entity_id` string, nullable: The entity the scenario belongs to, by id: its history and its computed months are that entity's books. Omit for the group parent.
  - CreateLegacyArm: Create-information-block body for block types that don't yet have a typed construction path at the API boundary. Statement-family blocks (balance_sheet, income_statement, cash_flow_statement, equity_statement, comprehensive_income) are constructed via `create-report`, not this endpoint. Disclosure structures (regulatory_disclosure) are vocabulary, authored via `create-taxonomy-block`; their facts land when `create-report` picks them. Metric blocks are recognized but their evaluator has not shipped. Calling this endpoint with one of these block types returns HTTP 501 with a hint pointing to the correct construction path.
    - `block_type` 'balance_sheet' | 'income_statement' | 'cash_flow_statement' | 'equity_statement' | 'comprehensive_income' | 'regulatory_disclosure' | 'metric' | 'reconciliation', required: Statement-family or metric block type. The endpoint returns 501 for these values — statements are constructed via `create-report`; metric construction is pending.
    - `payload` object: Untyped payload — typed-arm validation is skipped because the dispatch handler raises 501 before the payload is consumed.

## Response `200`

Successful Response

- OperationEnvelopeInformationBlockEnvelope
  - `operation` string, required: Kebab-case operation name
  - `operationId` string, required: op_-prefixed ULID for audit and SSE correlation
  - `status` 'completed' | 'pending' | 'failed', required: Operation lifecycle state
  - `result` InformationBlockEnvelope: The Information Block exchange format. One envelope per block instance. Carries the block's identity + type, Information-Model attributes, the Artifact branch (mechanics + topic/template), and bundled atoms (elements, connections, facts). Rules / dimensions / FactSet / verification_results are present-but- empty for blocks where the upstream content (rule engine, FactSet expand, dimension catalog) has not yet been implemented.
    - `id` string, required
    - `block_type` string, required: Discriminator — 'schedule', …
    - `name` string, required
    - `display_name` string, required: Registry-sourced display label (e.g., 'Schedule').
    - `category` string, required: Registry-sourced sidebar grouping ('Close', 'Reporting', …).
    - `taxonomy_id` string, nullable: Source taxonomy the Structure was seeded from. Always present for currently-registered block types (the Structure → Taxonomy FK is non-null); declared optional to keep the shape forward-compatible with future synthetic blocks that don't originate from a taxonomy.
    - `taxonomy_name` string, nullable: Display name of the source taxonomy.
    - `disclosure_id` string, nullable: Qname of the named Disclosure this block corresponds to (e.g., 'disclosures:BalanceSheet'), when an inbound reportedDisclosure-requiresDisclosure arc identifies one. Null for tenant-authored blocks without a Disclosure mapping.
    - `entity_id` string, nullable: The entity whose books the envelope reads. A schedule, reconciliation or forecast is one entity's own and always reads its owner's; a block shared by the group (statements, metrics) reads the entity asked for, else the group parent. Null on the library and on a graph with no entity yet.
    - `information_model` InformationModelResponse, required: The block's intrinsic shape — concept + member arrangement patterns.
      - `concept_arrangement` string, nullable: roll_up | roll_forward | variance | adjustment | set | arithmetic | textblock. Null for block types where the concept arrangement is implicit in their mechanics.
      - `member_arrangement` string, nullable: is_a | whole_part | nested_whole_part | two_dimension_aggregation | complex_aggregating_whole_part, or null if non-hypercube.
    - `artifact` ArtifactResponse, required: The block's producible-artifact envelope — topic, template, mechanics.
      - `topic` string, nullable: Structure.description — the block's human-readable topic.
      - `renderer_note` string, nullable: e.g. 'in thousands', 'except per share'.
      - `template` object, nullable: Reusable layout (ordering, subtotals, styling) when attached. First-class templates are not yet implemented; this field is always null on currently-shipped block types.
      - `mechanics` union, required
        - ScheduleMechanics: Closing-entry generator mechanics for `block_type='schedule'`. Reads the typed `structures.artifact_mechanics` JSONB column, falling back to `structures.metadata_` for Schedule rows that lack it. `entry_template` and `schedule_metadata` reuse the wire-level request shapes so OpenAPI emits one canonical type per concept.
          - `kind` 'closing_entry_generator'
          - `entry_template` EntryTemplateRequest, required
            - `debit_element_id` string, required: CoA element id to debit (e.g. Depreciation Expense). This is a chart-of-accounts element id — the `id` returned by get-unmapped-elements / get-graph-schema — NOT a taxonomy qname.
            - `credit_element_id` string, required: CoA element id to credit (e.g. Accumulated Depreciation). A chart-of-accounts element id (see get-unmapped-elements), not a taxonomy qname. One template = one debit/credit pair; model a multi-account entry as several schedules.
            - `entry_type` 'standard' | 'adjusting' | 'closing' | 'reversing': Entry type for generated entries
            - `memo_template` string: Memo template ({structure_name} is replaced)
            - `auto_reverse` boolean: Auto-generate a reversing entry on the first day of the next period
          - `schedule_metadata` ScheduleMetadataRequest
            - `method` string: Calculation method. 'straight_line' (default) distributes `monthly_amount` evenly across periods with the final period absorbing rounding. 'custom' requires `periodic_amounts` — the generator uses those values verbatim instead of computing. Other strings are labels only; fact values still come from `monthly_amount` or `periodic_amounts`.
            - `original_amount` integer: Cost basis in cents
            - `residual_value` integer: Salvage value in cents. The schedule expenses `original_amount` less this; net book value ends at it.
            - `useful_life_months` integer: Useful life in months
            - `asset_element_id` string, nullable: BS asset element for net book value
            - `booked_on` string, date, nullable: The date the cost went on the books, when that is before the schedule's first period: a policy paid in December that starts amortizing in January, or an asset bought the month before it is placed in service. From this date until the first period the schedule carries its full cost, so the schedule reconciliation does not report that balance as unscheduled. Leave it out when the cost is booked in the first period.
            - `periodic_amounts` integer[], nullable: Explicit per-period amounts in cents. When set, the generator uses these values instead of `monthly_amount` — enabling non-straight-line schedules (effective-interest bond discount amortization, day-count interest accrual, variable lease payments, pre-computed effective-yield curves, etc.). Length must match the number of monthly periods between `period_start` and `period_end`; sum must equal `original_amount` less `residual_value` exactly. The auto-generated SumEquals rule proves that total regardless of the curve shape.
          - `periods_with_entries` integer: Number of in-scope periods that have at least one closing entry posted. Runtime state derived at envelope-build time from the Entry table.
        - StatementMechanics: Renderer mechanics for the statement family of block types. Covers `balance_sheet`, `income_statement`, `cash_flow_statement`, and `equity_statement`. All fields are optional so library-seeded rows that haven't been enriched yet still validate against an empty tagged body. The existing `statement(...)` GraphQL field continues to serve rendered output; this mechanics model is the source of truth for future renderer configuration.
          - `kind` 'statement_renderer'
          - `template_id` string, nullable: Pinned template id — when set, the renderer uses that template's layout instead of the block's default. The templates table is not yet implemented; the column is reserved so tenant writes can stamp it without another migration round-trip when it lands.
          - `rollup_root_element_ids` string[]: Element ids that anchor the statement's roll-up roots (e.g. the Assets and LiabilitiesAndEquity totals on a Balance Sheet). Empty on library-seeded rows until tenant adoption.
          - `period_comparisons` integer: Number of period columns to render in comparative mode: 1 = single-period, 2 = prior-period comparison, 3-4 = multi-year trailing view. Defaults to single-period; overridden by the template when one is attached.
        - MetricMechanics: Derivative mechanics for `block_type='metric'`. A metric block composes its facts from one or more source blocks at read time — covenant tests, ratios, KPI trend computations. The typed arm ships today so the discriminated union covers all three construction modes (declarative / compositional / derivative); the derivation evaluator that actually computes facts from source-block FactSets is not yet implemented. `source_block_ids` is the ordered list of Structure ids this metric derives from; `derivation_type` names the kind of computation (`ratio`, `trailing_twelve_month`, `covenant_test`, …), and `expression` carries the agent-authored derivation string that the evaluator will consume at envelope build time.
          - `kind` 'metric'
          - `source_block_ids` string[]: Ordered list of Structure ids this metric sources from. Must be non-empty at evaluation time; empty lists are accepted so library scaffolding can register metric templates before source linkage is wired.
          - `derivation_type` string, nullable: Free-form label for the derivation kind — 'ratio', 'trailing_twelve_month', 'covenant_test', etc. The evaluator dispatches on this tag; the set may be locked with a CHECK constraint once the derivation catalog stabilizes.
          - `expression` string, nullable: Derivation expression in the metric DSL — evaluated at envelope read time to produce the derivative fact value. Opaque string today; the metric-side parser / evaluator is not yet implemented.
          - `unit` string: Output unit of the derived value — 'ratio', 'percent', 'USD', 'count', etc. Used by the renderer to format the metric badge.
        - RollforwardMechanics: Filter-based attribution mechanics for `block_type='rollforward'`. Filter-based attribution: each block decomposes one BS source element's period delta into a list of flow concepts via declared :class:`AttributionFilter` predicates. The renderer evaluates the filters against ledger LineItems at envelope-build time, emits one attributed fact per filter per period, and arbitrates any residual against the default change tag fallback. Reads directly from the typed `structures.artifact_mechanics` JSONB column. `attribution_filters` rides as nested JSON; the predicate union widens as new predicate shapes are added — currently only `line_item_metadata_field` is carried.
          - `kind` 'rollforward'
          - `bs_source_element_id` string, required: Element id of the balance-sheet source whose period delta this block decomposes. Resolved from `bs_source_qname` at create time.
          - `bs_source_qname` string, required: QName of the BS source element (e.g. `mini:CashAndCashEquivalents`). Round-tripped for caller convenience; `bs_source_element_id` is authoritative.
          - `default_change_tag_element_id` string, nullable: Element id of the default change tag — the fallback flow concept that receives any residual (Δ BS − Σ filter matches). Null when no default is declared; behavior on residual then follows `validation_mode`.
          - `default_change_tag_qname` string, nullable: QName of the default change tag (e.g. `rs-gaap:IncreaseDecreaseInCashAndCashEquivalents`). Round-tripped for caller convenience and operator-readable envelopes; `default_change_tag_element_id` is authoritative. Null iff `default_change_tag_element_id` is null.
          - `attribution_filters` AttributionFilter[]: Filter predicates routing LineItems to flow concepts. The renderer evaluates each filter against the period's LineItems, aggregates signed amounts, and emits one fact per filter per period.
            - `target_qname` string, required: QName of the flow concept this filter produces facts for — e.g. `rs-gaap:ProceedsFromIssuanceOfCommonStock`. Resolved to `target_element_id` at create time.
            - `target_element_id` string, nullable: Resolved element id for `target_qname`. Null at create time; populated by the handler before persistence. Round-tripped in the envelope.
            - `predicate` LineItemMetadataPredicate, required: Filter ledger LineItems by flow concept. The single predicate kind shipped to date. `values` are flow-concept qnames — mini's `TransactionDescriptionCode` values, rs-gaap flow concepts (what the enrichment classifier emits for QuickBooks data), future XBRL GL `GenericFlowCategory` codes. The engine resolves them to element_ids and matches the first-class `LineItem.flow_element_id` FK; matched lines aggregate signed into the attributed fact for the period. `field` is accepted but ignored: the flow tag lives in the typed `flow_element_id` FK, not in JSONB metadata. It stays on the wire so existing request bodies keep validating.
              - …
          - `validation_mode` 'strict' | 'residual_as_default' | 'warn_only': Renderer arbitration policy when Σ filter matches != Δ BS. `strict` raises; `residual_as_default` emits the residual as a default-tag fact (the common case); `warn_only` logs and lets the imbalance pass.
        - ForecastMechanics: Authored scenario container for `block_type='forecast'`. The block IS the scenario: its structure id is the `scenario_id` every derived forward FactSet carries (NULL = actuals). The authored surface is exactly this — scenario identity, horizon, base period, lever assertions; everything downstream is derived by `compute-forecast` (levers → driven rs-gaap anchors via the rs-driver Derive rules → carry-forward for unmodeled IS lines → calc-DAG subtotals), landing in the EXISTING statement/metric block types stamped with the scenario. Reads directly from the typed `structures.artifact_mechanics` JSONB column.
          - `kind` 'forecast'
          - `scenario_kind` 'budget' | 'forecast' | 'projection': Scenario kind — display/filter metadata, not machinery.
          - `horizon_months` integer, required: Forward months projected past the base period.
          - `base_period` string, required: Origin month (`YYYY-MM`) of the authored horizon window — resolved at create time (request → fiscal calendar closed-through → newest actual report month) and stored so recompute is deterministic. Every lever, line assertion and growth rate is keyed to a month in `base_period + 1 … base_period + horizon_months`, so this never moves on its own; `base_anchor` decides whether the *walk* still seeds here.
          - `base_anchor` 'seam' | 'fixed': Where the walk takes its opening balances. `seam` (default) re-anchors on the newest closed month at or after `base_period`, so a scenario survives a period close without being rebuilt and its first forward month rolls off real balances. `fixed` pins the walk to `base_period` — the deliberate counterfactual (“if we had restarted in July”), whose balances diverge from actuals on purpose.
          - `levers` LeverAssertionLite[], required: Expanded lever assertions (authoring order).
            - `qname` string, required: rs-driver lever element qname.
            - `element_id` string, required: Resolved tenant element id.
            - `item_type` string, nullable: Format family from the catalog (percent | days | ...).
            - `values_by_period` object, required: Expanded per-month assertions keyed by `YYYY-MM`.
          - `line_assertions` LineAssertionLite[]: Direct statement-line assertions (authoring order) — manual overrides that win over driver rules and carry-forward for the months they name.
            - `qname` string, required: Asserted statement-leaf qname.
            - `element_id` string, required: Resolved tenant element id.
            - `item_type` string, nullable: Format family from the element (monetary | ...).
            - `period_type` string: The element's period type — duration assertions pin IS lines; instant assertions pin BS lines through the roll.
            - `values_by_period` object, required: Expanded per-month assertions keyed by `YYYY-MM`.
          - `line_growth` LineGrowthLite[]: Per-line growth trajectories (authoring order) — each grows an income-statement leaf month-over-month at the asserted rate, compounding from the base month.
            - `qname` string, required: Grown statement-leaf qname.
            - `element_id` string, required: Resolved tenant element id.
            - `item_type` string: Always 'percent' — the grid row renders rates, not values.
            - `values_by_period` object, required: Expanded per-month growth rates keyed by `YYYY-MM`.
          - `computed_months` integer: Number of forward months with computed scenario FactSets. Runtime state filled at envelope-build time — 0 until the first compute-forecast run.
        - ReconciliationMechanics: Mechanics for `block_type='reconciliation'`: what is compared, against what, and how much the close cares. A `ledger`-scope reconciliation checks the whole ledger against one source (the synced accounting system's own trial balance). An `account`-scope one ties a single account to an independent balance.
          - `kind` 'reconciliation'
          - `scope` 'ledger' | 'account', required: Whether the block covers the whole ledger or one account.
          - `method` 'source_ledger' | 'schedule_register' | 'statement', required: Where the independent side comes from.
          - `element_id` string, nullable: The account reconciled; null for a ledger-scope block.
          - `required_for_close` boolean: Whether the period's close waits on this reconciliation.
          - `materiality` number: A difference up to this amount still counts as reconciled. Zero means the two sides must agree to the cent.
          - `review_required` boolean: Whether the close waits for a sign-off as well, not just for the two sides to reconcile.
          - `separate_reviewer` boolean: Whether the person who signs off must be someone other than the person who ran the comparison.
          - `statement_cycle` 'monthly' | 'quarterly' | 'annual', nullable: `statement` blocks only: how often the account's statement is issued; unset is monthly. A period is covered by the latest statement ending within the cycle that ends with it.
    - `elements` ElementLite[]
      - `id` string, required
      - `qname` string, nullable
      - `name` string, required
      - `code` string, nullable
      - `element_type` string, required: concept | abstract | axis | member | hypercube
      - `is_abstract` boolean
      - `is_monetary` boolean
      - `balance_type` string, nullable
      - `period_type` string, nullable
      - `item_type` string, nullable: Value-domain vocabulary (monetary | ratio | percent | multiple | days | string | …). None means untyped; fall back to is_monetary.
      - `documentation` string, nullable: The element's documentation-role label — the catalog's authoritative value semantics (e.g. whether a percent driver is a growth rate or a rate-on-base fraction). None when the element carries no documentation label.
    - `connections` ConnectionLite[]
      - `id` string, required
      - `from_element_id` string, required
      - `to_element_id` string, required
      - `association_type` string, required: presentation | calculation | mapping | equivalence | general-special | essence-alias
      - `arcrole` string, nullable
      - `order_value` number, nullable
      - `weight` number, nullable
      - `classifications` ClassificationLite[]: Association-level classifications — concept_arrangement, member_arrangement, named_disclosure rows from the junction. Empty for library-seeded associations that haven't been classified yet.
        - `id` string, required: Classification vocabulary row id.
        - `category` string, required: One of the 3 association-level categories in the `public.classifications` CHECK constraint: 'concept_arrangement', 'member_arrangement', or 'named_disclosure'.
        - `identifier` string, required: Vocabulary identifier within the category — e.g. 'RollUp', 'whole_part', 'AssetsRollUp'.
        - `is_primary` boolean: Whether this is the canonical classification for the (association|element, category) pair. Non-primary rows capture alternates / AI suggestions alongside the chosen primary.
        - `confidence` number, nullable: AI/adapter-supplied confidence (0.0-1.0). Null for deterministic library-seeded rows.
        - `source` string, nullable: Provenance — 'arcrole_analysis', 'disclosure_mechanics', 'fac-traits', adapter name, etc.
    - `facts` FactLite[]
      - `id` string, required
      - `element_id` string, required
      - `element_name` string, nullable
      - `element_qname` string, nullable
      - `value` number, nullable: Numeric value; null for Nonnumeric (text-block) facts.
      - `text_value` string, nullable: Text payload for Nonnumeric facts; null for numeric.
      - `fact_type` string: Numeric | Nonnumeric
      - `content_type` string, nullable: MIME type of text_value (e.g. 'text/markdown').
      - `period_start` string, date, nullable
      - `period_end` string, date, required
      - `period_type` string, required
      - `unit` string
      - `fact_scope` string, required: historical | in_scope
      - `fact_set_id` string, nullable
    - `rules` RuleLite[]
      - `id` string, required
      - `rule_category` string, required: One of 8 cm:VerificationRule subclasses — AutomatedAccountingAndReportingChecks, FundamentalAccountingConceptRelation, PeerConsistencyRule, PriorPeriodConsistencyRule, ReportLevelModelStructureRule, ReportingSystemSpecificRule, ToDoManualTask, XBRLTechnicalSyntaxRule.
      - `rule_pattern` string, nullable: Arithmetic / logical pattern evaluated over fact values. One of 11 cm:BusinessRulePattern mechanisms — Adjustment, CoExists, EqualTo, Exists, GreaterThan, GreaterThanOrEqualToZero, LessThan, RollForward, RollUp, SumEquals, Variance. Null when the rule is a structural check (see rule_check_kind).
      - `rule_check_kind` string, nullable: Model-structure check kind evaluated over the association graph. One of 6 kinds — LeafHasClassification, LibraryOriginImmutability, NoCycles, NoOrphanArcs, ParentBeforeChild, UniqueQNameInTaxonomy. Null when the rule is an arithmetic pattern (see rule_pattern). Exactly one of rule_pattern / rule_check_kind is non-null per rule.
      - `rule_expression` string, required
      - `rule_target` RuleTargetLite: Polymorphic rule target — points at the atom the rule is scoped to.
        - `target_kind` string, required: Which atom type the rule targets — 'structure' | 'element' | 'association' | 'taxonomy'. Enum closure enforced by the `public.rules` CHECK constraint.
        - `target_ref_id` string, required: UUID of the target atom — structure_id, element_id, association_id, or taxonomy_id depending on `target_kind`.
      - `rule_variables` RuleVariableLite[]
        - `variable_name` string, required: Local name in the rule expression, e.g. 'Assets'.
        - `variable_qname` string, nullable: Concept qname the variable resolves to, e.g. 'fac:Assets'. Null for tenant CoA elements (which key on `code`/`element_id`, not qname) — in that case the binding is carried by `variable_element_id`.
        - `variable_element_id` string, nullable: Element id the variable binds to directly. Set for schedule SumEquals rules over CoA-debit elements that have no qname; null otherwise.
      - `rule_message` string, nullable
      - `rule_severity` string: Failure severity — 'info' | 'warning' | 'error'. Enum closure enforced by the `public.rules` CHECK constraint.
      - `rule_origin` string: Provenance — 'forked' (from an upstream artifact, e.g. an external XBRL taxonomy) or 'native' (authored in this seed or by a tenant). Enum closure enforced by the `public.rules` CHECK constraint.
    - `dimensions` object[]
    - `fact_set` FactSetLite: FactSet projection — period-specific instantiation of the Structure. The envelope carries one `FactSetLite` per block when a FactSet row exists for the requested period, and leaves `fact_set` null when none does.
      - `id` string, required
      - `structure_id` string, nullable
      - `period_start` string, date, nullable
      - `period_end` string, date, required
      - `factset_type` string, required: 'report' | 'schedule' | 'custom' | 'disclosure' | 'metric'. Enum closure enforced by the `public.fact_sets` CHECK constraint.
      - `entity_id` string, required
      - `report_id` string, nullable: Back-pointer to the parent row in `reports`. Null when the FactSet does not belong to a report package.
      - `scenario_id` string, nullable: Scenario axis (the forecast engine). NULL = actuals; non-NULL names the owning forecast block whose parallel universe this set belongs to.
      - `provenance` object, nullable: Typed `FactProvenance` descriptor (discriminated on `origin`: pivot | schedule | derived | asserted | document | forecast | filed) recording how this FactSet was constructed. It describes the set, not each fact: a `pivot` set's mapped leaves aggregate posted line items, while its subtotals and derivations are computed from those leaves. Surfaced as JSON, mirroring how mechanics is exposed. Null when the FactSet carries no descriptor.
      - `created_at` string, date-time, nullable: When the set was computed. For a close-stamped canonical set (`report_id` null, type `report`) this is the month as closed on this date: its facts keep that answer while a live render reads through the mapping arcs as they stand now.
    - `verification_results` VerificationResultLite[]
      - `id` string, required
      - `rule_id` string, required
      - `structure_id` string, nullable
      - `fact_set_id` string, nullable
      - `status` string, required: 'pass' | 'fail' | 'error' | 'skipped'. Enum closure enforced by the `public.verification_results` CHECK constraint.
      - `message` string, nullable
      - `period_start` string, date, nullable
      - `period_end` string, date, nullable
      - `evaluated_at` string, date-time, nullable
    - `verification_summary` VerificationSummary: Server-computed aggregate of a block's `verification_results`. Overall counts plus a per-`rule_category` breakdown, so the viewer renders the grouped Verification Results panel without a client-side results→rules join. Status closure is `pass | fail | error | skipped` (the `public.verification_results` CHECK); `total` is their sum.
      - `total` integer
      - `passed` integer
      - `failed` integer
      - `errored` integer
      - `skipped` integer
      - `by_category` VerificationCategorySummary[]
        - `category` string, required
        - `total` integer
        - `passed` integer
        - `failed` integer
        - `errored` integer
        - `skipped` integer
    - `view` ViewProjections: The six `type-of` View projections of an Information Block (Rendering, FactTable, ModelStructure, VerificationResults, ReportElements, BusinessRules), surfaced at the envelope boundary. Each projection is computed server-side at envelope-build time when its source data is available. The frontend's `BlockView` dispatcher routes to the projection component matching the user's selected view mode; missing projections render as empty states without breaking the dispatcher. Today: `rendering` is computed for the statement family, and `chart` (panel/series config over the rendering's rows and periods) for metric blocks. Projections without backend support yet are empty; `fact_table` is derivable from `InformationBlockEnvelope.facts`.
      - `rendering` RenderingLite: Pre-computed rendering projection of an Information Block. Computed server-side at envelope-build time for blocks where rendering is deterministic (the statement family today; future block types add their own rendering builders). The frontend's `BlockView` `Rendering` projection consumes this directly — no client-side rollup, depth computation, or calculation walk needed.
        - `rows` RenderingRowLite[]
          - `element_id` string, required
          - `element_qname` string, nullable
          - `element_name` string, required
          - `classification` string, nullable: FASB elementsOfFinancialStatements trait identifier — 'asset', 'liability', 'equity', 'revenue', 'expense'. Surfaced so the viewer can color-code or group rows without a follow-up trait lookup.
          - `balance_type` string, nullable
          - `item_type` string, nullable: Value-domain format family from the element (monetary | ratio | percent | multiple | days | …). Drives per-row value formatting; None falls back to is_monetary on the element.
          - `values` number[]
          - `text_value` string, nullable: Narrative payload for text-block disclosure rows (markdown); numeric rows carry values instead.
          - `is_subtotal` boolean
          - `depth` integer
        - `periods` RenderingPeriodLite[]
          - `start` string, date, required
          - `end` string, date, required
          - `label` string, nullable
          - `forecast` boolean, nullable: True when this column comes from a forecast scenario's FactSet — the machine-readable seam marker (labels also carry a '(forecast)' suffix, but consumers should key styling off this flag, not label parsing). None/absent = an actuals column.
        - `validation` ValidationLite: Outcome of guard-rail validation on a rendered statement. Distinct from :class:`VerificationResultLite` (which surfaces the rule-engine outcomes from `public.verification_results`). This lite type carries the synchronous guard-rail checks computed at envelope-build time — accounting equation, totals foot, etc.
          - `passed` boolean
          - `status` string
          - `checks` string[]
          - `failures` string[]
          - `warnings` string[]
        - `unmapped_count` integer
      - `chart` ChartLite: Server-shaped chart projection — panel/series CONFIG, never values. The second real server-computed View arm (after `rendering`). Values come from `rendering.rows` joined by `element_id`; the x-axis is `rendering.periods`. Renderers (report-components) turn one panel into one chart.
        - `panels` ChartPanelLite[]
          - `label` string, nullable: Panel heading — e.g. 'Monetary', 'Ratios'.
          - `item_type` string, nullable: Format family shared by the panel's series (monetary | ratio | percent | multiple | days); None for the untyped fallback panel.
          - `kind` string: Per-panel mark — 'line' or 'bar'.
          - `series` ChartSeriesLite[]
            - `key` string, required: Stable series id — element_id today.
            - `element_id` string, required
            - `label` string, required: Display name for legends.
  - `at` string, required: ISO-8601 UTC timestamp
  - `createdBy` string, nullable: User ID that initiated the operation
  - `idempotentReplay` boolean: True when this envelope came from the idempotency cache — the underlying command did not execute again. False on fresh executions.

## Other responses

- `400`: Invalid request
- `401`: Authentication required
- `403`: Access denied
- `404`: Resource not found
- `409`: Idempotency-Key conflict — key reused with different body
- `422`: Validation error
- `429`: Rate limit exceeded
- `500`: Internal server error

---

[API](https://skmtc.dev/robosystems/apis/robosystems-api.md) · [All operations](https://skmtc.dev/robosystems/apis/robosystems-api/llms.txt) · [OpenAPI document](https://skmtc.dev/robosystems/apis/robosystems-api/revisions/e661e2d5ca6a?raw)
