Skip to content

Keep a report's AI text as it stands

POST
/api/solutions/runs/{run_id}/keep-ai/
curl --request POST \
--url http://localhost:8000/api/solutions/runs/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/keep-ai/ \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "fingerprint": "9f2b1c4e7a01d3f5b8c6e2a4d7f0b3c5" }'

The other half of refresh-ai (#1995). Re-stamps the run’s freshness baseline to the CURRENT inputs and regenerates nothing: no cached prose is dropped, no AiArtifact row is touched, no LLM call is made here or on the next load. The report’s meta.aiStale therefore reads false until the inputs move AGAIN, at which point the notice returns — this records that the coach accepted the text they have (typically because they edited it themselves), it does not disable staleness detection. Offered as the notice’s dismiss control, so a coach who does not want to spend a refresh is not left with a banner they cannot clear. Team-scoped; cross-team run ids are a 404. Compare-and-set: fingerprint must be the meta.aiFingerprint the report GET served, so a change landing while the report was open cannot be dismissed unseen (409). Deliberately NOT rate-limited — the throttle on refresh-ai caps paid-model spend, and this call has none.

run_id
required
string format: uuid

POST /api/solutions/runs/<id>/keep-ai/ request — the coach keeps the AI text they were shown (#1995).

fingerprint is the report GET’s own meta.aiFingerprint, echoed back. It makes the dismiss a compare-and-set instead of a blind stamp: if the inputs moved while the report was open, the server answers 409 and the notice comes back describing the change nobody has seen yet, rather than silently accepting it.

object
fingerprint
required

The meta.aiFingerprint served with the report being dismissed. A mismatch against the current inputs is a 409.

string
>= 1 characters <= 128 characters
Examples
ExampleKeepTheReadThatWasShown

Echoes the report GET's own meta.aiFingerprint

{
"fingerprint": "9f2b1c4e7a01d3f5b8c6e2a4d7f0b3c5"
}
Media typeapplication/json

200 from POST /api/solutions/runs/<id>/keep-ai/ — the run’s freshness baseline was re-stamped to the current inputs and nothing was regenerated, so meta.aiStale reads false until the inputs move again (#1995).

object
kept
required

Always true on a 200 — the AI text on the report is now the baseline. No prose was dropped and no LLM call was made.

boolean
Examples
ExampleAITextKeptAsTheBaseline

Nothing regenerated; the notice stays down until the inputs move

{
"kept": true
}
Media typeapplication/json
object
detail
required

Human-readable message, or a stable machine code for the cases a client branches on. The standard envelope for 400 (validation — a field-keyed object may appear instead), 401 (missing / invalid credentials), 403 (authenticated but not permitted), and 404 (absent — cross-team records are collapsed to 404 so the API never leaks the existence of another team’s data).

string
Examplegenerated
{
"detail": "example"
}
Media typeapplication/json
object
detail
required

Human-readable message, or a stable machine code for the cases a client branches on. The standard envelope for 400 (validation — a field-keyed object may appear instead), 401 (missing / invalid credentials), 403 (authenticated but not permitted), and 404 (absent — cross-team records are collapsed to 404 so the API never leaks the existence of another team’s data).

string
Examplegenerated
{
"detail": "example"
}

No active team on the requesting account.

Media typeapplication/json
object
detail
required

Human-readable message, or a stable machine code for the cases a client branches on. The standard envelope for 400 (validation — a field-keyed object may appear instead), 401 (missing / invalid credentials), 403 (authenticated but not permitted), and 404 (absent — cross-team records are collapsed to 404 so the API never leaks the existence of another team’s data).

string
Examplegenerated
{
"detail": "example"
}
Media typeapplication/json
object
detail
required

Human-readable message, or a stable machine code for the cases a client branches on. The standard envelope for 400 (validation — a field-keyed object may appear instead), 401 (missing / invalid credentials), 403 (authenticated but not permitted), and 404 (absent — cross-team records are collapsed to 404 so the API never leaks the existence of another team’s data).

string
Examplegenerated
{
"detail": "example"
}

The inputs moved between the report GET and this call, so the notice being dismissed is not the one that is now true. Re-read the report: the staleness it reports is a change the coach has not seen yet.

Media typeapplication/json
object
detail
required

Human-readable message, or a stable machine code for the cases a client branches on. The standard envelope for 400 (validation — a field-keyed object may appear instead), 401 (missing / invalid credentials), 403 (authenticated but not permitted), and 404 (absent — cross-team records are collapsed to 404 so the API never leaks the existence of another team’s data).

string
Examplegenerated
{
"detail": "example"
}