---
title: "Write findings for a data stream's lines"
method: PUT
path: "/reconciliations/{reconciliation_id}/data_streams/{data_stream_id}/findings"
---

# Write findings for a data stream's lines

`PUT /reconciliations/{reconciliation_id}/data_streams/{data_stream_id}/findings`

## Request

- Base URL: `https://api.endclose.com/v1`
- URL: `https://api.endclose.com/v1/reconciliations/{reconciliation_id}/data_streams/{data_stream_id}/findings`
- Auth: API key in header `X-API-KEY`

The same upsert as `PUT /reconciliation_exceptions/{id}/findings`, for an engine that runs before the sweeper has opened an exception. Opens the exception for the (reconciliation, data stream) pair if none is open, reuses it otherwise, and returns its id with the result.

## Path parameters

- `reconciliation_id` string, required
- `data_stream_id` string, required

## Headers

- `Idempotency-Key` string

## Request body

- FindingsUpsertRequest
  - `findings` FindingInput[], required
    - `record_id` string: The record's id. Required unless `external_id` is given.
    - `external_id` string: The record's external id within the exception's data stream. Rejected when it matches more than one record.
    - `looks_right` boolean: `true` when the line is correct as it stands and only needs the note. These lines can be confirmed in bulk.
    - `note` string, required: One or two plain sentences: what happened to this line and what was checked.
    - `category` string, nullable: A short label for the kind of line, in your own words (e.g. `back-billing`, `monthly minimum`).
    - `suggestion` object: What Approve applies. Omit, or use kind `none`, when there is nothing to apply.
      - `kind` 'match' | 'adjust' | 'none': `match`: pair the line with `record_ids` (must balance). `adjust`: pair them and plug the remaining gap with an adjustment carrying `reason`. `none`: nothing to apply.
      - `record_ids` string[]: Every other record of the proposed match, either side, as record ids or external ids.
      - `reason` string: For `adjust`: why a gap remains. Becomes the adjustment's description.
      - `text` string: The sentence shown next to the Approve button.
      - `difference_cents` integer: Informational. Recomputed from the records as |side A| − |side B| whenever `record_ids` is given; only kept as sent for a one-sided `adjust`.
    - `evidence` object[]: Quotes that back the note. A quote with a `url` marks the line as checked against a document in the review.
      - `quote` string, required
      - `source` string, nullable: Where the quote is from, e.g. `Services Agreement, Exhibit B p.19`.
      - `url` string, nullable: An http(s) link to the document — for a file in End Close, the file's `url`. End `#page=N` to open a PDF at that page: the review drawer labels the link “Open p.N” and shows the document inline. Other schemes are dropped.
    - `precedent` string, nullable: How the same line was handled before, in one sentence.
    - `labels` object: Free-form markers your reviewers care about, e.g. `{"carried_forward": true, "colour": "peach"}`. The review page reads `colour`, `colour_cell` and `carried_forward`; anything else is stored and returned untouched.

## Response `200`

Findings written against the open exception

- object: Each finding is validated on its own, so a batch succeeds partially: `upserted` counts the rows written and `errors` names the rejected ones by position.
  - `upserted` integer
  - `errors` object[]
    - `index` integer: Position of the rejected finding in the request's `findings`.
    - `record_id` string
    - `external_id` string
    - `message` string
  - `exception_id` string: The open exception the findings were written to

## Other responses

- `401`: Unauthorized
- `404`: Reconciliation or data stream not found
- `422`: Data stream is not part of the reconciliation, or `findings` is invalid

## Changes

- **2026-10-29** `159f9ed3dbf4`: 1 info
  - added the new optional `header` request parameter `Idempotency-Key`
- **2026-10-07** `e4a47982742a`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/endclose/apis/end-close-api/changes/reconciliations/:reconciliation_id/data_streams/:data_stream_id/findings/put.md)

---

[API](https://skmtc.dev/endclose/apis/end-close-api.md) - [All operations](https://skmtc.dev/endclose/apis/end-close-api/llms.txt) - [OpenAPI document](https://skmtc.dev/endclose/apis/end-close-api/revisions/dfe0fde00f12?raw)
