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/repostroute. - Quote post: share-with-comment. The quote IS a post — body, attributes, reactions, comments, edits. The original is referenced via
source_post_idand 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.
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.
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_countreflects 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 withpayload: { quote_post_id }. Suppressed for self / blocks / per-kind preference.
Permissions
PAK scopes
- POST (the existing post create endpoint):
social.createonpcft:agora:post/*. - GET
/quotes:social.liston the community URN.