Social guides
Guides

@-mentions.

Write @alice in a post or comment. Social parses the body, resolves "alice" to an actor by external_id, persists the mention row, and fires a "mention" notification to her inbox. Unknown handles are silently ignored — no errors, no notifications.


1

Mentions in posts

Use the existing post-create endpoint. Any @handle in body is parsed at write time. Handles are matched against actor.external_id (case-insensitive), de-duplicated, and capped at 50 per post body.

bash
curl -X POST \
  -H "Authorization: Bearer pcft_live_..." \
  -H "Content-Type: application/json" \
  -d '{"actor_id":"<authorActorId>","body":"shipping today, cc @ada and @grace"}' \
  "https://social.productcraft.co/v1/communities/<communityId>/posts"

Each resolved mention triggers a kind: "mention" notification on the recipient's inbox with target_kind: "post" and target_id set to the post UUID. Self-mentions, blocked-pair mentions, and per-kind opt-outs (see notification preferences) are filtered at write time — no row written, no inbox noise.


2

Mentions in comments

Same parser, same resolution rules. Comment mentions carry both comment_id and the parent post_id in the notification payload so the client can deep-link straight into the threaded view.

bash
curl -X POST \
  -H "Authorization: Bearer pcft_live_..." \
  -H "Content-Type: application/json" \
  -d '{"actor_id":"<commenterActorId>","body":"agreed @ada"}' \
  "https://social.productcraft.co/v1/communities/<communityId>/posts/<postId>/comments"

3

Updating: re-indexing on body changes

Editing the body of a post or comment re-runs the parser. Mentions removed from the new body are deleted from the index; mentions newly added are persisted and re-fan-out notifications. Editing only visibility / pinned / status doesn't re-parse — mentions ride on body content.


4

"Show me everywhere I'm tagged"

Per-actor mentions feed. Cursor-paginated newest-first, interleaving posts + comments. Each entry carries source (post or comment), source_id, and the parent post_id so the client can deep-link either way.

bash
curl -H "Authorization: Bearer pcft_live_..." \
  "https://social.productcraft.co/v1/communities/<communityId>/actors/<actorId>/mentions?limit=20"
json
{
  "data": [
    { "source": "post",    "source_id": "p-1", "post_id": "p-1", "mentioned_id": "...", "created_at": "2026-05-11T12:00:00.000Z" },
    { "source": "comment", "source_id": "c-7", "post_id": "p-3", "mentioned_id": "...", "created_at": "2026-05-10T08:00:00.000Z" }
  ],
  "pagination": { "next_cursor": null, "has_more": false }
}

Parser rules

What counts as a mention

  • Pattern: @ followed by 1..32 chars from [a-z0-9_], case-insensitive (but matched against external_id in lowercase).
  • A handle longer than 32 chars never matches — the parser uses a negative lookahead so it doesn't silently truncate.
  • Duplicates within the same body collapse to one notification.
  • Cap: 50 mentions per body. Beyond that, additional@handles are silently dropped.
  • Unknown handles (no actor with that external_id) are silently ignored — no error, no notification.

Permissions

PAK scopes

  • POST / PATCH on the post + comment endpoints uses their existing scopes (social.create / social.update) — no extra grant needed for mentions.
  • GET /actors/:actorId/mentions requires social.list on pcft:agora:community/<communityId>.