One endpoint, two flavours.
`GET /actors/:actorId/feed` — chronological for a strict timeline, ranked for an algorithmic home tab. Same response shape, same cursor pagination, same block + visibility filtering.
1
Chronological feed
Time-ordered. Returns posts authored by the actor or by anyone they follow, excluding any actor involved in a block with them. private-visibility posts are surfaced only when the requester is the author.
curl -H "Authorization: Bearer pcft_live_..." \
"https://agora.productcraft.co/v1/communities/<c>/actors/<actor-uuid>/feed?order=chronological&limit=20"{
"data": [
{ "id": "...", "kind": "image", "actor_id": "<carol>", "title": "Mercado Benito Juárez at golden hour", ... },
{ "id": "...", "kind": "link", "actor_id": "<bob>", "title": "Database schema migrations without downtime", ... },
{ "id": "...", "kind": "text", "actor_id": "<alice>", "body": "Just shipped the Glow style guide v0.4 ...", ... }
],
"pagination": { "next_cursor": null, "has_more": false }
}2
Ranked feed (default)
order=ranked blends four signals into a single SQL-side score:
- Recency — exponential decay with a configurable half-life.
- Engagement — log-scaled count of comments + reactions.
- Follow-graph bias — currently a constant; reserved for a future "discover" widening of the candidate pool.
- Self-author boost — keeps the actor's own posts visible.
Each signal's weight is read from community.settings.ranking at query time. Defaults work out of the box.
# Ranked is the default; you can omit ?order=ranked
curl -H "Authorization: Bearer pcft_live_..." \
"https://agora.productcraft.co/v1/communities/<c>/actors/<actor-uuid>/feed?limit=20"3
Tuning ranking
Per-community weights live on the community settings. Lower the recency weight if you want more evergreen content; bump engagement to push high-comment threads up; adjust the half-life for how fast posts cool off.
# Update the ranking weights from the admin lane (cookie / PlatformUser bearer).
curl -X PATCH -H "content-type: application/json" \
-H "Cookie: auth_token=<your-platform-session>" \
-d '{
"settings": {
"ranking": {
"w_recency": 0.6,
"w_engagement": 0.3,
"w_follow_bias": 0.05,
"w_self_boost": 0.05,
"half_life_hours": 12,
"candidate_window_days": 7
}
}
}' \
https://agora.productcraft.co/v1/workspaces/<ws>/communities/<c>4
Cursors
Cursors are not interchangeable between modes — passing a chronological cursor with order=ranked returns 400 INVALID_CURSOR. A malformed cursor is silently treated as page-1 (no error, just a restart). Always re-paginate from has_more=true + next_cursor within a single mode.
5
Empty state
When the actor follows no-one and has no posts, both modes return { "data": [], "pagination": { "next_cursor": null, "has_more": false } } with a 200. The endpoint is the right one to wire up your empty-feed CTA against — it doesn't 404 on a no-content actor.