Skip to navigation

Suggestions

POST /v1/suggestions — score a batch of titles for one member.

POST /v1/suggestions takes a batch of titles you’re about to show a member and scores them against that member’s bound persona and affinity — a fast-tier “why this, for you” pass over content you already have on screen.

Session-scoped — requires the X-Session-Id header. Body (max 64 KiB):

FieldRequiredRules
seatIdyesThe member’s seat.
titleIdsyes1–30 integer title ids from your catalog or search responses (see the id note). Unknown or nonservable ids are dropped before scoring.
memberSlotnoWhich member on a shared seat. Omit for solo.
curl -X POST "https://api.staging.westiq.ai/v1/suggestions" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "X-Session-Id: seat-12A-f3d9c1" \
-H "Content-Type: application/json" \
-d '{ "seatId": "12A", "titleIds": [2041, 2088, 3120] }'
{
"schemaVersion": "1",
"correlationId": "req_0197c0a1b2c3d4e5f60718293a4b5c6d",
"items": [
{
"titleId": 2041,
"delta": 0.18,
"boostScore": 74,
"whyForYou": "Leans into the character drama you finish most"
}
],
"behavioralInsight": "You're in a settle-in, one-long-film mood.",
"moodInference": "focused"
}
  • delta and boostScore (0–100) are code-clamped composites — the model supplies a raw signal, deterministic code computes the final numbers.
  • whyForYou and behavioralInsight are passenger-visible model free text.
  • moodInference is optional and may be null.

Flight-bound sessions

If the session is bound to a flight (via flightInstanceId at session setup) and that flight has a pushed active catalog, suggestions are intersected with the flight’s active set — titles not loaded on the aircraft are not suggested. The intersection can only ever narrow, and it never overrides the age gate below. A session with no flight binding, or a flight with no push, behaves exactly as before.

Age-gating: an empty result is honest, not an error

Before any model call, the requested titleIds are filtered against the member’s age tier. This has an important consequence:

A fully-gated request returns an honest empty result, not a 4xx. If none of the titles you sent are allowed for this member’s tier (e.g. a Child member and all-mature titles, or an unbound member whose tier is Unknown), the platform makes no model call and returns a 200 with empty fields:

{ "schemaVersion": "1", "correlationId": "req_…",
"items": [], "behavioralInsight": "" }

(moodInference is null here, and null fields are omitted from responses — so the key is simply absent, not sent as null.)

Do not treat this as a failure — it is the fail-closed design, and it costs nothing. If you expected results, check that the member is bound with the right age and that the titleIds suit their tier.

For every age tier, including adults, ids your airline’s catalog cannot serve are dropped before scoring and never appear in items. This includes unknown, mistyped and other-airline ids. A mixed request still scores its eligible titles. If every id is unknown or nonservable, the response is the same honest 200 empty shape above: items: [], behavioralInsight: "", and a null moodInference omitted from the wire. No model call is made for that empty set. Send ids obtained from your catalog or search responses.

Catalog titles with an unknown rating remain excluded for non-adult tiers.

Today the result rides this HTTP response only — the suggestions.updated SSE frame is not yet published. Read the response directly.

Errors

Standard envelope: 400 session.unresolved, 401 / 403, 422 request.validation (blank seatId, empty titleIds, or more than 30), 429 rate.limited over the per-client request-rate limit (honor the Retry-After header), 500.