---
title: "Compute Metrics for a Metric Block"
method: POST
path: "/extensions/roboledger/{graph_id}/operations/compute-metrics"
tags: ["RoboLedger: Information Blocks"]
---

# Compute Metrics for a Metric Block

`POST /extensions/roboledger/{graph_id}/operations/compute-metrics`

## 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/compute-metrics`
- Auth: one of:
  - API key in header `X-API-Key`
  - HTTP bearer

Resolves the Derive rules scoped to a metric block (block_type='metric'), binds each rule's operands to the entity's most recent persisted report facts at period_end, evaluates, and upserts the period's standing factset_type='metric' FactSet — one per (structure, entity, period_end), so successive runs accumulate the time series and re-running a period replaces its values. Metrics with missing operands or undefined ratios are skipped with a reason, never errored.

**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

- ComputeMetricsRequest: Request body for the `compute-metrics` operation. Resolves the `Derive` rules scoped to the metric block, binds each rule's operands to the entity's most recent persisted report facts at `period_end`, evaluates, and upserts the period's standing `factset_type='metric'` FactSet (re-running a period replaces its facts). One standing FactSet per (structure, entity, period_end) — the accumulating time series.
  - `structure_id` string, required: Metric block structure (block_type='metric') to compute.
  - `period_end` string, date, required: Period end to compute at. Operands bind to report facts whose period_end matches exactly (instant balances as of this date; durations ending on it).
  - `period_start` string, date, nullable: Optional lower bound for duration-operand binding and the standing FactSet's period_start.
  - `entity_id` string, nullable: The entity whose metrics to compute, by id. Omit for the group parent.
  - `scenario_id` string, nullable: Compute on a scenario slice: operands bind that scenario's facts (actuals as the fallback across the seam) and the standing metric set is stamped with the scenario. None (the default) computes actuals only. Pass a forecast block's structure id after compute-forecast to extend the metric series into its forward months.

## Response `200`

Successful Response

- OperationEnvelopeComputeMetricsResponse
  - `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` ComputeMetricsResponse: Response for the `compute-metrics` operation.
    - `structure_id` string, required
    - `entity_id` string, required
    - `period_end` string, date, required
    - `fact_set_id` string, nullable: Standing metric FactSet for the period — None when every metric was skipped and no prior set existed.
    - `computed` ComputedMetricLite[]
      - `rule_id` string, required: Derive rule that produced the value.
      - `element_id` string, required: Metric element the fact was written for.
      - `element_qname` string, nullable: Metric element qname (e.g. rs-metric:CurrentRatio).
      - `name` string, required: Metric display name.
      - `value` number, required: Computed value.
      - `unit` string, required: Fact unit — 'USD' for monetary, 'days' for days, else 'pure'.
      - `period_type` string, required: 'instant' or 'duration'.
      - `item_type` string, nullable: Format family from the metric element (monetary | ratio | percent | multiple | days). None means untyped; fall back to unit.
    - `skipped` SkippedMetricLite[]
      - `rule_id` string, required: Derive rule that was skipped.
      - `element_qname` string, nullable: Metric element qname the rule targets.
      - `reason` string, required: Why the metric was skipped.
      - `missing` string[]: Operand qnames with no bound fact at the period, when applicable.
  - `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)
