Guide for new ActivityPub implementers

This is an informal guide to help new implementers get up to speed with the ActivityPub specification (published as a W3C Recommendation) and how to build projects with ActivityPub support.

:information_source:   Note: This is a Wiki Post that anyone can edit. Please help improve and extend this document !

Why choose ActivityPub?

Why might you choose to implement ActivityPub in your project? Possible reasons include:

  • “to move beyond the silos of social media sites run by individual companies” (ActivityPub as it has been understood)
  • Interoperability with a growing library of federated software
  • To reuse and extend existing libraries.
  • Collaboration with other projects looking to federate.


This guide includes links to many projects. The point of such links is not to recommend any specific project but to inform about the kinds of projects that would be useful to know about.

This guide is intended to expand on what’s in the relevant specifications. Those specs remain the primary sources and should be referred to during implementation.


If you’re used to specifications that contain a lot of jargon, you may be pleasantly surprised when you look at the ActivityPub specification. The authors put in a lot of effort to try to make the spec readable and easy to understand. A good starting place is the overview.

This guide is maintained by members of the SocialHub, a grassroots community of technologists and fedizens who together build the Fediverse ecosystem and evolve its standards. The community has a non-technical brainstorming area on Lemmy, called Fediverse Futures where you can gather feedback and elaborate ideas.


As an ActivityPub implementer you may find the following documents to be useful:

  • Specification for ActivityPub
  • Specification for ActivityStreams, the basis of ActivityPub.
  • Specification for Activity Vocabulary, which details “extended types” for ActivityStreams actors and objects such as Person and Note.
  • Specification for JSON-LD. ActivityPub and its two related specs, Activity Streams and Activity Vocabulary, all structure their data in JSON-LD. You may want to start with introductory material, such as:


Technical ActivityPub introductions

API documentation for specific implementations

What’s already out there?

As you start in, it’s useful to get a sense of what ActivityPub implementations and code projects already exist. Doing so will help you:

  • Identify opportunities to collaborate and combine efforts.
  • Identify examples and models to work from.
  • See how your project relates to others.
  • Connect with the ActivityPub community.

The delightful project maintains three up-to-date lists of Fediverse-related open source projects (these were formerly the ActivityPub Watchlists, migrated from Feneas when it shut down):

Additional places to look include:

  • The Software category and Programming category on the ActivityPub SocialHub forum.
  • Fediverse.Party, which lists Fediverse projects including ones that support ActivityPub. You can find information in two places:
    • The home page has links to a curated list of Fediverse projects. Click on each to find very detailed information on the projects, including the languages they’re written in.
    • A list of more apps has more basic information on a bunch of other projects. On this page you can filter to see only apps that support ActivityPub.
  • The various Fediverse aggregators, some of which include information on the software running each instance.

Implementing ActivityPub

The ActivityPub, Activity Streams, and Activity Vocabulary specifications are the main places to look for details on what’s required to implement ActivityPub support. The notes here are intended to give pointers on areas not covered by the specs or where clarification or subsequent work is relevant.

ActivityPub objects and activities

While formally there are eight core object types defined in the Activity Vocabulary spec, with many “extended” types, it can help to think of these objects as falling into four main groups:

  • Activity objects like Follow or Announce. An activity is an action undertaken by an actor.
  • Actor objects, like a Person or Group. Actors undertake activities like following or creating content.
  • Object (and link) types such as a Note or a Video. These objects types usually represent content of some sort.
  • Collection objects. These are groupings or listings of multiple other objects, such as a list of followers of a particular person or a list of public posts.

Implementing ActivityPub support is about letting actors like site members on your application or site - in the Fediverse, often called an instance - have back and forth exchanges with actors on other instances. As discussed in Episode 12: ActivityPub Part 1 of the LibreLounge podcast (15:26 - 20:24), ActivityPub structures these exchanges in a way that’s analogous to a simple subject-verb-object statement. In every message that’s sent server-to-server:

Somebody is doing something to some object. In ActivityPub terms, that’s an Actor is performing an Activity on an Object.

In ActivityPub, two servers are federated with each other when there is a relationship between one or more actors on each. A common relationship is following: an actor on one server follows an actor on another server. From there, a whole set of other activities are opened up, like when the followed actor posts a Note or Video, the follower’s account receives a notification (in the form of a Create activity).

Some data are tracked on both sides of the relationship. For example, if follows, that relationship is tracked both as a record on (georgie is in chris’s following collection) and on (chris is in georgie’s followers collection).

ActivityPub URIs serve a dual role depending on the HTTP method used. Pretty much, a given URI such as the id URI of a Person or the URI of an actor’s inboxsupports two types of operations:

  • GET fetches an object or collection of objects.
  • POST receives an activity in JSON-LD format.

Note that instead of the other standard HTTP methods - PATCH, PUT, DELETE - there are different activity types (Create, Update, Delete).

The id of an object is a URI that can be “dereferenced”–that is, assuming appropriate access authorization, a GET request to the URI will look up and return the full object.

So URIs that are the id of a single object such as an Actor return data about that object. Other URIs, such as that of an actor’s outbox, can return a Collection of objects.


If you’re developing for ActivityPub, you’re going to be dealing with JSON-LD, since that’s the format ActivityPub JSON is in. While JSON-LD can be handled as regular JSON, there are also specialized tools in JSON-LD that may be valuable to your application.

Expansion, compaction, flattening

One thing you’ll quickly notice when reading through code examples in the ActivityPub specifications is that the JSON-LD can be super variable in its format. Add to that the fact it will be coming from any number of different implementations and you’ve got a big challenge when it comes to parsing the incoming information.

So it’s worth noting that JSON-LD supports compacted and expanded formats as well as flattening of either. To avoid having to directly manage the inconsistencies of the compact format, you may want to standardize on expanded and flattened, then compact before returning. Flattening:

may drastically simplify the code required to process JSON-LD data in certain applications.

Discussion: More than JSON: ActivityPub and JSON-LD.

Conversion to and from RDF

If you’re working in an environment where there’s existing support for RDF, you might want to look at JSON-LD support for RDF serialization and deserialization.

JSON-LD libraries and packages

The JSON-LD specification is widely supported and you may find an implementation in your programming language that will provide basic functionality such as methods to expand, compact, and flatten. Packages include:


There’s an unofficial ActivityPubSchema that may be useful if you’re validating the JSON-LD of ActivityPub requests and responses.

The “missing” pieces

While the ActivityPub specification covers a lot, there are also areas that aren’t spelled out and left to implementers to decide. As Serge Wroclawski put it in an episode of the Libre Lounge podcast (1:38 - 1:52):

If you’re an implementer and you first look at ActivityPub, it seems like there’s a lot missing, and there absolutely is. And so what you have to do is you have to look at best practices at the time, which aren’t necessarily in the standard itself.

This section is about those current practices.

Discovery: Webfinger

How to look up actor accounts on another server?

In ActivityPub, an Actor such as a Person (often, a user with an account on a given site) is identified by an ID in the form of a URI. That URI could be what’s used to identify the actor on other ActivityPub sites. But URIs can be hard to work with and understand. A much more familiar format is user@domain.tld (or, by convention in the Fediverse, @user@domain.tld, to distinguish the handle from an email address).

The ActivityPub spec doesn’t cover profile discovery, that is, the ability to look up a handle like @user@domain.tld and find the URI for the account’s profile. However, per ActivityPub? Well, it’s not that bad:

Most current implementers have integrated Webfinger for that purpose, since users like to work with handles rather than URLs.

For example, Webfinger is implemented in Mastodon and is the recommended way to implement interoperability. See the Mastodon documentation on Webfinger and this tutorial.

Other resources as suggested in How to retrieve “user@server.tld” handle from actor’s URL:

The tutorial How to implement remote following for your ActivityPub project outlines how to use webfinger to help users follow local actors from remote ActivityPub applications (and vice-versa).

Authentication and authorization

ActivityPub doesn’t itself specify how to handle server to server user authentication, but it provides some hints in a wiki page, SocialCG/ActivityPub/Authentication Authorization. In your implementation you’ll probably find yourself implementing at least one of the solutions they point to.

Client to server

As noted in the SocialCG wiki:

ActivityPub clients authenticate against a server using OAuth 2.0 bearer tokens.

So if you’re building a client app, or if you’re building a server app that supports client connections, you’ll need to build in OAuth 2.0 support.

Note: There are a lot of intricacies to C2S authentication. See this AndStatus issue Basic implementation of “client to server” ActivityPub protocol (#499) for a detailed discussion with many cross-references.

Server to server
HTTP Signatures

HTTP Signatures is the approach taken in most current implementations.

Usually you’ll need to both:

  • Support HTTP signature verification from remote instances.
  • Verify HTTP signatures on incoming activities.

The tutorial How to implement a basic ActivityPub server includes a good introduction to HTTP Signatures and how to use them, including how to add a publicKey attribute to an actor object.

Linked Data Signatures

Linked Data Signatures are recommended when:

it is important to be able to verify that the actors specified in the actor and attributedTo fields really did author the objects they are being claimed to have authored.

Information about the instance/node

ActivityPub is all about actors, activities, and objects, but doesn’t say anything about the instance itself–the site that’s hosting all this. Various approaches are filling this gap.


There is a NodeInfo standard adopted by many ActivityPub implementations.

NodeInfo is:

an effort to create a standardized way of exposing metadata about a server running one of the distributed social networks. The two key goals are being able to get better insights into the user base of distributed social networking and the ability to build tools that allow users to choose the best fitting software and server for their needs.

There is an alternate NodeInfo2 standard.

NodeInfo2 is a fork of NodeInfo which was seen as too complex for the problem it is solving.

There has also been discussion about the possibility of ActivityPub-specific discovery.

Complementary to NodeInfo, some implementations have introduced a file to describe instance capabilities in a human readable way. See this discussion for more information. The files are a good way to get a sense of how different projects are using and adapting ActivityPub. Examples include:

Filtering out abuse and hate

ActivityPub provides a way to connect to other instances. But what if there are instances a particular site’s administrators don’t want to connect to? How to deal with the fact that the Fediverse is by default unfiltered and there are nodes that permit or actively encourage hate speech and abuse?

Background on the problem and proposed solutions:

A very basic approach is to enable whitelisting/blacklisting of ActivityPub domains so that an individual site’s admins can decide who to or not to federate with. That’s what’s supported in Mastodon.

Relevant background from the Mastodon project:


While you may find the set of objects and properties spelled out in the Activity Streams specs is sufficient for your use case, in many cases it won’t be.

The upside of custom extensions is they meet a specific need. The downside is they limit interoperability with other ActivityPub implementations.

While you can definitely create your own extensions, it’s worth getting familiar with what other implementers have already done.

Frequently Asked Questions

Designed to address the most common questions, this section is a compendium of tips, suggestions, and ideas around specific implementation questions.

What do I need to present to my users?

For starters, if you’re building a server app, you’ll probably want to display the ID of the user’s ActivityPub profile, since this is the way that others can interact with them in the Fediverse. If you’re using Webfinger, you may also want to display the format so that users on other instances can use that to mention or look up your users.

What document object types to use?

Activity Vocabulary defines several types of objects, such as Note, Article, and Video. Currently there is some tension between interoperability, on the one hand, and adherence the spec, on the other. Some implementers are focusing on what’s currently supported in Mastodon, where a Note will be fully displayed (minus certain markup) while an Article, for example, will appear as a link.

How to handle public content?

ActivityPub content may be publicly addressed. It’s left to implementers to decide how to handle such content.

Questions to consider include:

  • Should any locally generated public content be posted to all known sharedInbox URIs?
  • If you’ve implemented a sharedInbox, what if anything do you want to do with publicly addressed content that arrives there?

What’s special about the sharedInbox?

Among other uses, a shared inbox can optionally be used to send a single post to multiple actors who would otherwise need to each be messaged separately. When you are sending an activity to remote instances, instead of sending one per Actor, you can instead iterate through all your actors and post to the list of unique sharedInbox URIs. The ActivityPub spec notes:

in this scenario, the remote/receiving server participates in determining targeting and performing delivery to specific inboxes.

Participates? How?

The idea here is that in theory a following relationship is tracked on both sides: as part of a followers collection associated with the actor on the originating server and as part of a followed collection associated with the actor on the receiving server. So the originating server doesn’t need to explicitly list recipients. Instead, the receiving server can take the ID of the activity’s actor, look up its own list of who’s following that actor, and deliver the object to each member of that list.

What data do I need to store locally?

Many web application developers will be used to a model where there’s a clear separation between (a) what’s created and managed within the application and (b) any data objects that are externally hosted. For example, in the most simple case, you might have your own User and Article entities which you store locally. If you also, say, display remote content from an RSS feed, you might might model and store that content and its authors quite differently than your own User and Article data.

With ActivityPub, there’s at least the potential to use the same models for both local and remote objects. For example, if a user on your site both (a) posts Article content of their own and (b) follows actors on remote instances and so gets content when those remote actors make Article posts, you may decide to handle both local and remote articles in the same local model.

How can I add ActivityPub support to my existing software project?

If you have an existing software and want to add ActivityPub support, it may help to look at what that’s looked like for projects that have already done it. Places to look include:

Improving ActivityPub

Aided by a culture of collaboration among Fediverse advocates and participants, there is ongoing work to improve both the ActivityPub specification and interoperability among different ActivityPub implementations.

Join the conversation

Initiatives like FediConf, Feneas , and the ActivityPub forum on Activitypub.Rocks are great places to connect with other implementers and help move things forward.

Areas of critique and debate

As you assess the work of implementing in ActivityPub it can help to be up on some of the areas of discussion within the community.

Decisions against adopting ActivityPub

The Diaspora project has effectively decided against integrating with ActivityPub, see this issue which includes some critiques of the protocol. See also ActivityPub - Final thoughts, one year later.

Private content and trust

At and elsewhere, Ariadne Conill has critiqued the ActivityPub specification from a trust and safety perspective. See ActivityPub: The “Worse Is Better” Approach to Federated Social Networking and subsequent posts.

Others have critiqued the ActivityPub federation model’s reliance on external sites maintaining privacy restrictions. One commenter noted:

For the sake of privacy and safety I think that private posts should still only be pushed in stub/notification form (mostly because I don’t trust most ActivityPub implementations to keep private stuff private)

Federation issues

From A People’s History of the Fediverse

ActivityPub didn’t solve the longstanding federation issues which had been known about since before its creation, such as nomadic identity, key based identity rather than domain based identity and the ability to easily migrate accounts between instances.

Developer vs. user terminology

While “ActivityPub” may mean something to people with a technical bent, it’s probably not the best way to convey to site members what your software is and does.

“Fediverse” is probably a bit better, in that at least if you look it up you’re slightly more likely to find something basically readable. Still, it’s worth looking around at how other software are handling the question of presenting the ideas of federation and ActivityPub to their users.

More information

See the accompanying guides:


And an addendum

The ActivityPub spec, in checkboxes!

While the ActivityPub implementation report is outdated due to the test instance being down, the first column in that report is a valuable list of implementation details that comprise the ActivityPub spec.

Starting with what’s defined in the code driving the implementation report page, the following lists are designed to be easily copied into a set of tasks in an issue management system that supports GitHub flavoured Markdown, such as GitLab or GitHub.

Per the ActivityPub spec:

The key words MAY, MUST, MUST NOT, SHOULD, and SHOULD NOT are to be interpreted as described in RFC2119.

If implementing everything in these lists look like a ton of work, it’s worth noting that you may be able to skip whole sections. For example, if you’re focused on server to server support, you might be able to skip the entire client to server section. Also keep in mind this note from the Activity Vocabulary spec:

Support for specific extended vocabulary types is expected to vary, with implementations only selecting the extended types and properties that make sense within the specific context and requirements of those applications.

In short, while some stuff is needed across the board, there’s a lot you only have to worry about if you choose to support it.

For extra clarity and in case it’s handy, the lists include in parentheses the machine name assigned in the ActivityPub test suite to each item.

todo: coverage for “missing pieces” of the spec, such as authentication through HTTP Signatures.

Client to server interactions

  • Actor object’s outbox
    • Accepts Activity Objects (outbox:accepts-activities) MUST
    • Accepts non-Activity Objects, and converts to Create Activities per 7.1.1 (outbox:accepts-non-activity-objects) MUST
    • Removes the bto and bcc properties from Objects before storage and delivery (outbox:removes-bto-and-bcc) MUST
    • Ignores id on submitted objects, and generates a new id instead (outbox:ignores-id) MUST
    • Responds with status code 201 Created (outbox:responds-201-created) MUST
    • Response includes Location header whose value is id of new object, unless the Activity is transient (outbox:location-header)
    • Accepts Uploaded Media in submissions (outbox:upload-media) MUST
      • Accepts uploadedMedia file parameter (outbox:upload-media:file-parameter) MUST
      • Accepts uploadedMedia object parameter (outbox:upload-media:object-parameter) MUST
      • Responds with status code of 201 Created or 202 Accepted as described in 6. (outbox:upload-media:201-or-202-status) MUST
      • Response contains a Location header pointing to the to-be-created object’s id (outbox:upload-media:location-header) MUST
      • Appends an id property to the new object (outbox:upload-media:appends-id) MUST
      • After receiving submission with uploaded media, the server should include the upload’s new URL in the submitted object’s url property (outbox:upload-media:url) SHOULD
    • Update
      • Server takes care to be sure that the Update is authorized to modify its object before modifying the server’s stored copy (outbox:update:check-authorized) MUST
      • Supports partial updates in client-to-server protocol (but not server-to-server) (outbox:update:partial) NON-NORMATIVE
    • Server does not trust client submitted content (outbox:not-trust-submitted) SHOULD
    • Validate the content they receive to avoid content spoofing attacks (outbox:validate-content) SHOULD
    • Take care not to overload other servers with delivery submissions (outbox:do-not-overload) SHOULD
    • Create
      • Merges audience properties (to, bto, cc, bcc, audience) with the Create’s object’s audience properties (outbox:create:merges-audience-properties) SHOULD
      • Create’s actor property is copied to be the value of .object.attributedTo (outbox:create:actor-to-attributed-to) SHOULD
    • Follow
      • Adds followed object to the actor’s Following Collection (outbox:follow:adds-followed-object) SHOULD
    • Add
      • Adds object to the target Collection, unless not allowed due to requirements in 7.5 (outbox:add:adds-object-to-target) SHOULD
    • Remove
      • Remove object from the target Collection, unless not allowed due to requirements in 7.5 (outbox:remove:removes-from-target) SHOULD
    • Like
      • Adds the object to the actor’s Liked Collection (outbox:like:adds-object-to-liked) SHOULD
    • Block
      • Prevent the blocked object from interacting with any object posted by the actor (outbox:block:prevent-interaction-with-actor) SHOULD
    • Undo
      • Supports the Undo activity in the client-to-server protocol (outbox:undo) NON-NORMATIVE
      • Ensures that the actor in the activity actor is the same in activity being undone (outbox:undo:ensures-activity-and-actor-are-same) MUST
  • Actor object’s inbox
    • Delivery
      • [*] Performs delivery on all Activities posted to the outbox (inbox:delivery:performs-delivery) MUST
        • "Utilizes to, bto, cc, and bcc to determine delivery recipients. (inbox:delivery:addressing) MUST
      • Provides an id all Activities sent to other servers, unless the activity is intentionally transient (inbox:delivery:adds-id) MUST
      • Dereferences delivery targets with the submitting user’s credentials (inbox:delivery:submit-with-credentials) MUST
      • Delivers to all items in recipients that are Collections or OrderedCollections (inbox:delivery:deliver-to-collection) MUST
        • Applies the above, recursively if the Collection contains Collections, and limits recursion depth >= 1 (inbox:delivery:deliver-to-collection:recursively) MUST
      • Delivers activity with object property if the Activity type is one of Create, Update, Delete, Follow, Add, Remove, Like, Block, Undo (inbox:delivery:delivers-with-object-for-certain-activities) MUST
      • Delivers activity with ‘target’ property if the Activity type is one of Add, Remove (inbox:delivery:delivers-with-target-for-certain-activities) MUST
      • Deduplicates final recipient list (inbox:delivery:deduplicates-final-recipient-list) MUST
      • Does not deliver to recipients which are the same as the actor of the Activity being notified about (inbox:delivery:do-not-deliver-to-actor) MUST
      • SHOULD NOT deliver Block Activities to their object (inbox:delivery:do-not-deliver-block) SHOULD NOT
      • Delivers to sharedInbox endpoints to reduce the number of receiving actors delivered to by identifying all followers which share the same sharedInbox who would otherwise be individual recipients and instead deliver objects to said sharedInbox (inbox:delivery:sharedInbox) MAY
        • (For servers which deliver to sharedInbox:) Deliver to actor inboxes and collections otherwise addressed which do not have a sharedInbox (inbox:delivery:sharedInbox:deliver-to-inbox-if-no-sharedInbox) MUST
    • Accept
      • Deduplicates activities returned by the inbox by comparing activity ids") (inbox:accept:deduplicate) MUST
      • Forwards incoming activities to the values of to, bto, cc, bcc, audience if and only if criteria in 7.1.2 are met (inbox:accept:special-forward) MUST
        • Recurse through to, bto, cc, bcc, audience object values to determine whether/where to forward according to criteria in 7.1.2 (inbox:accept:special-forward:recurses) SHOULD
        • Limit recursion in this process (inbox:accept:special-forward:limits-recursion) SHOULD
      • Create
        • Supports receiving a Create object in an actor’s inbox (inbox:accept:create) NON-NORMATIVE
      • Delete
        • Assuming object is owned by sending actor/server, removes object’s representation (inbox:accept:delete) SHOULD
          • replace object’s representation with a Tombstone object (inbox:accept:delete:tombstone) MAY
      • Update
        • Take care to be sure that the Update is authorized to modify its object (inbox:accept:update:is-authorized) MUST
      • Completely replace its copy of the activity with the newly received value) (inbox:accept:update:completely-replace`) SHOULD
      • Don’t trust content received from a server other than the content’s origin without some form of verification (inbox:accept:dont-blindly-trust) SHOULD
      • `Follow
        • Add the actor to the object user’s Followers Collection (inbox:accept:follow:add-actor-to-users-followers) SHOULD
        • Generates either an Accept or Reject activity with Follow as object and deliver to actor of the Follow (inbox:accept:follow:generate-accept-or-reject) SHOULD
        • If in reply to a Follow activity, adds actor to receiver’s Following Collection (inbox:accept:accept:add-actor-to-users-following) SHOULD
        • If in reply to a Follow activity, MUST NOT add actor to receiver’s Following Collection (inbox:accept:reject:does-not-add-actor-to-users-following) MUST
      • Add
        • Add the object to the Collection specified in the target property, unless not allowed to per requirements in 7.8 (inbox:accept:add:to-collection) SHOULD
      • Remove the object from the Collection specified in the target property, unless not allowed per requirements in 7.9 (inbox:accept:remove:from-collection) SHOULD
      • Like
        • Perform appropriate indication of the like being performed (See 7.10 for examples) (inbox:accept:like:indicate-like-performed) SHOULD
        • Increments object’s count of shares by adding the received activity to the ‘shares’ collection if this collection is present (inbox:accept:announce:add-to-shares-collection) SHOULD
      • Undo
        • Performs Undo of object in federated context (inbox:accept:undo) NON-NORMATIVE
    • Validate the content they receive to avoid content spoofing attacks (inbox:accept:validate-content) SHOULD

Common server support

  • Inbox retrieval
    • Server responds to GET request at inbox URL (server:inbox:responds-to-get) NON-NORMATIVE
    • inbox is an OrderedCollection (server:inbox:is-orderedcollection) MUST
    • Server filters inbox content according to the requester’s permission (server:inbox:filtered-per-permissions) SHOULD
  • Object retrieval
    • Allow dereferencing Object ids by responding to HTTP GET requests with a representation of the Object (server:object-retrieval:get-id) MAY
      • Respond with the ActivityStreams object representation in response to requests that primarily Accept the media type application/ld+json; profile=\\ (server:object-retrieval:respond-with-as2-re-ld-json) MUST
    • Respond with the ActivityStreams object representation in response to requests that primarily Accept the media type application/activity+json (server:object-retrieval:respond-with-as2-re-activity-json) SHOULD
    • Responds with response body that is an ActivityStreams Object of type Tombstone (if the server is choosing to disclose that the object has been removed) (server:object-retrieval:deleted-object:tombstone) MAY
    • Respond with 410 Gone status code if Tombstone is in response body, otherwise responds with 404 Not Found (server:object-retrieval:deleted-object:410-status) SHOULD
    • Respond with 404 status code for Object URIs that have never existed (server:object-retrieval:deleted-object:404-status) SHOULD
    • Respond with a 403 Forbidden status code to all requests that access Objects considered Private (or 404 if the server does not want to disclose the existence of the object, or another HTTP status code if specified by the authorization method)) (server:object-retrieval:private-403-or-404`) SHOULD
  • Security considerations
    • B.1), Server verifies that the new content is really posted by the actor indicated in Objects received in inbox and outbox (server:security-considerations:actually-posted-by-actor`) NON-NORMATIVE
    • By default, implementation does not make HTTP requests to localhost when delivering Activities (server:security-considerations:do-not-post-to-localhost) NON-NORMATIVE
    • Implementation applies a whitelist of allowed URI protocols before issuing requests, e.g. for inbox delivery (server:security-considerations:uri-scheme-whitelist) NON-NORMATIVE
    • Server filters incoming content both by local untrusted users and any remote users through some sort of spam filter (server:security-considerations:filter-incoming-content) NON-NORMATIVE
    • Implementation takes care to sanitize fields containing markup to prevent cross site scripting attacks) (server:security-considerations:sanitize-fields) NON-NORMATIVE

Client applications

  • Submission
    • Client discovers the URL of a user’s outbox from their profile (client:submission:discovers-url-from-profile`) MUST
    • Client submits activity by sending an HTTP post request to the outbox URL with the Content-Type of application/ld+json; profile=\\ (client:submission:submit-post-with-content-type) MUST
    • Client submission request body is either a single Activity or a single non-Activity Object (client:submission:submit-objects) MUST
    • Clients provide the object property when submitting the following activity types to an outbox: Create, Update, Delete, Follow, Add, Remove, Like, Block, Undo (client:submission:submit-objects:provide-object) MUST
    • Clients provide the target property when submitting the following activity types to an outbox: Add, Remove. (client:submission:submit-objects:provide-target) MUST
    • Client submission request is authenticated with the credentials of the user to whom the outbox belongs (client:submission:authenticated`) MUST
    • Client supports uploading media by sending a multipart/form-data request body (client:submission:uploading-media) MUST
    • Before submitting a new activity or object, Client infers appropriate target audience by recursively looking at certain properties (e.g. inReplyTo, See Section 7), and adds these targets to the new submission’s audience (client:submission:recursively-add-targets) SHOULD
      • Client limits depth of this recursion (client:submission:recursively-add-targets:limits-depth) SHOULD
  • Retrieval
    • When retrieving objects, Client specifies an Accept header with the application/ld+json; profile=\\ media type (3.2) (client:retrieval:accept-header) MUST

[2020-01-21 04:31:44+0000] nedjo via SocialHub:


If you’re developing for ActivityPub, you’re going to be dealing with JSON-LD, since that’s the format ActivityPub JSON is in.

Not so much actually, AFAIK only Mastodon and Friendica actually uses JSON-LD, the other projects just treat it as JSON and maybe with some additionnal schema declaration for compatibility.

Which means that most implementations will probably tend to stick to some well-known types as the namespacing part of JSON-LD just goes away.

1 Like

Thank you so much for this nice elaborate guide !

Yes, very much.
Do you come to OFFDEM Brussels in 9 days ?

I would like to add some points :
Please see the post about the new main page and the demonstration -
@rigelk : I would love to see this guide at the page.
The new page tries to reach “implementers” and “end users”, so we could split the guide in 2 parts, the introduction, terminology, why and some resources are for “end-users” and we can make the rest for “implementers” and in the beginning link the userguide.

You questioned “Areas of critique and debate” and “What’s already out there?” and I would like to collect/add “FAQ” and “How to make it better” later.

should have a beginning link to

This is just my initial input, thank you again.
btw: If you want you can also make the post a wiki (keep a copy of the original then). This would make the guid directly editable for everyone.

@lanodan thanks, makes sense, I’ll make changes in the next draft.


Please see the post about the new main page and the demonstration -

Wow, the demonstration has some really great improvements!

The new page tries to reach “implementers” and “end users”, so we could split the guide in 2 parts, the introduction, terminology, why and some resources are for “end-users” and we can make the rest for “implementers” and in the beginning link the userguide.

I’d love to contribute to that. I’ll start by dividing up what I’ve drafted and filling in some additional pieces. I might try three parts: a general intro for everyone, a section for end users, and a section for implementers. I’ll draw on your and others’ suggestions, including those at Discussing the evolution of the site.

If you want you can also make the post a wiki (keep a copy of the original then). This would make the guid directly editable for everyone.

I looked for a way to post a wiki but didn’t find it. Can you point me in the right direction? Thx!

1 Like

The wiki should be at the more icon ••• and then at the :hammer_and_wrench: (without the hammer) – maybe only admins can do – then we can work it out after splitting.
Thank You.

Go-fed? Also go-ap link for me is broken for some reason (may be on my end).

I don’t have the required permission. I’ll contact a site admin and see what we can do.

If you want it to be a wiki now: I can change it.

Yes please! I’d like to divide this into three separate pieces:

  • An introduction to ActivityPub (for everyone, including users and implementers)
  • An ActivityPub users guide
  • An ActivityPub users implementers guide (this one)

Are you okay to create placeholder wikis for the other two as well as converting this one into a wiki?

And a couple of followup notes…

I’ve opened a couple of issues on the repo that powers Fediverse.Party:

I think that’s a better place for listings of projects than trying to replicate all that here.

Do you come to OFFDEM Brussels in 9 days ?

No, I’m too far away (west coast of Canada).

Both first posts (also “addendum”) are now wikis –
everybody should be able to edit them now.
Placeholders are not possible I think.

@Sebastian thx! I’ve done a first pass at redrafting as three guides. I’ve also pulled out most of what was in the section “Potential models and building blocks”. Instead I’ve pointed to some places to discover ActivityPub implementations and I’ll open an issue on Fediverse.Party to add in the projects I’d compiled that aren’t there already.

I’d like to start figuring out some next steps. If this is potential content for the draft improvements, how do we get from here to there? Maybe we need a documentation team? Maybe there is one already? In any case, I’d be happy to participate.

A post was split to a new topic: Wiki posts and the latest topics list

We’re hitting the length limit for posts, so I’ll add here a stub of a last section of the implementers’ guide on how to improve ActivityPub as suggested earlier by @Sebastian:

Improving ActivityPub

Aided by a culture of collaboration among Fediverse advocates and participants, there is ongoing work to improve both the ActivityPub specification and interoperability among different ActivityPub implementations. Initiatives like FediConf, Feneas, and the ActivityPub forum on Activitypub.Rocks are great places to connect with other implementers and help move things forward.


@nedjo: I’ve gone ahead and upped the post length limit, so at least until we find a better place for it we can continue on with posting here. I think we should also split a couple of these sections out into their own threads, like “Introduction to Activitypub” and “Guide for new Activitypub users”—would you mind making new threads for these? I think that would make this post a lot more navigable.

@nightpool: done:

When you get a chance, please convert those other two pages into wikis. Thx!

1 Like


I use it too. Mostly because of LD-signatures.

I created a topic to discuss this again: Easing the onboarding of new developers to the Fediverse (and this post will bump the wiki guide to the top again, which is also good for attention :wink: )