Follow a hashtag.
Per-actor follow list for hashtags. Posts using any of the followed tags get unioned into the actor's feed alongside posts from people they follow — both chronological and ranked modes pick them up.
1
Follow a tag
Idempotent: re-following the same tag refreshes followed_at but doesn't error.
curl -X POST \
-H "Authorization: Bearer pcft_live_..." \
-H "Content-Type: application/json" \
-d '{"tag":"storymode"}' \
"https://social.productcraft.co/v1/communities/<communityId>/actors/<actorId>/hashtag-follows"The tag must already exist in the community directory. Following a never-used tag would create a forward- reference into an empty pool — usually a typo. The endpoint returns 404 Hashtag not found in that case so the customer can prompt the user to refine.
2
Unfollow
Idempotent 204 either way.
curl -X DELETE \
-H "Authorization: Bearer pcft_live_..." \
"https://social.productcraft.co/v1/communities/<communityId>/actors/<actorId>/hashtag-follows/storymode"3
List my follows
Cursor-paginated newest-first by followed_at.
curl -H "Authorization: Bearer pcft_live_..." \
"https://social.productcraft.co/v1/communities/<communityId>/actors/<actorId>/hashtag-follows?limit=20"4
What changes in the feed
Once you follow at least one tag, your GET /actors/:actorId/feed response includes posts using those tags — even from authors you don't follow. Both order=ranked and order=chronological pick them up. The existing visibility filters still apply:
publicposts: always surface.followersposts: surface only if the author IS in your follow pool. A hashtag-followed post authored by a non-followee withvisibility="followers"stays hidden — by design.close_friends: surfaces only when you're on the author's close-friends list.- Block / mute filters apply uniformly: a post by an actor you blocked or muted never surfaces, regardless of tag follows.
Internals
How the feed unions tag matches
FeedService loads the actor's followed tags, then for each tag pulls a recent slice of post ids from post_hashtag. The combined list (capped at 200 ids) is unioned into the existing author-pool query via WHERE actor_id IN (...) OR id IN (...). One query plan, one cursor; results are sorted by the existing chronological / ranked rules.
Cap rationale: 200 keeps the SQL IN list bounded for index usage. The author-pool path still backfills the rest of the page if the union doesn't fill limit on its own.
Permissions
PAK scopes
- POST:
social.createonpcft:agora:community/<communityId>. - DELETE:
social.deleteon the same URN. - GET:
social.liston the same URN.