Social guides
Guides

Quote posts.

X-style quote-tweet. Pass kind='quote' + source_post_id + body to the existing post-create endpoint and you've got a quote — its own engagement, its own feed slot, its own edit history. The source carries a quote_count denormalised on the row.


Quote vs repost

Pick the right shape

  • Repost: share-without-comment. No body of its own; appears in followers' feeds attributed to the reposter with the source rendered inline. Use the dedicated POST /posts/:postId/repost route.
  • Quote post: share-with-comment. The quote IS a post — body, attributes, reactions, comments, edits. The original is referenced via source_post_id and rendered inline on the client.

1

Create a quote

Reuse the existing post-create endpoint with kind: "quote". Both source_post_id AND a non-empty body are required.

bash
curl -X POST \
  -H "Authorization: Bearer pcft_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "actor_id": "<actorId>",
    "kind": "quote",
    "source_post_id": "<sourcePostId>",
    "body": "this is exactly right — and here\\'s my take"
  }' \
  "https://social.productcraft.co/v1/communities/<communityId>/posts"

The response is the regular post row with kind="quote" and source_post_id set. The source post's quote_count is bumped immediately; the source author receives a quote_post notification (subject to per-kind preferences from task 021).


2

See the quotes of a post

X-style “show quotes” link. Cursor-paginated newest-first. Each entry is the full quote post row with its own body / counters / engagement.

bash
curl -H "Authorization: Bearer pcft_live_..." \
  "https://social.productcraft.co/v1/communities/<communityId>/posts/<sourcePostId>/quotes?limit=20"

Refusals

What 422s

  • CANNOT_QUOTE_SELF — quoting your own post.
  • CANNOT_QUOTE_PRIVATE — the source has visibility="private". Private content can't be redistributed.

And 400s: QUOTE_REQUIRES_SOURCE, QUOTE_REQUIRES_BODY, SOURCE_POST_ID_REQUIRES_QUOTE (passing source_post_id on a non-quote kind). Removed / draft / expired / invisible sources 404 opaque per the standard social boundary rule.


Behaviour

Quote vs repost

  • Engagement. The quote post earns reactions, comments, even gets quoted itself — everything posts get.
  • Edit history. Quotes participate in the edit window like any other post. Editing changes the quoter's commentary, not the source.
  • Hashtags / mentions. Parsed from the quote's body (not the source) — same as any regular post.
  • Counter. source.quote_count reflects current published quotes. Soft-deleting a quote (status → removed) does NOT decrement automatically; that's a parity gap with the existing post-delete path (post.delete only decrements post_count). File a follow-up if you need it tracked.
  • Notification. Source author gets a kind: "quote_post" notification with payload: { quote_post_id }. Suppressed for self / blocks / per-kind preference.

Permissions

PAK scopes

  • POST (the existing post create endpoint): social.create on pcft:agora:post/*.
  • GET /quotes: social.list on the community URN.