Skip to content

Refresh a report's AI text

POST
/api/solutions/runs/{run_id}/refresh-ai/
curl --request POST \
--url http://localhost:8000/api/solutions/runs/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/refresh-ai/ \
--header 'Authorization: Bearer <token>'

Explicit whole-report AI refresh (#1528): invalidates every regenerable cached AI take for the run — the run-level prose caches (coach summary, injury note, Key-Insights read; all language / unit / attempt variants) and the unedited per-metric / per-group / per-card / block AiArtifact drafts — so the next report load regenerates them from the current data via the normal deferred SSE streams. Coach-EDITED takes are kept untouched: the edit stays authoritative, exactly like the per-card Regenerate. No LLM call happens in this request. Offered by the frontend when the report’s meta.aiStale flag says the AI text’s inputs changed underneath it (a bound session was re-analyzed, a threshold moved, a phase frame was re-picked). Team-scoped; cross-team run ids are a 404. Rate-limited per account (429 with Retry-After): each refresh makes the next report open regenerate all of the run’s AI text.

run_id
required
string format: uuid
Media typeapplication/json

200 from POST /api/solutions/runs/<id>/refresh-ai/ — the run’s cached AI text was invalidated; the next report load regenerates it from the current data via the normal deferred streams (#1528).

object
refreshed
required

Always true on a 200 — the cached AI text was invalidated.

boolean
cleared_artifacts
required

How many unedited AI-draft rows were dropped (coach-edited takes are kept — the edit stays authoritative).

integer
Examples
ExampleAITextInvalidated

Cached AI dropped; 12 unedited drafts cleared, edits kept

{
"refreshed": true,
"cleared_artifacts": 12
}
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"
}
Media typeapplication/json
object
detail
required

429 — rate limit exceeded. Honour the Retry-After response header (seconds to wait) before retrying; it is sent on every 429.

string
Examplegenerated
{
"detail": "example"
}