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

# logic

> POST /v2/logic/compute — run a designated logic unit, without retrieval.

A score, a tree: once the unit is found, the clinician **walks** it. Tick a box,
tick another, pick a branch. Each of those is a computation — a sum, a
comparison, a step through a graph — and none of them is a new question.

This route does that computation, on a unit you **designate** instead of
searching for.

## Why not call `/v2/retrieve` again

Two reasons, and the second is the real one.

**Cost.** Adding up seven checkboxes used to re-run the query maker, the
embedding, both graph access paths, the expansion and the synthesis: 3 to 5
seconds for a sum the engine does in microseconds.

**Determinism.** A second call to `/v2/retrieve` goes back through **ranking**,
and nothing guarantees it finds the unit currently being filled in. The
clinician ticks the seventh box of one score and gets another score's
interpretation. Here the unit is named by its key: that case does not exist.

It is the same split as [`/v2/feedback`](/en/capabilities/feedback) — a gesture
that happens **after** the answer, with its own lifetime, and that has no
business crossing the pipeline that produced it.

<Note>
  `/v2/retrieve` is still the route when the **question** changes.
  `/v2/logic/compute` is for the intermediate turns of a form already open.
</Note>

## Calling it

```bash theme={null}
curl -X POST https://core.locusmedical.fr/v2/logic/compute \
  -H "Authorization: Bearer $LOCUS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "mku_key": "score:cha2ds2vasc",
    "checked": ["Âge ≥ 75 ans", "Hypertension", "Diabète"]
  }'
```

| Field                         | What it is                                                                                                                                                                               |
| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `mku_key`                     | The unit, by its readable key (`score:cha2ds2vasc`) **or** its `mku_id`. Both are in the `/v2/retrieve` payload; the key survives a re-extraction, which matters when a form stays open. |
| `answers`                     | Score: `{question title: option label}`. Tree: `{node id: chosen condition}`.                                                                                                            |
| `checked`                     | Checkbox score: the labels retained.                                                                                                                                                     |
| `level`                       | Ordinal scale: the band picked ("NYHA II").                                                                                                                                              |
| `sources` · `exclude_sources` | The same publisher restriction as on `/v2/retrieve`.                                                                                                                                     |

The three answer fields are **exactly** those of `logic_answers`: a client that
already holds an open form has nothing to translate.

## What it returns

```json theme={null}
{
  "mku_id": "…",
  "mku_key": "score:cha2ds2vasc",
  "type": "score",
  "titre": "Score CHA₂DS₂-VASc",
  "computed": {
    "total": 4.0,
    "outcome": "Anticoagulation recommandée",
    "retained": [
      { "quoi": "Âge ≥ 75 ans", "points": 2.0 },
      { "quoi": "Hypertension", "points": 1.0 },
      { "quoi": "Diabète", "points": 1.0 }
    ],
    "reason": null
  }
}
```

`computed` is the **same object** as `elicitations[].computed` from
`/v2/retrieve`, produced by the same code. Two implementations of the same
arithmetic would eventually diverge; there is only one.

For a tree, `computed` carries `outcome`, `path` (labels) and `path_ids` (ids,
resolvable in the `graph` that `/v2/retrieve` returned).

<Note>
  `outcome: null` with a filled `reason` **is not a failure**. "The source gives no
  interpretation for this total" is clinical information: an engine can say it,
  where a model would produce a plausible, invented class. Likewise
  `reason: "décision requise"` on a tree means a branch is still to be chosen.
</Note>

What the route does not return: no synthesis, no sources, no `trace_id`. There
is no written answer, so nothing to put a thumb on.

## Scope

The read is source-filtered like every other. The invariant: **what
`/v2/retrieve` cannot return, `/v2/logic/compute` cannot compute.** Without it,
the route would be a way around the filter for anyone who guesses a key.

## Errors

| Status | Code                 | Meaning                                                    |
| ------ | -------------------- | ---------------------------------------------------------- |
| 400    | `UNKNOWN_SOURCE`     | A requested source does not exist.                         |
| 404    | `UNKNOWN_LOGIC_UNIT` | No logic unit carries that key within the requested scope. |
