Copyright © 2017 W3C® (MIT, ERCIM, Keio, Beihang). W3C liability, trademark and permissive document license rules apply.
The ActivityPub protocol is a decentralized social networking protocol based upon the [ActivityStreams] 2.0 data format. It provides a client to server API for creating, updating and deleting content, as well as a federated server to server API for delivering notifications and subscribing to content.
This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at https://www.w3.org/TR/.
This document is a proposed submission to the W3C Social working group.
This document was published by the Social Web Working Group as a Candidate Recommendation. This document is intended to become a W3C Recommendation. If you wish to make comments regarding this document, please send them to public-socialweb@w3.org (subscribe, archives). W3C publishes a Candidate Recommendation to indicate that the document is believed to be stable and to encourage implementation by the developer community. This Candidate Recommendation is expected to advance to Proposed Recommendation no earlier than 27 April 2017. All comments are welcome.
Please see the Working Group's implementation report.
Publication as a Candidate Recommendation does not imply endorsement by the W3C Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.
This document was produced by a group operating under the 5 February 2004 W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.
This document is governed by the 1 March 2017 W3C Process Document.
The ActivityPub protocol is broadly based on the distribution of activities, described using [ActivityStreams]; these activities are produced in response to a user performing delivery of an activity. Most activities are purely responsive in nature - they are produced as a response to a user having done something. In addition, certain activities posted by a user to their outbox may trigger certain side effects on the user's behalf. Finally, activities may have side effects as they propagate throughout the social graph by being posted to the inboxes of other actors on the network. As an example of this:
Like
activity to their outbox.
This activity causes the user's server to perform delivery of an
activity on behalf of the user, adding the specified object to the
collection of objects the user has liked.
As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.
The key words MAY, MUST, MUST NOT, SHOULD, and SHOULD NOT are to be interpreted as described in [RFC2119].
This specification defines two closely related and interacting protocols:
All servers claiming conformance to this specification are required to implement the former protocol, and may optionally implement the latter. This gives three conformance classes:
It is called out whenever a portion of the specification only applies to implementation of the federation protocol. In addition, whenever requirements are specified, it is called out whether they apply to the client or server (for the client-to-server protocol) or whether referring to a sending or receiving server in the server-to-server protocol.
For this specification to advance to Proposed Recommendation, there must be at least two independent, interoperable implementations of each feature. Each feature may be implemented by a different set of products. There is no requirement that all features be implemented by a single product.
For the purposes of evaluating exit criteria, each of the following is considered a feature:
The Working Group has marked the following features as At Risk and may seek to advance the specification with the removal of these features if insufficient implementation experience can be gathered.
preferredUsername
property.
publicInbox
endpoint.
Objects are the core concept around which both [ActivityStreams] and ActivityPub are built. Objects are often wrapped in Activities and are contained in streams of Collections, which are themselves subclasses of Objects. See the Activity Vocabulary document, particularly the Core Classes; ActivityPub follows the mapping of this vocabulary very closely.
ActivityPub defines some terms in addition to those provided by
ActivityStreams. These terms are provided in the ActivityPub
JSON-LD context at
https://www.w3.org/ns/activitystreams
. Implementers SHOULD include the ActivityPub context in their object definitions. Implementers MAY include additional context as appropriate.
ActivityPub shares the same URI / IRI conventions as in ActivityStreams.
Servers SHOULD validate the content they receive to avoid content spoofing attacks. In particular, servers SHOULD NOT trust client submitted content, and federated servers also SHOULD NOT trust content received from a server other than the content's origin without some form of verification. No particular mechanism for verification is authoritively specified by this document, though some possible directions are discussed in 9. Authentication and Authorization. (A server should do something at least as robust as checking that the object appears as received at its origin, but better mechanisms such as checking signatures would be better if available).
{
"@context": "https://www.w3.org/ns/activitystreams",
"type": "Like",
"actor": "https://example.net/~mallory",
"to": ["https://hatchat.example/sarah/",
"https://example.com/peeps/john/"],
"object": {
"@context": {"@language": "en"},
"id": "https://example.org/~alice/note/23",
"type": "Note",
"author": "https://example.org/~alice",
"content": "I'm a goat"
}
}
id
both to ensure that it
exists and is a valid object, and that it is not misrepresenting the
object. (In this example, Mallory could be spoofing an object allegedly
posted by Alice).
All Objects in [ActivityStreams] should have unique global identifiers. ActivityPub extends this requirement; all objects distributed by the ActivityPub protocol MUST have unique global identifiers, unless they are intentionally transient (short lived activities that are not intended to be able to be looked up, such as some kinds of chat messages or game notifications). These identifiers must fall into one of the following groups:
null
object, which implies an anonymous object (a part of its parent context)
Identifiers MUST be
provided for activities posted in server to server communication, unless
the activity is intentionally transient. However, for client to server
communication, a server receiving an object with no specified id
SHOULD allocate an object ID in the user's namespace and attach it to the posted object.
All objects have the following properties:
id
MAY be omitted).
The HTTP GET method may be dereferenced against an object's
id
property to retrieve the activity. Servers MAY use HTTP content negotiation as defined in [RFC7231] to select the type of data to return in response to a request, but MUST present the ActivityStreams object representation in response to
application/ld+json; profile="https://www.w3.org/ns/activitystreams"
, and SHOULD also present the ActivityStreams representation in response to application/activity+json
as well. The client MUST specify an Accept
header with the
application/ld+json; profile="https://www.w3.org/ns/activitystreams"
media type in order to retrieve the activity.
Servers MAY implement other behavior for requests which do not comply with the above requirement. (For example, servers may implement additional legacy protocols, or may use the same URI for both HTML and ActivityStreams representations of a resource).
Servers MAY require authorization as specified in 9. Authentication and Authorization, and may additionally implement their own authorization rules. Servers SHOULD fail requests which do not pass their authorization checks with the appropriate HTTP error code, or the 403 Forbidden error code where the existence of the object is considered private. An origin server which does not wish to disclose the existence of a private target MAY instead respond with a status code of 404 Not Found.
In addition to all the properties defined by the
Activity Vocabulary, ActivityPub extends the Object
by supplying the
source
property. The source
property is intended to convey some sort of source from which the content
markup was derived, as a form of provenance, or to support future
editing by clients. In general, clients do the conversion from source
to content
, not the other way around.
The value of source
is itself an object which uses its own content
and mediaType
fields to supply source information.
{
"@context": ["https://www.w3.org/ns/activitystreams",
{"@language": "en"}],
"object": "Note",
"id": "http://postparty.example/p/2415",
"content": "<p>I <em>really</em> like strawberries!</p>",
"source": {
"content": "I *really* like strawberries!",
"mediaType": "text/markdown"},
}
In general, it's best to let a user edit their original post
in the same source format they originally composed it in. But not all
clients can reliably provide a nice interface for all source types, and
since clients are expected to do the conversion from source
to content
,
some clients may work with a media type that another client does not
know how to work with. While a client could feasibly provide the content
markup to be edited and ignore the source, this means that the user will lose the more desirable form of the original
source
in any future revisions. A client doing
so should thus provide a minimally obtrusive warning cautioning that the
original source format is not understood and is thus being ignored.
For example, Alyssa P. Hacker likes to post to her
ActivityPub powered blog via an Emacs client she has written, leveraging
Org mode. Later she switches to editing on her phone's client, which has no idea what text/x-org
is or how to render it to HTML, so it provides a text box to edit the original
content
instead. A helpful warning displays
above the edit area saying, "This was originally written in another
markup language we don't know how to handle. If you edit, you'll lose
your original source!" Alyssa decides the small typo fix isn't worth
losing her nice org-mode markup and decides to make the update when she
gets home.
Actors are [ActivityStreams] Objects, generally one of the
ActivityStreams Actor Types, and are retrieved like any other Object in ActivityPub. Like other ActivityStreams objects, actors have an id
,
which is a URI. When entered directly into a user interface (for
example on a login form), it is desirable to support simplified naming.
For this purpose, ID normalization SHOULD be performed as follows:
example.org/alice/
, clients MAY attempt to provide a default scheme, preferably https
.
Once the actor's URI has been identified, it should be dereferenced.
Actor objects are ActivityStreams objects which are subclasses of the
Actor
type. Actor objects MUST have, in addition to the properties mandated by 3.1 Object Identifiers, the following properties:
Implementations SHOULD, in addition, provide the following properties:
{
"@context": ["https://www.w3.org/ns/activitystreams",
{"@language": "ja"}],
"type": "Person",
"id": "https://kenzoishii.example.com/",
"following": "https://kenzoishii.example.com/following.json",
"followers": "https://kenzoishii.example.com/followers.json",
"likes": "https://kenzoishii.example.com/likes.json",
"inbox": "https://kenzoishii.example.com/inbox.json",
"outbox": "https://kenzoishii.example.com/feed.json",
"preferredUsername": "kenzoishii",
"name": "石井健蔵",
"summary": "この方はただの例です",
"icon": [
"https://kenzoishii.example.com/image/165987aklre4"
]
}
Implementations MAY, in addition, provide the following properties:
The endpoints
mapping MAY include the following properties:
x-www-form-urlencoded
id
parameter with the value being the id
of the requested ActivityStreams object.
publicInbox
endpoints SHOULD also be publicly readable OrderedCollection
objects.
As the upstream vocabulary for ActivityPub, any applicable [ ActivityStreams] property may be used on ActivityPub Actors. Some ActivityStreams properties are particularly worth highlighting to demonstrate how they are used in ActivityPub implementations.
id
.
Properties containing natural language values, such as name
, preferredUsername
, or
summary
, make use of
natural language support defined in ActivityStreams.
[ActivityStreams] defines the collection concept; ActivityPub defines several collections with special behavior. Note that ActivityPub makes use of ActivityStreams paging to traverse large sets of objects.
Note that some of these collections are specified to be of type
OrderedCollection
specifically, while others are permitted to be either a
Collection
or an
OrderedCollection
. An
OrderedCollection
MUST be presented consistently in reverse chronological order.
What property is used to determine the reverse chronological order is intentionally left as an implementation detail. For example, many SQL-style databases use an incrementing integer as an identifier, which can be reasonably used for handling insertion order in most cases. In other databases, an insertion time timestamp may be preferred. What is used isn't important, but the ordering of elements must remain intact, with newer items first. A property which changes regularly, such a "last updated" timestamp, should not be used.
Every actor SHOULD have a followers
collection. This is a list of everyone who has sent a
Follow activity for the user, added as a
side effect. This is where one would find a list of all the users that are following the actor. The followers
collection MUST be either an
OrderedCollection
or a
Collection
and MAY be filtered on privileges of an authenticated user or as appropriate when no authentication is given.
The follow activity generally is a request to see the objects a user creates. This makes the Followers collection an appropriate default target for delivery of notifications.
Every actor SHOULD have a following
collection. This is a list of everybody that the actor has followed, added as a
side effect. The following
collection MUST be either an
OrderedCollection
or a
Collection
and MAY be filtered on privileges of an authenticated user or as appropriate when no authentication is given.
Every actor MAY have a likes
collection. This is a list of every object from all of the actor's Like
activities, added as a side effect. The likes
collection MUST be either an
OrderedCollection
or a
Collection
and MAY be filtered on privileges of an authenticated user or as appropriate when no authentication is given.
The outbox is discovered through the outbox
property of an actor's profile. The outbox
MUST be an
OrderedCollection
.
The outbox stream contains objects the user has published, subject to the ability of the requestor to retrieve the object (that is, the contents of the outbox are filtered by the permissions of the person reading it). If a user submits a request without Authorization the server should respond with all of the Public posts. This could potentially be all relevant objects published by the user, though the number of available items is left to the discretion of those implementing and deploying the server.
The outbox accepts HTTP POST requests, with behaviour described in Client to Server Interactions.
The inbox is discovered through the inbox
property of an actor's profile. The inbox
MUST be an
OrderedCollection
.
The inbox stream contains all objects received by the user. The server SHOULD filter content according to the requester's permission. In general, the owner of an inbox is likely to be able to access all of their inbox contents. Depending on access control, some other content may be public, whereas other content may require authentication for non-owner users, if they can access the inbox at all.
The server MUST perform
de-duplication of activities returned by the inbox. Duplication can
occur if an activity is addressed both to a user's followers, and a
specific user who also follows the recipient user, and the server has
failed to de-duplicate the recipients list. Such deduplication MUST be performed by comparing the
id
of the activities and dropping any activities already seen.
The inbox accepts HTTP POST requests, with behaviour described in Delivery.
In addition to [ActivityStreams] collections and objects, Activities may additionally be addressed to the special "public" collection, with the identifier
https://www.w3.org/ns/activitystreams#Public
. For example:
{
"@context": "https://www.w3.org/ns/activitystreams",
"id": "https://www.w3.org/ns/activitystreams#Public",
"type": "Collection"
}
Activities addressed to this special URI shall be accessible to all users, without authentication. Implementations MUST NOT deliver to the "public" special collection; it is not capable of receiving actual activities.
ActivityPub supports uploading document types to be referenced in
activites, such as images, video or other binary data, and servers
MAY implement this feature. To accomplish this, a client MUST submit a
multipart/form-data
message to the user's
uploadMedia
endpoint on
their ActivityStreams profile object. A client should expect that it
must be properly authenticated in order to be able to upload media.
The submitted form data should contain two parts / fields:
Assuming that the server accepts the request and that the user was appropriately authorized to upload media, servers MUST respond with a
201 Created
if the object is immediately available or a
202 Accepted
if the server is still processing the submitted media. The response MUST contain a Location
header pointing to the to-be-created object's id
.
The server, having done any appropriate processing on the received
file
and putting it in place, transforms the
object
that will be retrievable by the id
. In particular, servers MUST append an id
property to the object, and SHOULD include the uploaded and/or processed file paths in the object's url
property. The server MAY wrap the shell object submitted by the user in a
Create
via 7.1.1 Object creation without a Create Activity if appropriate and present this as the object pointed to by the forementioned Location
header in the post-media-upload response.
Activities as defined by [ActivityStreams] are the core mechanism for creating, modifying and sharing content within the social graph. Client to server interaction takes place through clients posting activities to a user's outbox.
Clients are responsible for addressing new
Activites appropriately. To some extent, this is dependent upon the
particular client implementation, but clients must be aware that the
server will only forward new Activities to addressees in the to
,
bto
, cc
, bcc
, and
audience
fields.
The Followers Collection and/or the Public Collection are good choices for the default addressing of new Activities.
Clients SHOULD look at any objects attached to the new Activity via the
object
, target
, inReplyTo
and/or
tag
fields, retrieve their actor
or
attributedTo
properties, and MAY also retrieve their addressing properties, and add these to the to
or cc
fields of the new Activity being created. Clients MAY recurse through attached objects, but if doing so, SHOULD set a limit for this recursion.
Clients MAY give the user the chance to amend this addressing in the UI.
For example, when Chris likes the following article by Amy:
{
"@context": ["https://www.w3.org/ns/activitystreams",
{"@language": "en-GB"}],
"id": "https://rhiaro.co.uk/2016/05/minimal-activitypub",
"type": "Article",
"name": "Minimal ActivityPub update client",
"content": "Today I finished morph, a client for posting ActivityStreams2...",
"attributedTo": "https://rhiaro.co.uk/#amy",
"to": "https://rhiaro.co.uk/followers/",
"cc": "https://e14n.com/evan"
}
the like is generated by the client as:
{
"@context": ["https://www.w3.org/ns/activitystreams",
{"@language": "en"}],
"type": "Like",
"actor": "https://dustycloud.org/chris/"
"name": "Chris liked 'Minimal ActivityPub update client'",
"object": "https://rhiaro.co.uk/2016/05/minimal-activitypub",
"to": ["https://rhiaro.co.uk/#amy",
"https://dustycloud.org/followers",
"https://rhiaro.co.uk/followers/"],
"cc": "https://e14n.com/evan"
}
The receiving outbox can then perform delivery to not only the followers of Chris (the liker), but also to Amy, and Amy's followers and Evan, both of whom received the original article.
To submit new Activities to a user's server, clients MUST discover the URL of the user's outbox from their profile and then MUST make an HTTP POST
request to to this URL with the Content-Type of
application/ld+json; profile="https://www.w3.org/ns/activitystreams"
. The request MUST be authenticated with the credentials of the user to whom the outbox belongs. The body of the POST
request MUST contain a single Activity (which MAY contain embedded objects), or a single non-Activity object which
will be wrapped in a Create activity
by the server.
POST /outbox/ HTTP/1.1
Host: dustycloud.org
Authorization: Bearer XXXXXXXXXXX
Content-Type: application/ld+json; profile="https://www.w3.org/ns/activitystreams"
{
"@context": ["https://www.w3.org/ns/activitystreams",
{"@language": "en"}],
"type": "Like",
"actor": "https://dustycloud.org/chris/"
"name": "Chris liked 'Minimal ActivityPub update client'",
"object": "https://rhiaro.co.uk/2016/05/minimal-activitypub",
"to": ["https://rhiaro.co.uk/#amy",
"https://dustycloud.org/followers",
"https://rhiaro.co.uk/followers/"],
"cc": "https://e14n.com/evan"
}
If an Activity is submitted with a value in the id
property, servers MUST ignore this and generate a new id
for the Activity. Servers MUST return a 201 Created
HTTP code, and unless the activity is transient, MUST include the new id
in the
Location
header.
HTTP/1.1 201 Created
Location: https://dustycloud.org/likes/345
The server MUST remove the bto
and/or bcc
properties, if they exist, from the ActivityStreams object before storage and delivery, but MUST utilize the addressing originally stored on the bto
/ bcc
properties for determining recipients in delivery.
The server adds this new Activity to the outbox collection. Depending on the type of Activity, servers may then be required to carry out further side effects. These are described per individual Activity below.
Clients submitting the following activities to an outbox
MUST provide the object
property in the activity:
Create
, Update
, Delete
,
Follow
, Add
, Remove
,
Like
, Block
, Undo
. Additionally, clients submitting the following activities to an outbox
MUST also provide the target
property:
Add
, Remove
.
The Create
activity is used when posting a new object. This has the side effect that the object embedded within the Activity (in the object
property) is created.
When a Create
activity is posted, the actor
of the activity SHOULD be copied onto the object
's
attributedTo
field.
A mismatch between addressing of the Create activity and its
object
is likely to lead to confusion. As such, a server SHOULD copy any recipients of the Create activity to its object
upon initial distribution, and likewise with copying recipients from the object
to the wrapping Create activity. Note that it is acceptable for the object
's addressing to be changed later without changing the Create
's addressing (for example via an Update
activity).
For client to server posting, it is possible to submit an
object for creation without a surrounding activity. The server MUST accept a valid [ActivityStreams] object that isn't a subtype of Activity
in the POST request to the outbox. The server then MUST attach this object as the object
of a Create Activity. For non-transient objects, the server MUST attach an
id
to both the wrapping Create
and its wrapped Object
.
The Location
value returned by the server should be the URL of the new Create activity (rather than the object).
Any to
, bto
, cc
, bcc
, and audience
properties specified on the object MUST be copied over to the new Create activity by the server.
{
"@context": "https://www.w3.org/ns/activitystreams",
"type": "Note",
"content": "This is a note",
"published": "2015-02-10T15:04:55Z",
"to": ["https://example.org/~john/"],
"cc": ["https://example.com/~erik/followers",
"https://www.w3.org/ns/activitystreams#Public"]
}
{
"@context": "https://www.w3.org/ns/activitystreams",
"type": "Create",
"id": "https://example.net/~mallory/87374"
"actor": "https://example.net/~mallory",
"object": {
"id": "https://example.com/~mallory/note/72",
"type": "Note",
"attributedTo": "https://example.net/~mallory",
"content": "This is a note",
"published": "2015-02-10T15:04:55Z",
"to": ["https://example.org/~john/"],
"cc": ["https://example.com/~erik/followers",
"https://www.w3.org/ns/activitystreams#Public"]
},
"published": "2015-02-10T15:04:55Z",
"to": ["https://example.org/~john/"],
"cc": ["https://example.com/~erik/followers",
"https://www.w3.org/ns/activitystreams#Public"]
}
The Update
activity is used when updating an already existing object. The side effect of this is that the object
MUST
be modified to reflect the new structure as defined in the update
activity, assuming the actor has permission to update this object.
For client to server interactions, updates are partial; rather
than updating the document all at once, any key value pair supplied is
used to replace the existing value with the new value. This only applies
to the top-level fields of the updated object. A special exception is
for when the value is the json
null
type; this means that this field should be removed from the server's representation of the object.
Note that this behavior is for client to server interaction where the client is posting to the server only. Server to server interaction and updates from the server to the client should contain the entire new representation of the object, after the partial update application has been applied. See the description of the Update activity for server to server interactions for more details.
The Delete
activity is used to delete an already existing object. The side effect of this is that the server MAY replace the
object
with a Tombstone
of the object
that will be displayed in activities which reference the deleted object.
If the deleted object is requested the server SHOULD respond with either the HTTP 410 Gone status code if a Tombstone
object is presented as the response body, otherwise respond with a HTTP 404 Not Found.
A deleted object:
{
"@context": "https://www.w3.org/ns/activitystreams",
"id": "https://example.com/~alice/note/72",
"type": "Tombstone",
"published": "2015-02-10T15:04:55Z",
"updated": "2015-02-10T15:04:55Z",
"deleted": "2015-02-10T15:04:55Z",
}
The Follow
activity is used to subscribe to the activities of another user.
The side effect of receiving this in an outbox is that the server SHOULD add the object
to the
actor
's following
Collection.
Upon receipt of an Add
activity into the
outbox, the server SHOULD add the object
to the collection specified in the
target
property, unless:
target
is not owned by the receiving server, and thus they are not authorized to update it.
object
is not allowed to be added to the
target
collection for some other reason, at the receiving server's discretion.
Upon receipt of a Remove
activity into the
outbox, the server SHOULD remove the object
from the collection specified in the
target
property, unless:
target
is not owned by the receiving server, and thus they are not authorized to update it.
object
is not allowed to be removed from the
target
collection for some other reason, at the receiving server's discretion.
The Like
activity indicates the actor
likes the object
.
The side effect of receiving this in an outbox is that the server SHOULD add the object
to the
actor
's likes
Collection.
The Block
activity is used to indicate that the posting actor does not want another actor (defined in the object
property) to be able to interact with objects posted by the actor posting the Block
activity. The server SHOULD prevent the blocked user from interacting with any object posted by the actor.
Servers SHOULD NOT deliver Block Activities to their object
.
The Undo
activity is used to undo a previous activity. See the Activity Vocabulary documentation on
Inverse Activities and "Undo". For example, Undo
may be used to undo a previous
Like
or Follow
. The undo activity and the activity being undone MUST both have the same author. Side effects should be undone, to the extent possible. For example, if undoing a Like
, any counter that had been incremented previously should be decremented appropriately.
There are some exceptions where there is an existing and explicit "inverse activity" which should be used instead.
Create
based activities should instead use
Delete
, and Add
activities should use
Remove
.
Federated servers MUST perform delivery on all Activities posted to the outbox according to outbox delivery.
Servers communicate with other servers and propagate information across the social graph by posting activities to actors'
inbox endpoints. An Activity sent over the network SHOULD have an id
, unless it is intended to be transient (in which case it MAY omit the
id
).
In order to propagate updates throughout the social graph, Activities are sent to the appropriate recipients. First, these recipients are determined through following the appropriate links between objects until you reach an agent, and then the Activity is inserted into the agent's inbox (delivery). This allows recipient servers to:
Delivery is usually triggered by, for example:
Servers performing delivery to the inbox
or
publicInbox
properties of actors on other servers MUST provide the object
property in the activity:
Create
, Update
, Delete
,
Follow
, Add
, Remove
,
Like
, Block
, Undo
. Additionally, servers performing server to server delivery of the following activities MUST also provide the target
property: Add
, Remove
.
An activity is delivered to its targets (which are
actors) by first looking up the targets'
inboxes and then posting the activity to those inboxes. Targets for
delivery are determined by checking the
ActivityStreams audience targeting; namely, the to
, bto
, cc
,
bcc
, and audience
fields of the activity.
The inbox is determined by first
retrieving the target actor's JSON-LD representation and then looking up the inbox
property. If a recipient is a Collection
or OrderedCollection
, then the server MUST dereference the collection (with the user's credentials) and discover inboxes for each item in the collection. Servers MUST limit the number of layers of indirections through collections which will be performed, which MAY be one.
Servers MUST de-duplicate the final recipient list. Servers MUST also exclude actors from the list which are the same as the actor
of the Activity being notified about. That is, users shouldn't have their own activities delivered to themselves.
What to do when there are no recipients specified is not defined, however it's recommended that if no recipients are specified the object remains completely private and access controls restrict the access to object. If the object is just sent to the "public" collection the object is not delivered to any users but is publicly viewable in the actor's outbox.
An HTTP POST request (with authorization of the submitting user) is then made to to the inbox, with the Activity as the body of the request. This Activity is added by the receiver as an item
in the
inbox OrderedCollection.
For federated servers performing delivery to a 3rd party server, delivery SHOULD be performed asynchronously, and SHOULD additionally retry delivery to recipients if it fails due to network error. Servers SHOULD also take care not to overload servers with submissions, for example by using an exponential backoff strategy.
While it is not required reading to understand this
specification, it is worth noting that ActivityPub's targeting and
delivery mechanism overlaps with the
Linked Data Notifications specification, and the two specifications may interoperably combined. In particular, the inbox
property is the same between ActivityPub and Linked Data Notifications,
and the targeting and delivery systems described in this document are
supported by Linked Data Notifications. In addition to JSON-LD compacted
ActivityStreams documents, Linked Data Notifications also supports a
number of RDF serializations which are not required for ActivityPub
implementations. However, ActivityPub implementations which wish to be
more broadly compatible with Linked Data Notifications implementations
may wish to support other RDF representations.
When objects are received in the outbox, the server MUST target and deliver to:
to
, bto
, cc
,
bcc
or audience
fields if their values are individuals or Collections owned by the actor.
These fields will have been populated appropriately by the client which posted the Activity to the outbox.
When Activities are received in the inbox, the server needs to forward these to recipients that the origin was unable to deliver them to. To do this, the server MUST target and
deliver to the values of to
, bto
, cc
,
bcc
, and/or audience
if and only if all of the following are true:
to
, bto
, cc
,
bcc
, and/or audience
contain a Collection owned by the server.
inReplyTo
, object
,
target
and/or tag
are objects owned by the server. The server SHOULD recurse through these values to look for linked objects owned by the server, and SHOULD
set a maximum limit for recursion (ie. the point at which the thread is
so deep the recipients followers may not mind if they are no longer
getting updates that don't directly involve the recipient). The server MUST only target the values of to
, bto
,
cc
, bcc
, and/or audience
on the original object being forwarded, and not pick up any new
addressees whilst recursing through the linked objects (in case these
addressees were purposefully amended by or via the client).
The server MAY filter its delivery targets according to implementation-specific rules (for example, spam filtering).
For servers hosting many actors, delivery to all participants can result in an overwhelming number of messages sent. Some servers would also like to display a list of all messages posted publicly to the "known network". Thus ActivityPub provides an optional mechanism for serving these two use cases.
When an origin server is sending an activity to a remote server which is addressed with the special
Public recipient, the origin server MAY reduce the number of actors delivered to by identifying all actors which would be recipients who share a
publicInbox who would otherwise be individual recipients and instead deliver to only publicInbox
objects. (An origin server MAY alternately decide to publish all posts to all publicInbox
endpoints known). The server with the receiving publicInbox
should use its own following lists
to determine which actors should have the post delivered to their
inbox. Thus in this scenario, the remote/receiving server participates
in determining targeting and performing delivery to specific inboxes.
Origin servers sending publicly addressed activities to
publicInbox
endpoints MUST still deliver to actors and collections otherwise addressed (through to
,
bto
, cc
, bcc
, and
audience
) which do not have a publicInbox
and would not otherwise receive the activity through the
publicInbox
mechanism.
Receiving a Create
activity in an inbox
has surprisingly few side effects; the activity should appear in the actor's inbox
and it is likely that the server will want to locally store a
representation of this activity and its accompanying object. However,
this mostly happens in general with processing activities delivered to
an inbox
anyway.
For server to server interactions, an Update
activity means that the receiving server SHOULD update its copy of the
object
of the same id
to the copy supplied in the Update
activity. Unlike the
client to server handling of the Update activity, this is not a partial update but a complete replacement of the object.
The receiving server MUST take care to be sure that the
Update
is authorized to modify its object
. At minimum, this may be done by ensuring that the Update
and its object
are of same origin.
The side effect of receiving this is that (assuming the
object
is owned by the sending actor / server) the server receiving the delete activity SHOULD remove its representation of the object
with the same id
, and MAY replace that representation with a Tombstone
object.
(Note that after an activity has been transmitted from an origin server to a remote server, there is nothing in the ActivityPub protocol that can enforce remote deletion of an object's representation).
The side effect of receving this in an inbox is that the server SHOULD add the actor
to the object
user's Followers Collection.
Upon receipt of an Add
activity into the
inbox, the server SHOULD add the object
to the collection specified in the
target
property, unless:
target
is not owned by the receiving server, and thus they can't update it.
object
is not allowed to be added to the
target
collection for some other reason, at the receiver's discretion.
Upon receipt of a Remove
activity into the
inbox, the server SHOULD remove the object
from the collection specified in the
target
property, unless:
target
is not owned by the receiving server, and thus they can't update it.
object
is not allowed to be removed to the
target
collection for some other reason, at the receiver's discretion.
The side effect of receving this in an inbox is that the server SHOULD increment the object
's count of likes, or perform other appropriate indication of the like being performed, such as listing the liking actor
amongst actors who have liked this object
.
The Undo
activity is used to undo the side effects of previous activities. See the ActivityStreams documentation on
Inverse Activities and "Undo". The scope and restrictions of the Undo
activity are the same as for
the Undo activity in the context of client to server
interactions, but applied to a federated context.
This section is non-normative.
Building an international base of users is important in a federated network.
ActivityStreams provides tooling for internationalization of content, which should be used whenever possible. However, it can be difficult for implementations to determine which
@language
property
to provide for user-submitted content. The
W3C Internationalization group provides some
guidance on language detection.
This section is non-normative.
Servers should be careful to verify that new content is really posted by the author that claims to be posting it, and that the author has permission to update the resources it claims to. Discussion of how to accomplish this is laid out in the 3. Objects and 9. Authentication and Authorization sections.
It is often convenient while developing to test against a process running on localhost. However, permitting requests to localhost in a production client or server instance can be dangerous. Making requests to URIs on localhost which do not require authorization may unintentionally access or modify resources assumed to be protected to be usable by localhost-only.
If your ActivityPub server or client does permit making requests to localhost URIs for development purposes, consider making it a configuration option which defaults to off.
There are many types of URIs aside from just http
and
https
. Some libraries which handle fetching
requests at various URI schemes may try to be smart and reference
schemes which may be undesirable, such as file
. Client and
server authors should carefully check how their libraries handle
requests, and potentially whitelist only certain safe URI types, such as
http
and https
.
Spam is a problem in any network, perhaps especially so in federated networks. While no specific mechanism for combating spam is provided in ActivityPub, it is recommended that servers filter incoming content both by local untrusted users and any remote users through some sort of spam filter.
Any activity field being rendered for browsers (or other rich text enabled applications) should take care to sanitize fields containing markup to prevent cross site scripting attacks.
This section is non-normative.
This specification comes from years of hard work and experience by a number of communities exploring the space of federation on the web. In particular, much of this specification is informed by OStatus and the Pump API, as pioneered by StatusNet (now GNU Social) and Pump.io. Both of those initiatives were the product of many developers' hard work, but more than anyone, Evan Prodromou has been a constant leader in this space, and it is unlikely that ActivityPub would exist in something resembling its current state without his hard work.
Owen Shepherd built the initial version of this specification, borrowed from the ideas in the Pump API document, mostly as a complete rewrite of text, but sharing most of the primary ideas while switching from ActivityStreams 1 to ActivityStreams 2. Jessica Tallon and Christopher Allan Webber took over as editors when the standard moved to the W3C Social Working Group and did the majority of transition from Owen's document to its current state as ActivityPub.
ActivityPub has been shaped by the careful input of many members in the W3C Social Working Group. ActivityPub especially owes a great debt to Amy Guy, who has done more than anyone to map the ideas across the different Social Working Group documents through her work on [Social-Web-Protocols]. Amy also laid out the foundations for a significant refactoring of the ActivityPub spec while sprinting for four days with Christopher Allan Webber. These revisions lead to cleaner separation between the client to server and server components, along with clarity about ActivityPub's relationship to [LDN], among many other improvements. Special thanks also goes to Benjamin Goering for putting together the implementation report template.
This section is non-normative.
These questions provide an overview of security and privacy considerations for this specification as guided by [ security-privacy-questionnaire].
This section is non-normative.
Content-Type
for posting to outbox
.@language
to many examples.bto
and audience
to everything that isn't referencing it currently and Reference the ActivityStreams audience targeting directly.
object
and target
are required.
id
parameter.
Create
and Delete
activities to the server to server side effects section and put all listed activities in the same order as in client to server.
@context
on one example where @language
moving around was reported to be confusing/distracting.
@language
to first example.OrderedCollection
.
application/ld+json; profile="https://www.w3.org/ns/activitystreams"
the default media type. Servers MAY do content negotiation but MUST respond with AS2 to the right content type.
1.1 Social Web Working Group
ActivityPub is one of several related specifications being produced by the Social Web Working Group. Implementers interested in alternative approaches and complementary protocols should review [Micropub] and the overview document [ Social-Web-Protocols].