Discussion
Loading...

Post

  • About
  • Code of conduct
  • Privacy
  • Users
  • Instances
  • About Bonfire
Terence Eden’s Blog
@blog@shkspr.mobi  ·  activity timestamp last week

Getting started with Mastodon's Quote Posts - technical implementation details for servers

https://shkspr.mobi/blog/2025/10/getting-started-with-mastodons-quote-posts-technical-implementation-details-for-servers/

Quoting posts on Mastodon is slightly complex. Because of the privacy conscious nature of the platform and its users, reposting isn't merely a case of sharing a URl.

A user writes a status. The user can choose to make their statuses quotable or not. What happens when a quoter quotes that post?

I've read through the specification and tried to simplify it. Quoting is a multi-step process:

  1. The status must opt-in to being shared.
  2. The quoter quotes the status.
  3. The quoter's server sends a request to the status's server.
  4. The status's server sends an accept message back to the quoter's server.
  5. When other servers see the quote, they check with the status's server to see if it is allowed.

I'm going to walk you through each stage as best as I understand them.

Opting In

An ActivityPub status message is JSON. In order to opt-in, it needs this additional field.

 JSON"interactionPolicy": { "canQuote": { "automaticApproval": "https://www.w3.org/ns/activitystreams#Public" }}

That tells ActivityPub clients that anyone is allowed to quote this post. It is also possible to say that only specific users, or only followers, or no-one is allowed.

The QuoteRequest

Someone has hit the quote post button, typed their own message, and shared their wisdom. Their server sends the following message to the server which hosts the quoted status. This has been edited for brevity.

 JSON{ "@context": [ "https://www.w3.org/ns/activitystreams", { "QuoteRequest": "https://w3id.org/fep/044f#QuoteRequest" } ], "type": "QuoteRequest", "id": "https://mastodon.test/users/Edent/quote_requests/1234-5678-9101", "actor": "https://mastodon.test/users/Edent", "object": "https://example.com/posts/987654321.json", "instrument": { "id": "https://mastodon.test/users/Edent/statuses/123456789", "url": "https://mastodon.test/@Edent/123456789", "attributedTo": "https://mastodon.test/users/Edent", "quote": "https://example.com/posts/987654321.json", "_misskey_quote": "https://example.com/posts/987654321.json", "quoteUri": "https://example.com/posts/987654321.json" }}

All this says is "I would like permission to quote you."

The Stamp

The quoted server needs to approve this quote. First, it generates a "stamp".

This is a file which lives on the quoted server. It is proof that the quote is allowed. If it is deleted, the quote permission is revoked. When the stamp's ID is requested the stamp must be returned.

 JSON{ "@context": [ "https://www.w3.org/ns/activitystreams", { "gts": "https://gotosocial.org/ns#", "QuoteAuthorization": { "@id": "https://w3id.org/fep/044f#QuoteAuthorization", "@type": "@id" }, "interactingObject": { "@id": "gts:interactingObject" }, "interactionTarget": { "@id": "gts:interactionTarget" } } ], "type": "QuoteAuthorization", "id": "https://example.com/quote-987654321.json", "attributedTo": "https://example.com/users/username", "interactionTarget": "https://example.com/posts/987654321.json", "interactingObject": "https://mastodon.test/users/Edent/statuses/123456789"}

If the quoted status is viewed from a different server, that server will query the stamp to make sure the share is allowed.

The Accept

This is the message that the quoted server sends to the quoting server. It references the request and the stamp.

 JSON{ "@context": [ "https://www.w3.org/ns/activitystreams", { "QuoteRequest": "https://w3id.org/fep/044f#QuoteRequest" } ], "type": "Accept", "to": "https://mastodon.test/users/Edent", "id": "https://example.com/posts/987654321.json", "actor": "https://example.com/account", "object": { "type": "QuoteRequest", "id": "https://mastodon.test/users/Edent/quote_requests/1234-5678-9101", "actor": "https://mastodon.test/users/Edent", "instrument": "https://mastodon.test/users/Edent/statuses/123456789", "object": "https://example.com/posts/987654321.json" }, "result": "https://example.com/quote-987654321.json"}

The "result" must be the same as the stamp's URl.

And then?

You can follow and quote @colours@colours.bots.edent.tel on your favourite Fediverse platform.

I've written an ActivityPub server in a single file which is designed to teach you have the protocol works. Have a play with ActivityBot.

#ActivityPub #fediverse #mastodon #MastodonAPI

Codeberg.org

fep/fep/044f/fep-044f.md at main

fep - Fediverse Enhancement Proposals
Screenshot of me quoting a post.
Screenshot of me quoting a post.
Screenshot of me quoting a post.
  • Copy link
  • Flag this post
  • Block
Log in

bonfire.cafe

A space for Bonfire maintainers and contributors to communicate

bonfire.cafe: About · Code of conduct · Privacy · Users · Instances
Bonfire social · 1.0.0-rc.3.13 no JS en
Automatic federation enabled
  • Explore
  • About
  • Members
  • Code of Conduct
Home
Login