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 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 Recommendationan Editor's Draft. This Comments regarding this document is intended to become a W3C Recommendation. Comments regarding this document are welcome. Please send them to public-socialweb@w3.org (subscribe, archives).
Please see the Working Group's implementation report.
Publication as an Editor's Draft does not imply endorsement by the W3C publishes a Candidate Recommendation to indicate that the Membership. This is a draft document is believed to be stable and to encourage implementation by the developer communityand may be updated, replaced or obsoleted by other documents at any time. This Candidate Recommendation is expected to advance to Proposed Recommendation no earlierIt is inappropriate to cite this document as other than 05 October 2017work in progress.
Please see the Working Group's implementation report. Publication as a Candidate Recommendation does not imply endorsement by the This document was produced by a group operating under the W3C MembershipPatent Policy. 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.
ActivityPub provides two layers:
ActivityPub implementations can implement just one of these things or both of them. However, once you've implemented one, it isn't too many steps to implement the other, and there are a lot of benefits to both (making your website part of the decentralized social web, and being able to use clients and client libraries that work across a wide variety of social websites).
In ActivityPub, every accounts on a server (including those of real-world users, bots, and other automated processes) are represented by "actoractors (users are represented as "actors" here)". Every Actor has:
inbox
: How they get messages from the worldoutbox
: How they send messages to others
These are endpoints, or really, just URLs which are listed in the ActivityPub actor's ActivityStreams description. (More on ActivityStreams later).)
Here's an example of the record of our friend Alyssa P. Hacker:
{"@context": "https://www.w3.org/ns/activitystreams",
"type": "Person",
"id": "https://social.example/alyssa/",
"name": "Alyssa P. Hacker",
"preferredUsername": "alyssa",
"summary": "Lisp enthusiast hailing from MIT",
"inbox": "https://social.example/alyssa/inbox/",
"outbox": "https://social.example/alyssa/outbox/",
"followers": "https://social.example/alyssa/followers/",
"following": "https://social.example/alyssa/following/",
"liked": "https://social.example/alyssa/liked/"}
ActivityPub uses [ActivityStreams] for its vocabulary. This is pretty great because ActivityStreams includes all the common terms you need to represent all the activities and content flowing around a social network. It's likely that ActivityStreams already includes all the vocabulary you need, but even if it doesn't, ActivityStreams can be extended via [JSON-LD]. If you know what JSON-LD is, you can take advantage of the cool linked data approaches provided by JSON-LD. If you don't, don't worry, JSON-LD documents and ActivityStreams can be understood as plain old simple JSON. (If you're going to add extensions, that's the point at which JSON-LD really helps you out).
So, okay. Alyssa wants to talk to her friends, and her friends want to talk to her! Luckily these "inbox" and "outbox" things can help us out.) So, okay. Alyssa wants to talk to her friends, and her friends want to talk to her! Luckily these "inbox" and "outbox" things can help us out. They both behave differently for GET and POST. Let's see how that works:
Hey nice, so just as a recap:
Of course, if that last one (GET'ing from someone's outbox) was the only way to see what people have sent, this wouldn't be a very efficient federation protocol! Indeed, federation happens usually by servers posting messages sent by actors to actors on other servers' inboxes.
Let's see an example! Let's say Alyssa wants to catch up with her friend, Ben Bitdiddle. She lent him a book recently and she wants to make sure he returns it to her. Here's the message she composes, as an ActivityStreams object:
{"@context": "https://www.w3.org/ns/activitystreams",
"type": "Note",
"to": ["https://chatty.example/ben/"],
"attributedTo": "https://social.example/alyssa/",
"content": "Say, did you finish reading that book I lent you?"}
This is a note addressed to Ben. She POSTs it to her outbox.
Since this is a non-activity object, the server recognizes that this is an object being newly created, and does the courtesy of wrapping it in a Create activity. (Activities sent around in ActivityPub generally follow the pattern of some activity by some actor being taken on some object. In this case the activity is a Create of a Note object, posted by a Person).)
{"@context": "https://www.w3.org/ns/activitystreams",
"type": "Create",
"id": "https://social.example/alyssa/posts/a29a6843-9feb-4c74-a7f7-081b9c9201d3",
"to": ["https://chatty.example/ben/"],
"actor": "https://social.example/alyssa/",
"object": {"type": "Note",
"id": "https://social.example/alyssa/posts/49e2d03d-b53a-4c4c-a95c-94a6abf45a19",
"attributedTo": "https://social.example/alyssa/",
"to": ["https://chatty.example/ben/"],
"content": "Say, did you finish reading that book I lent you?"}}
Alyssa's server looks up Ben's ActivityStreams actor object, finds his inbox endpoint, and POST'sPOSTs her object to his inbox.
Technically these are two separate steps... one is client to server communication, and one is server to server communication (federation). But, since we're using them both in this example, we can abstractly think of this as being a streamlined submission from outbox to inbox:
Cool! A while later, Alyssa checks what new messages she's gotten. Her phone polls her inbox via GET, and amongst a bunch of cat videos posted by friends and photos of her nephew posted by her sister, she sees the following:
{"@context": "https://www.w3.org/ns/activitystreams", "type": "Create", "id": "https://chatty.example/ben/p/51086", "to": ["https://social.example/alyssa/"], "actor": "https://chatty.example/ben/", "object": {"type": "Note", "id": "https://chatty.example/ben/p/51085", "attributedTo": "https://chatty.example/ben/", "to": ["https://social.example/alyssa/"], "inReplyTo": "https://social.example/alyssa/posts/49e2d03d-b53a-4c4c-a95c-94a6abf45a19", "content": "<p>Argh, yeah, sorry, I'll get it back to you tomorrow.</p> <p>I was reviewing the section on register machines, since it's been a while since I wrote one.</p>"}}
Alyssa is relieved, and likes Ben's post:
{"@context": "https://www.w3.org/ns/activitystreams",
"type": "Like",
"id": "https://social.example/alyssa/posts/5312e10e-5110-42e5-a09b-934882b3ecec",
"to": ["https://chatty.example/ben/"],
"actor": "https://social.example/alyssa/",
"object": "https://chatty.example/ben/p/51086"}
She POSTs this message to her outbox. (Since it's an activity, her server knows it doesn't need to wrap it in a Create object).)
Feeling happy about things, she decides to post a public message to her followers. Soon the following message is blasted to all the members of her followers collection, and since it has the special Public group addressed, is generally readable by anyone.
{"@context": "https://www.w3.org/ns/activitystreams",
"type": "Create",
"id": "https://social.example/alyssa/posts/9282e9cc-14d0-42b3-a758-d6aeca6c876b",
"to": ["https://social.example/alyssa/followers/",
"https://www.w3.org/ns/activitystreams#Public"],
"actor": "https://social.example/alyssa/",
"object": {"type": "Note",
"id": "https://social.example/alyssa/posts/d18c55d4-8a63-4181-9745-4e6cf7938fa1",
"attributedTo": "https://social.example/alyssa/",
"to": ["https://social.example/alyssa/followers/",
"https://www.w3.org/ns/activitystreams#Public"],
"content": "Lending books to friends is nice. Getting them back is even nicer! :)"}}
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:
The ActivityPub specification is designed so that once either of these protocols are implemented, supporting the other is of very little additional effort. However, servers may still implement one without the other. 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.
sharedInbox
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 (A server should do something at least as robust as checking that the object appears as received at its origin, but mechanisms such as checking signatures would be better if available). No 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 mechanism for verification. No particular mechanism for verification is authoritively is authoritatively specified by this document, thoughbut please see Security Considerations for some possible directions are discussed in 8suggestions and good practices. 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",
"attributedTo": "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 posted to the outbox with no specified id
SHOULD
allocate an object ID in the user'sactor'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 8B.1 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"}],
"type": "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.
ActivityPub actors are generally one of the
ActivityStreams Actor Types,
but they don't have to be. For example, a
Profile object
might be used as an actor, or a type from an ActivityStreams extension.
Actors 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 MUST have, in addition to the properties mandated by 3.1 Object Identifiers, the following properties:
OrderedCollection
comprised of all the messages received by the actor; see
5.2 Inbox.
OrderedCollection
comprised of all the messages produced by the actor; see
5.1 Outbox.
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",
"liked": "https://kenzoishii.example.com/liked.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.
sharedInbox
endpoints SHOULD also be publicly
readable OrderedCollection
objects containing
objects addressed to the Public
special collection.
Reading from the sharedInbox
endpoint MUST NOT present
objects which are not addressed to the Public
endpoint.
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. url A link to the actor's "profile web page", if not equal to the value of id. name The preferred "nickname" or "display name" of the actor. summary A quick summary or bio by the user about themselves. icon A link to an image or an Image object which represents the user's profile picture (this may be a thumbnail). Note Properties containing natural language values, such as name, preferredUsername, or summary, make use of natural language support defined in ActivityStreams. 5. Collections [ActivityStreams] defines the collection concept;property may be used on ActivityPub defines several collections with special behaviorActors. Note that Some ActivityStreams properties are particularly worth highlighting to demonstrate how they are used in ActivityPub makes use of ActivityStreams paging to traverse large sets of objectsimplementations.
Note that some of these collections are specified to be of typeOrderedCollectionid
specifically, while others are permitted to be either a
Collection or an
OrderedCollection. An
OrderedCollection
MUST be presented consistently in reverse chronological order
Properties containing natural language values,
such as name
, preferredUsername
, or
summary
, make use of
natural language support defined in ActivityStreams. 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.
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. 5.2 Inbox 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 inboxes of actors on federated servers accepts HTTP POST requests, with behaviour described in Delivery. Non-federated servers SHOULD return a 405 Method Not Allowed upon receipt of a POST request. 5.3 Followers Collection 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. Note: Default for notification targeting 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. 5.4 Following Collection 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. 5.5 Liked Collection Every actor MAY have a liked collection. This is a list of every object from all of the actor's Like activities, added as a side effect. The liked 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. 5.6 Public Addressing In addition to [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.
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 inboxes of actors on federated servers accepts HTTP POST requests, with behaviour described in Delivery. Non-federated servers SHOULD return a 405 Method Not Allowed upon receipt of a POST request.
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 liked
collection.
This is a list of every object from all of the actor's Like
activities, added as a side effect.
The liked
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.
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.
However, actors MAY have a
sharedInbox
endpoint which is available for efficient shared delivery of public
posts (as well as posts to followers-only); see
7.1.3 Shared Inbox Delivery.
Compacting an ActivityStreams object using the ActivityStreams
JSON-LD context might result in
https://www.w3.org/ns/activitystreams#Public
being represented as simply Public
or as:Public
which are valid representations of the Public collection.
Implementations which treat ActivityStreams objects as simply
JSON rather than converting an incoming activity over to a
local context using JSON-LD tooling should be aware of this
and should be prepared to accept all three representations.
Every object MAY have a likes
collection.
This is a list of all Like
activities with this object
as the object
property, 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.
Care should be taken to not confuse the the
likes
collection with the similarly named but different
liked
collection.
In sum:
Like
activities performed
by the actor,
added to the collection as a
side effect of delivery to the outbox.
Like
activities referencing
this object,
added to the collection as a
side effect of delivery to the inbox.
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.
To do this, 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 MUST then add this new Activity to the outbox collection. Depending on the type of Activity, servers may then be required to carry out further side effects. (However, there is no guarantee that time the Activity may appear in the outbox. The Activity might appear after a delay or disappear at any period). These are described per individual Activity below.
Attempts to submit objects to servers not implementing client to server
support SHOULD result in a 405 Method Not Allowed
response.
HTTP caching mechanisms [RFC7234] SHOULD be respected when appropriate, both in clients receiving responses from servers as well as servers sending responses to clients.
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.
(Note that this does not suggest that the client should "unpack"
collections of actors being addressed as individual recipients).)
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/",
"summary": "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.
If an Activity is submitted with a value in the
Clients submitting the following activities to an idoutbox
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.
Example 14: Outbox response to submitted Activity
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 MUST then add this new Activity to the
outbox collection. Depending on the type of Activity, servers may then be required to carry out further side effects. (However, there is no guarantee that time the Activity may appear in the outbox. The Activity might
appear after a delay or disappear at any period.) These are described per individual Activity below.
Attempts to submit objects to servers not implementing client to server support SHOULD result in a 405 Method Not Allowed response.
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
.
HTTP caching mechanisms [RFC7234]
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 respected when appropriate, both in clients receiving responses from servers as well as servers sending
responses to clients.
6.1 Create Activity
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
when and only if an Accept
activity is subsequently
received with this Follow
activity as its object.
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 liked
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 actor. Side effects should be undone, to the extent possible. For example, if undoing
a
Like
, Follow
, or Block
.
The undo activity and the activity being undone MUST both have the
same actor.
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
.
ActivityPub supports uploading document types to be referenced in activites, such as images, video or other binary data, and Federated 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. (Unlike most client to server interactions, using this endpoint does not involve submitting to the perform delivery on all Activities posted to the outbox according to outbox delivery.) 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: file The media file file being uploaded. object A shell of an ActivityStreams object, which will be finalized by the server. 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 new or 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 viaThis section is non-normative.
ActivityPub uses authentication for two purposes; first Servers MAY support uploading document types to be referenced in activites, to authenticate clients to serverssuch as images, and secondly in federated implementations to authenticate servers to eachvideo or other. Unfortunately at the time of standardization binary data, there are no strongly agreed upon mechanisms for authentication. Some possible directions for authentication are laidbut the precise mechanism is out as follows. 8.1 OAuth 2.0 and JSON Web Signatures ActivityPub implementations may use OAuth 2.0 with JSON Web Signatures [RFC7515] for authentication and authorization. This has the advantage of wide deployment of OAuth 2.0 technologies. However, OAuth 2.0 technologies are frequently incompatible, and the agreed upon mechanisms for deploying via OAuth 2.0 are still in flux, so it is not feasible to recommend a general pattern for OAuth 2.0 based deployments at this time. 8.1.1 Client to Origin Server Authentication For client to server interactions where the client is interacting directly to the actor's server, clients may use OAuth 2.0 bearer tokens to authenticate. Bearer tokens may be acquired out of band. They may also be acquired using OAuth 2.0 authorization. To discover the correct endpoint for authorization, clients should use [OAuth-Server-Metadata] on the host part from the actor's ID URI. Client IDs may be acquired out of band for some servers. They may also be acquired using [RFC7591]. 8.1.2 Client to Foreign Server Authentication For client to server interactions where the client is interacting with servers beyond the user's origin server, clients and servers may support use of OAuth 2.0 with JSON Web Signatures. 8.1.3 Servers Acting on Behalf of Users Servers performing operations on behalf of a user (e.g. delivery to a recipient) may use OAuth 2.0 with JSON Web Signatures to authenticate with a 3rd party server. 8.2 Linked Data Signatures and HTTP Signatures ActivityPub implementations may use Linked Data Signatures and signed HTTP messages for authentication and authorization. (Linked Data Signatures are best used when authentication is meant to be "long lived" and attached to an object, such as verifying that an object truly was posted by this actor, and signed HTTP messages should be used when authentication or authorization is ephemeral.) This has the advantage of clean integration with existing JSON-LD based technologies already used byof scope for this version of ActivityPub. However, at the time of specification, Linked Data Signatures and HTTP signatures are very young, particularly in adoption. When Linked Data Signatures is used in combination with The Social Web Community Group is refining the protocol in the ActivityPub, the server should assign an actor a public and private key pair, and link the public key to the actor's profile object, which may later be used with the Linked Data Signatures verification algorithm to validate the authenticity of messages passed along the network. 8.2.1 Client to Origin Server Authentication For client to server interactions where the client is interacting directly with the actor's server, a client may use HTTP signatures by registering their client's public key with the actor on the server and subsequently using this key to sign any HTTP requests made. 8.2.2 Client to Foreign Server Authentication For client to server interactions where the client is interacting with servers beyond the user's origin server, clients may use a combination of HTTP signatures and Linked Data Signatures. In this scenario, a client would have their client key authorized for a limited window of time by the key listed on their actor profile. The client key would then be used to sign HTTP requests made to the foreign server while also providing the signature of the client public key, signed by and linked to the key on their actor profile. 8.2.3 Servers Acting on Behalf of Users Servers performing operations on behalf of a user (e.g. delivery to a recipient) may use Linked Data Signatures to authenticate with a 3rd party server. This may be achieved by attaching the linked data signature to the activity posted to the remote inbox, signed by the actor's public key. Servers receiving activities verified via Linked Data Signatures SHOULD NOT process an object with a nonce they have seen before, so as to prevent replay attacks. A. Internationalization 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 Media Upload report.
This section is non-normative
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
B.1 Verification and authorization
Servers should be careful to verify that new content is really posted by the actor that claims to be posting it have an id
, and that the actor has permission to update the resources it claims to. Discussion of how to accomplish this is laid out in the
3. Objects and 8. Authentication and Authorization sections.
B.2 Accessing localhost URIs
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
unless it is intended to be transient (in 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.
B.3 URI Schemes
There are many types of URIs aside from just case it MAY omit the
httpid
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.
B.4 Recursive Objects
Servers should set a limit on how deep to recurse while resolving objects, or otherwise specially handle ActivityStreams objects with recursive references. Failure to properly do so may result in denial-of-service security vulnerabilities.
B.5 Spam
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.
B.6 Federation denial-of-service
Servers should implement protections against denial-of-service attacks from other, federated servers. This can be done using, for example, some kind of ratelimiting mechanism. Servers should be especially careful to implement this protection around activities
that involve side effects.
B.7 Client-to-server ratelimiting
Servers should ratelimit API client submissions. This serves two purposes:
It prevents malicious clients from conducting denial-of-service attacks on the server.
It ensures that the server will not distribute so many activities that it triggers another server's denial-of-service
protections.
B.8 Sanitizing Content
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.
C. Acknowledgements
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.
O 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 O Shepherd's document to its current
state as ActivityPub. Much of the document was rewritten and reorganized under the long feedback process of the Social Working Group.
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. We also thank mray for producing the spectacular tutorial illustrations (which are licensed under the same license as the rest of this document).
Many people also helped ActivityPub along through careful review
POST
requests (eg. In particular, thanks to: Aaron Parecki, AJ Jordan, Benjamin Goering, Caleb Langeslag, Elsa Balderrama, elf Pavlik, Eugen Rochko, Erik Wilde, Jason Robinson, Manu Sporny, Michael Vogel,
Mike McGarvin, nightpool, Puck Meerburg, Sandro Hawke, Sarven Capadisli, and Tantek Çelik.
This document is dedicated to all citizens of planet Earth. You deserve freedom of communication; we hope we have contributed in some part, however small, towards that goal and right.
D. Security and Privacy Review
This section is non-normative.
These questions provide an overview of security and privacy considerations for this specification as guided by [
security-privacy-questionnaire].
Does this specification deal with personally-identifiable
information?
ActivityPub's actors may contain information about the associated user. At minimum, the actor profile contains an identifier which also provides a mechanism for contacting the actor, through the exposed actor'sto the inbox. Aside from this, ActivityPub does
not mandate any personally identifiable information to operate, though depending on the implementation, any number of details may be exposed on the actor's profile, particularly user names and real names. Additionally, a notification payload
could include personally identifiable information, depending on the implementation and use, but it is again not required for the core functionality to operate.
Does this specification deal with high-value data?
Same implications as personally-identifiable information in notification payload (as mentioned above). The application supplies no normative mechanism for authentication from clients to servers, but depending on what mechanism is used, OAuth tokens may
be exposed, particularly if HTTP is used without TLS/SSL support. Similarly, no normative mechanism for authentication between servers is exposed, though without TLS/SSL support, OAuth tokens could be exposed here as well.
Does this specification introduce new state for an origin that
persists across browsing sessions?
No. Clients may choose to cache server state information supplied through the application, though this is not mandated or specified.
Does this specification expose persistent, cross-origin state to the
web?
Yes. Clients, if appropriately authorized, may read some inbox / outbox information from other actors on the web. Additionally, servers both read and submit activities to other servers on the network.
Does this specification expose any other data to an origin that it
doesn’t currently have access to?
No. (Or at least, not as far as the person filling out this section can tell.)
Does this specification enable new script execution/loading
mechanisms?
No.
Does this specification allow an origin access to a user’s location?
No.
Does this specification allow an origin access to sensors on a
user’s device?
No.
Does this specification allow an origin access to aspects of a
user’s local computing environment?
No.
Does this specification allow an origin access to other devices?
No.
Does this specification allow an origin some measure of control over
a user agent’s native UI?
No.
Does this specification expose temporary identifiers to the web?
Not directly. However, mechanisms to authenticate an actor or authorize behavior might.
Does this specification distinguish between behavior in first-party
and third-party contexts?
No.
How should this specification work in the context of a user agent’s
"incognito" mode?
Being in "incognito" mode means that authentication information a browser or agent might keep between sessions would not be preserved, thus limiting access to any content requiring explicit authorization.
Does this specification persist data to a user’s local device?
This depends on implementation. Clients might choose to cache activities they have previously seen, but this is not a normative requirement. Depending on the authentication method used, authentication tokens or keys may be persisted.
Does this specification have a "Security Considerations" and
"Privacy Considerations" section?
You're looking at it!
Does this specification allow downgrading default security
characteristics?
No.
E. Change Log
This section is non-normative.
E.1 Changes from 22 August 2017 to 07 September 2017
[Normative] Add explicit Accept / Reject of Follow activities. (Issue #244)
Update test suite URL
[Normative] Switch publicInbox to sharedInbox (Issue #242)
clarification on scope of endpoints for server/domain endpoints specifically
E.2 Changes from 9 May 2017 to 22 August 2017
Fix inReplyTo being on Create instead of Note.
Various typo fixes.
Give the LDN relationship note a decent URL hash.
Note recursive objects in Security Considerations and give suggestion on how to handle.
Fix broken OAuth Discovery link.
Fixed some examples (rename likes to liked in actors example, change object property to type).
Fix various examples of "author" mistakenly used where "actor" should be.
Add section on federation denial-of-service.
Add client-to-server ratelimiting section.
Updated acknowledgements.
E.3 Changes from 13 April 2017 to 9 May 2017
[Normative] Make adding to outbox collection on client to server section a MUST.
Various typo / grammar fixes.
Call attention to the Public Inbox Delivery section in Public Addressing.
"Spoofing prevention" used author attribute instead of attributedTo, fixed.
Clarify wording around adding id in client to server communication.
When listing inbox and outbox properties, explicitly call them OrderedCollections (as they are represented later).
Use "summary" on Liking the minimal update client example instead of "name".
Add another example of delivery for user-curated collections.
Clarify behavior of delivery to the same origin.
[Normative] Specify delivery behavior on non-federated servers.
[Possibly normative] Add notes about HTTP caching.
Refer to actors as "actors" instead of as "agents" in Server to Server Interactions section.
Fix Activity Vocabulary not being in References.
[Normative] Include the option for actors to be a Profile object and Clarify language surrounding what can be an actor.
[Normative] Remove reference to Actors being subclass of the Actor type.
Add note about flow for acquiring bearer tokens and client IDs.
Rename OAuth endpoints to match RFC6749.
[Normative] Rename present "likes" collection for actors to "liked".
Reordered collections section, putting outbox and inbox collections first.
[Normative] Add "likes" section and reference it in Like inbox side effects section.
[Normative] Add the shares property and Announce activity and describe federated behavior.
[Normative] Client to server no longer required for server to server in conformance classes.
Reorder outbox submission bit in C2S Interactions.
Replace present "Overview" with a tutorial.
[Possibly normative, but probably not] Clarify that clients traversing build-up of addressing doesn't mean unpack collections.
Add media uploading example.
[Normative] Mention returning 405 Method Not Allowed when submitting objects to non-c2s outboxes.
Move Uploading Media section directly into the Client to Server section.
Clarify submitting to uploadMedia endpoint does not involve outbox submission.
E.4 Changes from 17 November 2016 to 13 April 2017
Various wording clarifications and grammatical fixes.
Added some informative references.
Update security and privacy questionnaire answers for incognito mode and "local device" to be closer to implementation.
Correct typo in be made with a Content-Type for posting to outbox.
Move duplicate ActivityStreams properties from main Actors section into subsection that's marked clearly as non-normative.
E.5 Changes from 04 October 2016 to 17 November 2016
Various typo / grammar fixes.
Added @language to many examples.
Linked to the i18n LanguageDetection wiki page.
Switched to using a Japanese example for Person example.
Note that ActivityPub shares the same URI / IRI conventions as in ActivityStreams.
Added notes about text direction for natural language values.
More clearly reference ActivityStreams targeting in the overview.
Clarify that followers/following are links/uris, not embedded.
Marked preferredUsername at-risk.
Clarify that likes/following/followers collections MAY be filtered.
Switch over to activitystreams namespace.
Update the special Public collection to point to use a fragment identifier.
Switch federation like side effect from MAY->SHOULD and widen effect possibilities.
Make ActivityPub document readable without LDN, but clearly describe overlap.
Beter text around displaying 404 or 403 if an object is private.
Add Undo activity for federated contexts.
Add public content delivery section, marked at risk.
Add non-normative recommendation that implementations seeking to gain broader interop with LDN might want to support other RDF types.
"Object without Create" section marked at-risk.
Renamed "Binary Data" to "Uploading Media".
Significant refactoring to media endpoint's mechanism. Now works on a single request.
Add text about adding an id to both an object and its wrapping Create.
Add Public special collection to some more examples.
Note that implementations MUST NOT deliver to the Public special collection.
Merged targeting and delivery; remove outdated "notification targeting".
Note that bcc/bto must be stripped from the delivered ActivityStreams object.
Add SHOULD on not overloading servers with submissions; recommend exponential backoff.
Move "Partial Updates" to own section; mark at risk.
Explicitly name addressing properties to copy for object creation w/o Create.
Add bto and audience to everything that isn't referencing it currently and Reference the ActivityStreams audience targeting directly.
Fixed non-normative citation of Micropub and Social Web Protocols.
Went over all MAY / SHOULD / MUST and made sure correct everywhere.
Note where object and target are required.
Clarify transient messages: allowed, and happen by omitting id (not via fragment id).
Clarify that the proxyUrl uses a form-urlencoded id parameter.
Point to the AS2 docs on Undo.
Added 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.
Updated @context on one example where @language moving around was reported to be confusing/distracting.
E.6 Changes from 13 September 2016 to 04 October 2016
Various typo / grammar fixes.
Added acknowledgements section.
Added security / privacy review section.
Added "At Risk features" section, with the following features listed:
Binary data mechanism
source field
Added source field section
Note that using "https" as a default scheme is ok in clients, if a user neglected to provide one.
Adjusted text around what verification methods are possible.
Added @language to first example.
Explain what we mean by "presented consistently in reverse chronological order" with regard to OrderedCollection.
E.7 Changes from 23 August 2016 to 13 September 2016
Various typo / grammar fixes.
Clarify both transient identifiers and the requirements for "id"
Reference the Social Working Group, Social Web protocols, and Micropub.
Clarify that upon initial Create, both Create and object should share addressing.
Clarify that what was previously called "streams" use OrderedCollections; remove "streams" as an independent term.
Mention ActivityStreams paging.
Add "endpoints" property to actor, move mediaEndpoint here and rename to "uploadMedia".
Add "oauthClientAuthorize", "provideClientKey", and "signClientKey" endpoints.
More clear specification of content negotiation on retrieving AS2 objects; make
of
application/ld+json; profile="https://www.w3.org/ns/activitystreams"
the default media type
and GET
requests (see also 3. 2 Retrieving objects)
with an Accept header of
application/ld+json; profile="https://www.w3.org/ns/activitystreams"
.
Servers SHOULD interpret a Content-Type or Accept
header of application/activity+json
as equivalent
to application/ld+json; profile="https://www.w3.org/ns/activitystreams"
for server-to-server interactions.
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 actor, and then the Activity is inserted into the actor's inbox (delivery). This allows recipient servers to:
Delivery is usually triggered by, for example:
Servers performing delivery to the inbox
or
sharedInbox
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
.
HTTP caching mechanisms [RFC7234] SHOULD be respected when appropriate, both when receiving responses from other servers as well as sending responses to other servers.
The following is required by federated servers communicating with other federated servers only.
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 do content negotiation butbe one.
Servers MUST respond
with AS2 to thede-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.
Attempts to deliver to an inbox on a non-federated server SHOULD
result in a 405 Method Not Allowed
response.
For federated servers performing delivery to a third party server, delivery SHOULD be performed asynchronously, and SHOULD additionally retry delivery to recipients if it fails due to network error.
Note: Activities being distributed between users on the same origin may use any internal mechanism, and are not required to use HTTP.
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).
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 receiving this in an inbox is
that the server SHOULD generate either an Accept
or
Reject
activity with the Follow as the
object
and deliver it to the actor
of the
Follow.
The Accept
or Reject
MAY be generated
automatically, or MAY be the result of user input (possibly after
some delay in which the user reviews).
Servers MAY choose to not explicitly send a Reject
in response to a Follow
, though implementors ought to
be aware that the server sending the request could be left in an
intermediate state.
For example, a server might not send a Reject
to protect
a user's privacy.
In the case of receiving an Accept
referencing this
Follow
as the object, the server SHOULD add the
actor
to the object user's
Followers Collection.
In the case of a Reject
, the server MUST NOT add the
actor to the object user's
Followers Collection.
Sometimes a successful Follow
subscription may
occur but at some future point delivery to the follower fails
for an extended period of time.
Implementations should be aware that there is no guarantee
that actors on the network will remain reachable and should
implement accordingly.
For instance, if attempting to deliver to an actor for perhaps
six months while the follower remains unreachable, it is
reasonable that the delivering server remove the subscriber
from the followers
list.
Timeframes and behavior for dealing with unreachable actors are
left to the discretion of the delivering server.
The side effect of receiving this in an inbox is
determined by the type of the object
received,
and it is possible to accept types not described in this document
(for example, an Offer
).
If the object
of an Accept
received to an
inbox is a Follow
activity
previously sent by the receiver, the server SHOULD add the
actor
to the receiver's
Following Collection.
The side effect of receiving this in an inbox is
determined by the type of the object
received,
and it is possible to reject types not described in this document
(for example, an Offer
).
If the object
of a Reject
received to an
inbox is a Follow
activity
previously sent by the receiver, this means the recipient did not
approve the Follow
request. The server MUST NOT add the
actor
to the receiver's
Following 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 by
adding the received activity to the
likes
collection
if this collection is present.
Upon receipt of an Announce
activity in an
inbox, a server SHOULD increment the object's count
of likes by adding the received activity to the
shares
collection
if this collection is present.
Announce
activity is effectively what is known as
"sharing", "reposting", or "boosting" in other social networks.
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 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.
Servers should be careful to verify that new content is really posted by the actor that claims to be posting it, and that the actor has permission to update the resources it claims to. See also 3. Objects and B.1 Authentication and Authorization.
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
.
Servers should set a limit on how deep to recurse while resolving objects, or otherwise specially handle ActivityStreams objects with recursive references. Failure to properly do so may result in denial-of-service security vulnerabilities.
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.
Servers should implement protections against denial-of-service attacks from other, federated servers. This can be done using, for example, some kind of ratelimiting mechanism. Servers should be especially careful to implement this protection around activities that involve side effects. Servers SHOULD also take care not to overload servers with submissions, for example by using an exponential backoff strategy.
Servers should ratelimit API client submissions. This serves two purposes:
In order to prevent a client from being overloaded by oversized Collections, servers should take care to limit the size of Collection pages they return to clients. Clients should still be prepared to limit the size of responses they are willing to handle in case they connect to malicious or compromised servers, for example by timing out and generating an error.
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.
Erin 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 Erin Shepherd's document to its current state as ActivityPub. Much of the document was rewritten and reorganized under the long feedback process of the Social Working Group.
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. We also thank mray for producing the spectacular tutorial illustrations (which are licensed under the same license as the rest of this document).
Many people also helped ActivityPub along through careful review. In particular, thanks to: Aaron Parecki, AJ Jordan, Benjamin Goering, Caleb Langeslag, Elsa Balderrama, elf Pavlik, Eugen Rochko, Erik Wilde, Jason Robinson, Manu Sporny, Michael Vogel, Mike Macgirvin, nightpool, Puck Meerburg, Sandro Hawke, Sarven Capadisli, Tantek Çelik, and Yuri Volkov.
This document is dedicated to all citizens of planet Earth. You deserve freedom of communication; we hope we have contributed in some part, however small, towards that goal and right.
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/ binary uploadsld+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].