Enrichment

POST /v1/enrichment — deep per-member behavioral enrichment, on a trigger gate.

POST /v1/enrichment runs a deeper pass over a member’s accumulated behavior to surface newly-discovered preferences and genre-affinity shifts, with a passenger-visible narrative. It is gated: a deterministic trigger decides whether the deep pass is warranted before any model call, so most requests are cheap and only some do real work.

Session-scopedrequires the X-Session-Id header. Enrichment is title-free by design: you identify the member, not a content batch. Request body max 8 KiB.

FieldRequiredRules
seatIdyesThe member’s seat.
memberSlotnoWhich member on a shared seat. Omit for solo.
manualnotrue signals a manual trigger request. It is one input to the gate, not a bypass — the gate still decides. Defaults to false.
$curl -X POST "https://api.staging.westiq.ai/v1/enrichment" \
> -H "Authorization: Bearer $ACCESS_TOKEN" \
> -H "X-Session-Id: seat-12A-f3d9c1" \
> -H "Content-Type: application/json" \
> -d '{ "seatId": "12A", "manual": true }'

When the trigger fires, applied is true and the pass returns real content:

1{
2 "schemaVersion": "1",
3 "correlationId": "req_0197c0a1b2c3d4e5f60718293a4b5c6d",
4 "discoveredPreferences": [
5 { "category": "genre", "label": "Slow-burn thrillers", "confidence": 0.72 }
6 ],
7 "genreShifts": [
8 { "fromGenre": "Action", "toGenre": "Thriller", "magnitude": 0.35 }
9 ],
10 "reasoningNarrative": "Lately you've been finishing tense, quieter thrillers…",
11 "applied": true
12}
  • discoveredPreferences[].confidence and genreShifts[].magnitude are code-clamped to 0–1.
  • reasoningNarrative is passenger-visible model free text.

applied: false is a cost-free decline, not an error

When the trigger gate declines — the member is rate-limited, a pass is already in flight, or a session cap is reached — the response is a 200 with applied: false, no model call made, and empty content:

1{ "schemaVersion": "1", "correlationId": "req_…",
2 "discoveredPreferences": [], "genreShifts": [],
3 "reasoningNarrative": "", "applied": false }

This is normal and costs nothing. Branch on applied: only merge results when it is true; an applied: false simply means “not now.”

Enrichment never rewrites the member’s persona — the persona is immutable for the session. The refinement rides this response (and the affinity signals that scored serve and suggestions already read), not a persona mutation. The enrichment.ready SSE frame is not yet published — read this HTTP response.

Errors

Standard envelope: 400 session.unresolved, 401 / 403, 422 request.validation, 500. Note a declined trigger is not an error — it’s a 200 with applied: false.