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

# Setup progress

> Read a context's aggregated setup and activation-readiness state in a single request to drive an onboarding checklist or setup wizard.

The setup-progress endpoint returns configured-resource counts, the last-run state, and activation readiness for a context in a single aggregate. A setup wizard or onboarding checklist derives its state from one request instead of many.

## Get setup progress

***

```bash theme={null}
curl -X GET "https://api.matcher.example.com/v1/contexts/{contextId}/setup-progress" \
  -H "Authorization: Bearer $TOKEN"
```

```json theme={null}
{
  "contextId": "550e8400-e29b-41d4-a716-446655440000",
  "status": "DRAFT",
  "sources": { "total": 2, "left": 1, "right": 1 },
  "fieldMaps": { "mappedSources": 2 },
  "matchRules": { "total": 3 },
  "schedules": { "total": 1 },
  "lastRun": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "status": "COMPLETED",
    "completedAt": "2025-01-15T10:30:00Z"
  },
  "readiness": {
    "ready": true,
    "missing": []
  },
  "next": null
}
```

## What it returns

***

* **`status`**: the context lifecycle status: `DRAFT` (in setup), `ACTIVE` (running), `PAUSED` (suspended), or `ARCHIVED` (retired).
* **`sources`**: source counts split by matching side: `total`, `left`, `right`.
* **`fieldMaps.mappedSources`**: number of **mapped** sources. This count covers sources with a field map, plus self-mapped CAMT.053 sources. For those, the parser embeds the ISO 20022 mapping and ignores field maps.
* **`matchRules.total`**: match-rule count for the context.
* **`schedules.total`**: schedule count for the context.
* **`lastRun`**: the most recent match run (`id`, `status` of `PROCESSING`/`COMPLETED`/`FAILED`, and `completedAt`). It is `null` when the context has never run.
* **`readiness`**: activation-readiness summary (see below).
* **`next`**: the deterministic next setup action to take, or `null` when the context is ready (see below).

## Readiness and the checklist

***

The `readiness` block reports whether the context satisfies every activation requirement:

```json theme={null}
{
  "ready": false,
  "missing": [
    "context.activation.requirement.source-mapping",
    "context.activation.requirement.match-rule"
  ]
}
```

`missing` holds **stable public activation-requirement identifiers** you can map to checklist items. The possible values are:

* `context.activation.requirement.left-source`: the context needs at least one LEFT-side source.
* `context.activation.requirement.right-source`: the context needs at least one RIGHT-side source.
* `context.activation.requirement.source-mapping`: at least one source lacks a mapping: it has no field map and is not a self-mapped CAMT.053 source.
* `context.activation.requirement.match-rule`: the context needs at least one match rule.
* `context.activation.requirement.fee-rule`: the context enables fee normalization but has no fee rule. This requirement is **conditional**. It appears only when you set `feeNormalization` to `NET` or `GROSS`. It mirrors the run precondition, which requires fee **rules**, not fee schedules, to be non-empty.

<Note>If you move a context to `ACTIVE` before it is ready, the update fails with `409 Conflict` and code `MTCH-0103`. Its problem details list the same public activation-requirement identifiers. Use them, or re-read setup progress, to render the remaining setup guidance.</Note>

## The next action

***

`next` turns `readiness.missing` into a concrete call. It comes from `missing[0]`, the first unsatisfied requirement in the stable order above. It is `null` when the context is ready:

```json theme={null}
{
  "requirementId": "context.activation.requirement.source-mapping",
  "operationId": "createFieldMap",
  "method": "POST",
  "path": "/v1/contexts/{contextId}/sources/{sourceId}/field-maps",
  "requiredFields": ["mapping"],
  "forSource": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "Bank statement"
  }
}
```

* **`requirementId`**: the public activation-requirement identifier this action satisfies.
* **`operationId`**, **`method`**, **`path`**: the endpoint to call to satisfy the requirement.
* **`requiredFields`**: the **names** of the fields that the create request requires. They never carry values. You supply those.
* **`forSource`**: present only for the source-mapping action, naming the first unmapped source so you can fill `{sourceId}` without a separate lookup.

The full requirement-to-action table:

| `requirementId`                                 | Endpoint                                                      | `requiredFields`                |
| ----------------------------------------------- | ------------------------------------------------------------- | ------------------------------- |
| `context.activation.requirement.left-source`    | `POST /v1/contexts/{contextId}/sources`                       | `name`, `type`, `side`          |
| `context.activation.requirement.right-source`   | `POST /v1/contexts/{contextId}/sources`                       | `name`, `type`, `side`          |
| `context.activation.requirement.source-mapping` | `POST /v1/contexts/{contextId}/sources/{sourceId}/field-maps` | `mapping`                       |
| `context.activation.requirement.match-rule`     | `POST /v1/contexts/{contextId}/rules`                         | `priority`, `type`, `config`    |
| `context.activation.requirement.fee-rule`       | `POST /v1/contexts/{contextId}/fee-rules`                     | `side`, `feeScheduleId`, `name` |

Both source-side requirements resolve to the same `createSource` operation. The `side` field is what distinguishes them.

## How to use it during setup

***

1. **Render the checklist.** On each step of the wizard, GET setup-progress and use the counts (`sources`, `fieldMaps`, `matchRules`, `schedules`) to tick off completed items.
2. **Drive the primary button from `next`.** Do not reimplement the requirement order client-side. Call the operation that `next` names. Then re-read setup-progress for the next action.
3. **Gate the "Activate" button.** Enable activation only when `readiness.ready` is `true`. Otherwise, list `readiness.missing` as the remaining steps.
4. **Show run health.** Once `lastRun` is present, surface its `status` and `completedAt` so operators can confirm the context produces results.

The whole state comes from one call. You can poll this endpoint to keep the wizard live, with no separate source, rule, and run reads.

## Response codes

***

| Status | Meaning                 |
| ------ | ----------------------- |
| `200`  | Setup progress returned |
| `404`  | Context not found       |
