---
title: "Record a write-back finding against an intent: a contradiction that building the spec surfaced. The inverse of a decision — the next agent that pulls this intent reads open findings as 'the spec may be stale here' so the refinement loop converges instead of repeating a dead premise."
method: POST
path: "/api/v1/intents/{id}/findings"
tags: ["findings"]
---

# Record a write-back finding against an intent: a contradiction that building the spec surfaced. The inverse of a decision — the next agent that pulls this intent reads open findings as 'the spec may be stale here' so the refinement loop converges instead of repeating a dead premise.

`POST /api/v1/intents/{id}/findings`

Rate-limited by the 'general' bucket (300/h sliding window, keyed user:<userId> or ip:<ip>). Findings are stored as a read-modify-write append on the intent's implementation_findings JSONB array (prior findings are preserved); the merged set is sanitized (capped length, malformed legacy rows dropped) before persisting. Every new finding is created with status 'open' and a server-assigned id + recordedAt (epoch ms); target, correction, and source are echoed back only when supplied. openCount is the number of findings still in status 'open' after the write.

## Path parameters

- `id` string, required

## Query parameters

- `workspace_id` string

## Request body

- object
  - `assumption` string, required — What the spec assumed or said before it was built. Non-empty after trim.
  - `finding` string, required — What building it actually revealed — the fact that contradicts the assumption. Non-empty after trim.
  - `target` string — Which part of the spec this contradicts: 'objective', 'outcome:<id>', 'constraint:<index>', 'edgeCase:<id>', 'check:<id>' (a verification check — recording this flips that check to failing), or plain prose. Non-empty after trim when provided.
  - `correction` string — Proposed correction to the intent, if any. Non-empty after trim when provided.
  - `source` string — Provenance: where this came from, e.g. 'claude-code @ owner/repo'. Non-empty after trim when provided.

## Response `201`

Created — returns { intentId, finding, openCount }

- object

## Other responses

- `400` — Invalid request body (zod) — { error, details }; OR cookie-session auth missing workspace_id
- `401` — Invalid/expired API key, or no Bearer key and no valid session cookie
- `403` — Lacks write scope; OR cookie auth not a member of the workspace
- `404` — Intent not found within this workspace
- `429` — Rate limit exceeded (general bucket, 300/h) — { error } with Retry-After header
- `500` — DB error recording the finding or unexpected internal error

---

[API](https://skmtc.dev/pathmode/apis/pathmode-api.md) · [All operations](https://skmtc.dev/pathmode/apis/pathmode-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/pathmode/pathmode-api/revisions/e419abb0a327/schema)
