ActivityPub
ActiveActivityPub is a W3C Recommendation (2018) for decentralized social networking. It defines a server-to-server federation protocol and a client-to-server API, both using ActivityStreams 2.0 JSON-LD as the data format. Actors (users, groups, services) have inbox and outbox endpoints. Mastodon, PeerTube, Pixelfed, Lemmy, and 10,000+ servers form the Fediverse – a federated social network of 10+ million users all interoperating via ActivityPub.
In one line
ActivityPub (W3C Recommendation, January 2018) is the federation protocol powering the Fediverse. Every actor has an inbox (receives Activities) and an outbox (publishes Activities). Server-to-server federation: when Alice on mastodon.social follows Bob on fosstodon.org, mastodon.social POSTs a Follow activity to Bob's inbox on fosstodon.org. Activities use ActivityStreams 2.0 JSON-LD. Actor discovery uses WebFinger (RFC 7033). Content is end-to-end signed using HTTP Signatures.
Quick Reference
| Field | Size | Description |
|---|---|---|
| Actor | JSON-LD object | Person, Group, Organization, Application, or Service. Every actor has an id (HTTPS URL), inbox, outbox, followers, following collections. |
| Inbox | POST endpoint | HTTPS URL where other servers POST activities. The server validates the activity, deduplicates, and notifies local users. Authenticated via HTTP Signatures. |
| Outbox | GET/POST endpoint | Contains all public activities by the actor as an OrderedCollection. GET returns the actor's public timeline. POST creates new activities (C2S API). |
| Activity types | 16 core types | Create, Update, Delete, Follow, Accept, Reject, Like, Announce (boost/repost), Block, Undo, Add, Remove, Move, Flag, Ignore, Join. Each wraps an Object. |
| Object types | Note, Article, ... | Note (Mastodon post), Article (blog post), Video (PeerTube), Image (Pixelfed), Question (polls), Audio, Event, Place. Wrapped inside Activities. |
| WebFinger | RFC 7033 | Actor discovery: GET /.well-known/webfinger?resource=acct:user@domain returns the actor's profile URL. How @user@domain lookups work across servers. |
| HTTP Signatures | Draft spec | All S2S federation requests include an HTTP Signature header signing the request body with the actor's RSA private key. Receivers verify against the actor's public key from the actor document. |
| JSON-LD context | @context | Every ActivityPub object must include "@context": "https://www.w3.org/ns/activitystreams". Servers may add extension contexts for Mastodon-specific fields. |
Key Characteristics
Federated delivery
When an actor publishes a post, the server looks up followers' inbox URLs across all servers and POSTs the activity to each. No central server involved.
HTTP Signatures
All server-to-server requests are signed. The receiving server fetches the sender's public key from the actor document and verifies the signature, preventing spoofing.
No end-to-end encryption
ActivityPub transmits content in cleartext to all participant servers. The server admin can read all federated messages. For E2E encryption, see Matrix or XMPP.
Pull vs push
S2S federation is push-based: senders POST to receivers' inboxes. However, fetching old outbox content is pull-based (GET the outbox collection). Both patterns are part of the spec.
Message Format
// Actor document (fetched via WebFinger discovery)
GET https://mastodon.social/users/alice HTTP/1.1
Accept: application/activity+json
{
"@context": "https://www.w3.org/ns/activitystreams",
"type": "Person",
"id": "https://mastodon.social/users/alice",
"inbox": "https://mastodon.social/users/alice/inbox",
"outbox": "https://mastodon.social/users/alice/outbox",
"followers": "https://mastodon.social/users/alice/followers",
"following": "https://mastodon.social/users/alice/following",
"preferredUsername": "alice",
"publicKey": {
"id": "https://mastodon.social/users/alice#main-key",
"owner": "https://mastodon.social/users/alice",
"publicKeyPem": "-----BEGIN PUBLIC KEY-----
..."
}
}// S2S: alice follows bob (fosstodon → mastodon.social)
POST https://mastodon.social/users/alice/inbox HTTP/1.1
Content-Type: application/activity+json
Signature: keyId="...",algorithm="rsa-sha256",headers="...",signature="..."
{
"@context": "https://www.w3.org/ns/activitystreams",
"type": "Follow",
"id": "https://fosstodon.org/users/bob/follows/123",
"actor": "https://fosstodon.org/users/bob",
"object": "https://mastodon.social/users/alice"
}
// mastodon.social accepts and notifies alice:
// POST https://fosstodon.org/users/bob/inbox
{
"type": "Accept",
"actor": "https://mastodon.social/users/alice",
"object": "https://fosstodon.org/users/bob/follows/123"
}