Suggested follows.
Two-tier recommendation: friend-of-a-friend signal first, top-by-followers fallback for new accounts that don't have an FoF graph yet. 1-hour cache per (actor, limit) — suggestions are stale-tolerant.
1
Read the suggestions
One endpoint, one shape. Returns up to limit candidates (default 20, max 50) ordered by signal strength. Each candidate carries a reason so the UI can label the row (“People you might know” vs “Popular in this community”).
curl -H "Authorization: Bearer pcft_live_..." \
"https://social.productcraft.co/v1/communities/<communityId>/actors/<actorId>/suggested-follows?limit=10"{
"data": [
{
"actor": {
"id": "aaaaaaaa-...",
"external_id": "ada",
"display_name": "Ada Lovelace",
"avatar_url": "https://...",
"status": "active",
"...": "..."
},
"score": 4,
"reason": "followed_by_friends"
},
{
"actor": { "id": "...", "external_id": "grace", "...": "..." },
"score": 1042,
"reason": "top_in_community"
}
]
}2
How candidates are picked
- followed_by_friends: count, per candidate, of the requester's followees who follow that candidate. Ordered descending. The classic friend-of-a-friend graph signal — if 4 of the people you follow also follow Ada, Ada surfaces with
score: 4. - top_in_community: cold-start fallback when FoF doesn't fill the requested limit (or returns nothing for a brand-new account). Ranks candidates by their
follower_countfromactor_counter.scoreis the follower count.
Excluded
Who never appears
- The requester themselves.
- Actors the requester already follows.
- Actors the requester has muted or blocked.
- Actors who have blocked the requester back (visibility parity with the existing block-aware feed).
- Suspended or deleted actors (status filter applied at the SQL layer).
Caching
What to expect
Results are cached per (community, actor, limit) for 1 hour. A new follow / mute / block by the requester does not bust the cache — they'll see the change reflected within the hour. Suggestions are inherently stale-tolerant; X / Threads / Instagram all cache at this cadence or longer.
If you need an immediate refresh after a UI action (e.g. user dismissed a candidate), call the endpoint with a different limit value — different limits map to different cache keys. The wire shape stays consistent.
Permissions
PAK scopes
- GET requires
social.listonpcft:agora:community/<communityId>. Member, admin, and owner system roles all have it by default.