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

# Write measurements

> POST /v1/measurements. A measured strength of a causal edge, as a new vintage that is known from now on and never edited.

A measurement is a block that points at the causal edge it measured. Measuring again writes a new vintage of the same fact; the old one stays, so a read [as of an earlier instant](/api-reference/edges) answers with what was known then. The caller computes the numbers. The server checks their shape, records when it learned them, and links the preregistration if there is one.

Calling this route declares each new fact with policy `latest_observed` (the latest known vintage wins). A fact that is already declared is not declared again.

## Request

**space** `string` *required*

Whose memory this is, as in [write memories](/api-reference/write-memories).

**measurements** `object[]` *required*

One object per measurement:

* `edge` (required): `{source_id, target_id, edge_type, regime?}` of a causal edge already in memory. `regime` must match the edge's `properties.regime` (both absent counts as a match).
* `horizon` (required): e.g. `30d`.
* `value` (required): `grade` (0 to 3, integer), `method`, `method_hash`, and any other fields: `beta`, `se`, `unit`, `n_dates`, `p_sign`, `lfsr`, `post_mean`, `post_sd`, `p_break`, `half_life`, `cs_lo`, `cs_hi`, `e_value`, `prereg_sha256`, `framework_hash`. Unknown fields are kept. `p_sign` is in \[0, 1]; with `lfsr` the two sum to 1.
* `asserted_at` (required): when it was measured. `valid_from` (required): when the sample starts. `valid_to`: when it ends.
* `prereg`: `{commitment_id}` of a `commitment` block already in memory. The measurement gets a `DEPENDS_ON` edge to it.
* `fact_key`: must start with `measure.`. Default: `measure.<source_id>.<edge_type lower case>.<target_id>[.<regime>].<horizon>`.
* `id`: default `<fact_key>.<server time, YYYYMMDDTHHMMSS.ffffffZ>`. `statement`: default `Measured <source> -<TYPE>-> <target> (<horizon>): grade <g>`.
* `batch`: the key of one of `backfills`, for a measurement made in the past.

**backfills** `object[]`

`[{key, declared_captured_at, reason}]`, the same rules as [write memories](/api-reference/write-memories).

`captured_at` and `known_at` are never inputs: a row that sends one is refused. Any other top-level key (`backfill`, say) is a `400` (`TCKG_UNKNOWN_FIELD`) rather than being dropped.

## Response

Always `200` for a well-formed body. A refused row does not cost the others.

**accepted** `integer`

Measurements written (the `DEPENDS_ON` links are not counted).

**refused** `object[]`

`{index, reason, why}`, `index` being the row's position (from 0), with `fact_key` when the row gave one. One reason per row, the first that applies: `captured_at_supplied`, `not_causal_edge`, `unknown_edge`, `bad_measure_key`, `bad_measure_value`, `measure_fact_policy` (the fact is declared with another policy), `measure_edge_mismatch` (the fact already measures another edge, regime or horizon), `same_fact_twice` (two or more rows of one fact in one request; all of them are refused, since vintages known at the same instant never resolve), `prereg_not_found`. The usual write refusals (`overlapping_valid`, `unknown_batch`, ...) apply too.

**warned** `object[]`

Written, with a note: `already_remembered` for an identical resend.

**captured\_at** `timestamp`

The server's stamp, shared by every row of the request.

**backfill\_batches** `object`

`{key: batch id}` for `backfills`.

```bash Request theme={null}
curl -s -X POST $TCKG/v1/measurements -H 'content-type: application/json' -d '{
  "space": "farm:demo",
  "measurements": [{"edge": {"source_id": "factor:rain", "target_id": "entity:harvest", "edge_type": "CAUSES"},
                    "horizon": "30d", "asserted_at": "2026-10-20T00:00:00Z", "valid_from": "2016-01-01T00:00:00Z",
                    "value": {"grade": 2, "beta": 0.12, "se": 0.04, "method": "event_study", "method_hash": "9f2c..."},
                    "prereg": {"commitment_id": "commitment:prereg:rain-harvest"}}]
}'
```

```json Response theme={null}
{"accepted": 1, "refused": [], "warned": [], "captured_at": "2026-10-21T03:40:00.123456+00:00", "backfill_batches": {}}
```

What the server guarantees: a measurement is known from its `captured_at` (or its batch's declared instant), and `before_measurement` means the preregistration was in memory first. What it does not: that the numbers are right, that `method_hash` matches any code, or when the data behind the measurement was first looked at.

A measurement written the existing way, as a `claim` with `fact_key: measure.*`, `fact_value` and `payload.edge` through [write memories](/api-reference/write-memories), reads the same, apart from its id and times.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.