Skip to content

Consume Recommendations

Read recommendations and search from the AI Engine API. Point the UI at the API base (the same tunnel host, or http://localhost:8000 locally).

const API = "https://merely-matrix-naples-jews.trycloudflare.com"; // or http://localhost:8000

Recommendations

const res = await fetch(`${API}/api/recommend?user_id=${userId}&limit=10`);
const { result } = await res.json();
// result.strategy is "warm" or "cold"; result.filter echoes the filter you sent
result.items.forEach(it => {
  render({
    id: it.id,
    title: it.content?.title,
    score: it.relevance_score,
    why: it.breakdown            // {semantic: 0.41, tag: 0.33} -> explanation
  });
});

Response shape (the payload is wrapped in result):

{
  "result": {
    "user_id": "u1",
    "strategy": "warm",
    "filter": null,
    "request_id": "9f1c...",
    "items": [
      { "id": "842", "rank": 1, "relevance_score": 0.74, "role": "target",
        "breakdown": { "semantic": 0.41, "tag": 0.33 },
        "content": { "id": "842", "title": "...", "content_type": "text_item" } }
    ],
    "diagnostics": {}
  }
}

Each item carries a breakdown you can surface as a "why this" cue (see Explainability) and a role (target or distractor).

Echo the request_id (closes the learning loop)

The response carries a request_id. Keep it with the items you render, and echo it on the resulting CONTENT_VIEW_ENDED event (properties.details.request_id) when the visitor finishes a recommended item. That join lets the bandit's reward find the exact served context (the feature vector it scored). Without the echo, served impressions and outcomes cannot be joined and the learned ranker gets no signal. See Send Events and Bandit / online learning.

X-Tenant-Id

On a multi-tenant deployment, send X-Tenant-Id: <id> on every request (and event). user_id and content_id only resolve within a tenant. No header means the default tenant. See Multi-tenancy.

If the deployment locks reads (SERVING_REQUIRES_KEY=1), send the tenant's X-API-Key instead: the tenant is derived from the key, so X-Tenant-Id isn't needed. See Authentication.

Query parameters

Param Purpose
user_id required, the visitor id
limit cap the number of items (1 to 50)
filter restrict candidates to a single tag, for example a location: filter=AiARLocationBarrack3
near_lat / near_lon the visitor's current GPS; re-ranks by proximity (geo scorer), independent of filter
geo_radius_m also hard-restrict candidates to this radius (metres) around near_lat/lon
include_content false returns a compact result (ids and scores only, no content blob)

filter (a discrete tag) and near_lat/near_lon (live GPS) are orthogonal; given together they compose by intersection. See Ranking -> geo.

// Filter recommendations to a location/tag
fetch(`${API}/api/recommend?user_id=${userId}&filter=AiARLocationBarrack3&limit=10`);

// Proximity re-rank, then a hard radius cutoff
fetch(`${API}/api/recommend?user_id=${userId}&near_lat=52.7579&near_lon=9.9048&geo_radius_m=500`);

// Compact payload (ids + scores, no content blob)
fetch(`${API}/api/recommend?user_id=${userId}&include_content=false`);

Test without events

POST /api/recommend/preview recommends from a hand-authored user model (tag affinity, liked items, demographics) without sending any events. Handy for trying the engine or for LLM evaluation. Same filter and include_content options apply.

Search and narrative

// Semantic search
const s = await (await fetch(`${API}/api/search?q=${encodeURIComponent(q)}`)).json();
s.result.forEach(item => render(item));   // item.score, item.highlight, item.title

// Geo search
fetch(`${API}/api/search/geo?lat=52.7579&lon=9.9048&radius_meters=2000`);

// Narrative from a set of items
fetch(`${API}/api/narrative`, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ items: selectedItems })
});

Inspect the user model (debug)

fetch(`${API}/api/usermodel?user_id=${userId}`); // positives, negatives, tag_affinity, taste_vector

Full request/response detail with a try-it console: the interactive AI Engine API.

CORS

The API allows all origins by default (demo posture). For production, restrict it to your UI origin. See Cloud and production.