Lemmy Federation Protocol

The Lemmy Protocol (or Lemmy Federation Protocol) is a strict subset of the ActivityPub Protocol. Any deviation from the ActivityPub protocol is a bug in Lemmy or in this documentation (or both).

This document is targeted at developers who are familiar with the ActivityPub and ActivityStreams protocols. It gives a detailed outline of the actors, objects and activities used by Lemmy.

Before reading this, have a look at our Federation Overview to get an idea how Lemmy federation works on a high level.

Lemmy does not yet follow the ActivityPub spec in all regards. For example, we don't set a valid context indicating our context fields. We also ignore fields like inbox, outbox or endpoints for remote actors, and assume that everything is Lemmy. For an overview of deviations, read #698. They will be fixed in the near future.

Lemmy is also really inflexible when it comes to incoming activities and objects. They need to be exactly identical to the examples below. Things like having an array instead of a single value, or an object ID instead of the full object will result in an error.

In the following tables, "mandatory" refers to whether or not Lemmy will accept an incoming activity without this field. Lemmy itself will always include all non-empty fields.

Actors

Community

An automated actor. Users can send posts or comments to it, which the community forwards to its followers in the form of Announce.

Sends activities to user: Accept/Follow, Announce

Receives activities from user: Follow, Undo/Follow, Create, Update, Like, Dislike, Remove (only admin/mod), Delete (only creator), Undo (only for own actions)

{
    "@context": "https://www.w3.org/ns/activitystreams",
    "id": "https://enterprise.lemmy.ml/c/main",
    "type": "Group",
    "preferredUsername": "main",
    "name": "The Main Community",
    "category": { 
        "identifier": "1",
        "name": "Discussion"
    },
    "sensitive": false,
    "attributedTo": [
        "https://enterprise.lemmy.ml/u/picard",
        "https://enterprise.lemmy.ml/u/riker"
    ],
    "content": "Welcome to the default community!",
    "source": {
        "content": "Welcome to the default community!",
        "mediaType": "text/markdown"
    },
    "icon": {
        "type": "Image",
        "url": "https://enterprise.lemmy.ml/pictrs/image/Z8pFFb21cl.png"
    },
    "image": {
        "type": "Image",
        "url": "https://enterprise.lemmy.ml/pictrs/image/Wt8zoMcCmE.jpg"
    },
    "inbox": "https://enterprise.lemmy.ml/c/main/inbox",
    "outbox": "https://enterprise.lemmy.ml/c/main/outbox",
    "followers": "https://enterprise.lemmy.ml/c/main/followers",
    "endpoints": {
        "sharedInbox": "https://enterprise.lemmy.ml/inbox"
    },
    "published": "2020-10-06T17:27:43.282386+00:00",
    "updated": "2020-10-08T11:57:50.545821+00:00",
    "publicKey": {
        "id": "https://enterprise.lemmy.ml/c/main#main-key",
        "owner": "https://enterprise.lemmy.ml/c/main",
        "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA9JJ7Ybp/H7iXeLkWFepg\ny4PHyIXY1TO9rK3lIBmAjNnkNywyGXMgUiiVhGyN9yU7Km8aWayQsNHOkPL7wMZK\nnY2Q+CTQv49kprEdcDVPGABi6EbCSOcRFVaUjjvRHf9Olod2QP/9OtX0oIFKN2KN\nPIUjeKK5tw4EWB8N1i5HOuOjuTcl2BXSemCQLAlXerLjT8xCarGi21xHPaQvAuns\nHt8ye7fUZKPRT10kwDMapjQ9Tsd+9HeBvNa4SDjJX1ONskNh2j4bqHHs2WUymLpX\n1cgf2jmaXAsz6jD9u0wfrLPelPJog8RSuvOzDPrtwX6uyQOl5NK00RlBZwj7bMDx\nzwIDAQAB\n-----END PUBLIC KEY-----\n"
    }
}
Field NameMandatoryDescription
preferredUsernameyesName of the actor
nameyesTitle of the community
categoryyesHardcoded list of categories, see https://lemmy.ml/api/v1/categories
sensitiveyesTrue indicates that all posts in the community are nsfw
attributedToyesFirst the community creator, then all the remaining moderators
contentnoText for the community sidebar, usually containing a description and rules
iconnoIcon, shown next to the community name
imagenoBanner image, shown on top of the community page
inboxnoActivityPub inbox URL
outboxnoActivityPub outbox URL, only contains up to 20 latest posts, no comments, votes or other activities
followersnoFollower collection URL, only contains the number of followers, no references to individual followers
endpointsnoContains URL of shared inbox
publishednoDatetime when the community was first created
updatednoDatetime when the community was last changed
publicKeyyesThe public key used to verify signatures from this actor

User

A person, interacts primarily with the community where it sends and receives posts/comments. Can also create and moderate communities, and send private messages to other users.

Sends activities to Community: Follow, Undo/Follow, Create, Update, Like, Dislike, Remove (only admin/mod), Delete (only creator), Undo (only for own actions)

Receives activities from Community: Accept/Follow, Announce

Sends and receives activities from/to other users: Create/Note, Update/Note, Delete/Note, Undo/Delete/Note (all those related to private messages)

{
    "@context": "https://www.w3.org/ns/activitystreams",
    "id": "https://enterprise.lemmy.ml/u/picard",
    "type": "Person",
    "preferredUsername": "picard",
    "name": "Jean-Luc Picard",
    "content": "The user bio",
    "source": {
        "content": "The user bio",
        "mediaType": "text/markdown"
    },
    "icon": {
        "type": "Image",
        "url": "https://enterprise.lemmy.ml/pictrs/image/DS3q0colRA.jpg"
    },
    "image": {
        "type": "Image",
        "url": "https://enterprise.lemmy.ml/pictrs/image/XenaYI5hTn.png"
    },
    "inbox": "https://enterprise.lemmy.ml/u/picard/inbox",
    "endpoints": {
        "sharedInbox": "https://enterprise.lemmy.ml/inbox"
    },
    "published": "2020-10-06T17:27:43.234391+00:00",
    "updated": "2020-10-08T11:27:17.905625+00:00",
    "publicKey": {
        "id": "https://enterprise.lemmy.ml/u/picard#main-key",
        "owner": "https://enterprise.lemmy.ml/u/picard",
        "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyH9iH83+idw/T4QpuRSY\n5YgQ/T5pJCNxvQWb6qcCu3gEVigfbreqZKJpOih4YT36wu4GjPfoIkbWJXcfcEzq\nMEQoYbPStuwnklpN2zj3lRIPfGLht9CAlENLWikTUoW5kZLyU6UQtOGdT2b1hDuK\nsUEn67In6qYx6pal8fUbO6X3O2BKzGeofnXgHCu7QNIuH4RPzkWsLhvwqEJYP0zG\nodao2j+qmhKFsI4oNOUCGkdJejO7q+9gdoNxAtNNKilIOwUFBYXeZJb+XGlzo0X+\n70jdJ/xQCPlPlItU4pD/0FwPLtuReoOpMzLi20oDsPXJBvn+/NJaxqDINuywcN5p\n4wIDAQAB\n-----END PUBLIC KEY-----\n"
    }
}
Field NameMandatoryDescription
preferredUsernameyesName of the actor
namenoThe user's displayname
contentnoUser bio
iconnoThe user's avatar, shown next to the username
imagenoThe user's banner, shown on top of the profile
inboxnoActivityPub inbox URL
endpointsnoContains URL of shared inbox
publishednoDatetime when the user signed up
updatednoDatetime when the user profile was last changed
publicKeyyesThe public key used to verify signatures from this actor

Objects

Post

A page with title, and optional URL and text content. The URL often leads to an image, in which case a thumbnail is included. Each post belongs to exactly one community.

{
    "@context": "https://www.w3.org/ns/activitystreams",
    "id": "https://voyager.lemmy.ml/post/29",
    "type": "Page",
    "attributedTo": "https://voyager.lemmy.ml/u/picard",
    "to": "https://voyager.lemmy.ml/c/main",
    "summary": "Test thumbnail 2",
    "content": "blub blub",
    "source": {
        "content": "blub blub",
        "mediaType": "text/markdown"
    },
    "url": "https://voyager.lemmy.ml:/pictrs/image/fzGwCsq7BJ.jpg",
    "image": {
        "type": "Image",
        "url": "https://voyager.lemmy.ml/pictrs/image/UejwBqrJM2.jpg"
    },
    "commentsEnabled": true,
    "sensitive": false,
    "stickied": false,
    "published": "2020-09-24T17:42:50.396237+00:00",
    "updated": "2020-09-24T18:31:14.158618+00:00"
}
Field NameMandatoryDescription
attributedToyesID of the user which created this post
toyesID of the community where it was posted to
summaryyesTitle of the post
contentnoBody of the post
urlnoAn arbitrary link to be shared
imagenoThumbnail for url, only present if it is an image link
commentsEnabledyesFalse indicates that the post is locked, and no comments can be added
sensitiveyesTrue marks the post as NSFW, blurs the thumbnail and hides it from users with NSFW settign disabled
stickiedyesTrue means that it is shown on top of the community
publishednoDatetime when the post was created
updatednoDatetime when the post was edited (not present if it was never edited)

Comment

A reply to a post, or reply to another comment. Contains only text (including references to other users or communities). Lemmy displays comments in a tree structure.

{
    "@context": "https://www.w3.org/ns/activitystreams",
    "id": "https://enterprise.lemmy.ml/comment/95",
    "type": "Note",
    "attributedTo": "https://enterprise.lemmy.ml/u/picard",
    "to": "https://enterprise.lemmy.ml/c/main",
    "content": "mmmk",
    "source": {
        "content": "mmmk",
        "mediaType": "text/markdown"
    },
    "inReplyTo": [
        "https://enterprise.lemmy.ml/post/38",
        "https://voyager.lemmy.ml/comment/73"
    ],
    "published": "2020-10-06T17:53:22.174836+00:00",
    "updated": "2020-10-06T17:53:22.174836+00:00"
}
Field NameMandatoryDescription
attributedToyesID of the user who created the comment
toyesCommunity where the comment was made
contentyesThe comment text
inReplyToyesIDs of the post where this comment was made, and the parent comment. If this is a top-level comment, inReplyTo only contains the post
publishednoDatetime when the comment was created
updatednoDatetime when the comment was edited (not present if it was never edited)

Private Message

A direct message from one user to another. Can not include additional users. Threading is not implemented yet, so the inReplyTo field is missing.

{
    "@context": "https://www.w3.org/ns/activitystreams",
    "id": "https://enterprise.lemmy.ml/private_message/34",
    "type": "Note",
    "attributedTo": "https://enterprise.lemmy.ml/u/picard",
    "to": "https://voyager.lemmy.ml/u/janeway",
    "content": "test",
    "source": {
        "content": "test",
        "mediaType": "text/markdown"
    },
    "mediaType": "text/markdown",
    "published": "2020-10-08T19:10:46.542820+00:00",
    "updated": "2020-10-08T20:13:52.547156+00:00"
}
Field NameMandatoryDescription
attributedToID of the user who created this private message
toID of the recipient
contentyesThe text of the private message
publishednoDatetime when the message was created
updatednoDatetime when the message was edited (not present if it was never edited)

Activities

Follow

When the user clicks "Subscribe" in a community, a Follow is sent. The community automatically responds with an Accept/Follow.

Sent by: User

Sent to: Community

{
    "@context": "https://www.w3.org/ns/activitystreams",
    "id": "https://enterprise.lemmy.ml/activities/follow/2e4784b7-4edf-4fa1-a352-674d5d5f8891",
    "type": "Follow",
    "actor": "https://enterprise.lemmy.ml/u/picard",
    "to": "https://ds9.lemmy.ml/c/main",
    "object": "https://ds9.lemmy.ml/c/main"
}
Field NameMandatoryDescription
actoryesThe user that is sending the follow request
objectyesThe community to be followed

Accept Follow

Automatically sent by the community in response to a Follow. At the same time, the community adds this user to its followers list.

Sent by: Community

Sent to: User

{
    "@context": "https://www.w3.org/ns/activitystreams",
    "id": "https://ds9.lemmy.ml/activities/accept/5314bf7c-dab8-4b01-baf2-9be11a6a812e",
    "type": "Accept",
    "actor": "https://ds9.lemmy.ml/c/main",
    "to": "https://enterprise.lemmy.ml/u/picard",
    "object": {
        "@context": "https://www.w3.org/ns/activitystreams",
        "id": "https://enterprise.lemmy.ml/activities/follow/2e4784b7-4edf-4fa1-a352-674d5d5f8891",
        "type": "Follow",
        "object": "https://ds9.lemmy.ml/c/main",
        "actor": "https://enterprise.lemmy.ml/u/picard"
    }
}
Field NameMandatoryDescription
actoryesThe same community as in the Follow activity
tonoID of the user which sent the Follow
objectyesThe previously sent Follow activity

Unfollow

Clicking on the unsubscribe button in a community causes an Undo/Follow to be sent. The community removes the user from its follower list after receiving it.

Sent by: User

Sent to: Community

{
    "@context": "https://www.w3.org/ns/activitystreams",
    "id": "http://lemmy-alpha:8541/activities/undo/2c624a77-a003-4ed7-91cb-d502eb01b8e8",
    "type": "Undo",
    "actor": "http://lemmy-alpha:8541/u/lemmy_alpha",
    "to": "http://lemmy-beta:8551/c/main",
    "object": {
        "@context": "https://www.w3.org/ns/activitystreams",
        "id": "http://lemmy-alpha:8541/activities/follow/f0d732e7-b1e7-4857-a5e0-9dc83c3f7ee8",
        "type": "Follow",
        "actor": "http://lemmy-alpha:8541/u/lemmy_alpha",
        "object": "http://lemmy-beta:8551/c/main"
    }
}

Create or Update Post

When a user creates a new post, it is sent to the respective community. Editing a previously created post sends an almost identical activity, except the type being Update. We don't support mentions in posts yet.

Sent by: User

Sent to: Community

{
    "@context": "https://www.w3.org/ns/activitystreams",
    "id": "https://enterprise.lemmy.ml/activities/create/6e11174f-501a-4531-ac03-818739bfd07d",
    "type": "Create",
    "actor": "https://enterprise.lemmy.ml/u/riker",
    "to": "https://www.w3.org/ns/activitystreams#Public",
    "cc": [
      "https://ds9.lemmy.ml/c/main/"
    ],
    "object": ...
}
Field NameMandatoryDescription
typeyeseither Create or Update
ccyesCommunity where the post is being made
objectyesThe post being created

Create or Update Comment

A reply to a post, or to another comment. Can contain mentions of other users. Editing a previously created post sends an almost identical activity, except the type being Update.

Sent by: User

Sent to: Community

{
    "@context": "https://www.w3.org/ns/activitystreams",
    "id": "https://enterprise.lemmy.ml/activities/create/6f52d685-489d-4989-a988-4faedaed1a70",
    "type": "Create",
    "actor": "https://enterprise.lemmy.ml/u/riker",
    "to": "https://www.w3.org/ns/activitystreams#Public",
    "tag": [{
        "type": "Mention",
        "name": "@[email protected]",
        "href": "https://ds9.lemmy.ml/u/sisko"
    }],
    "cc": [
        "https://ds9.lemmy.ml/c/main/",
        "https://ds9.lemmy.ml/u/sisko"
    ],
    "object": ...
}
Field NameMandatoryDescription
tagnoList of users which are mentioned in the comment (like @[email protected])
ccyesCommunity where the post is being made, the user being replied to (creator of the parent post/comment), as well as any mentioned users
objectyesThe comment being created

Like Post or Comment

An upvote for a post or comment.

Sent by: User

Sent to: Community

{
    "@context": "https://www.w3.org/ns/activitystreams",
    "id": "https://enterprise.lemmy.ml/activities/like/8f3f48dd-587d-4624-af3d-59605b7abad3",
    "type": "Like",
    "actor": "https://enterprise.lemmy.ml/u/riker",
    "to": "https://www.w3.org/ns/activitystreams#Public",
    "cc": [
        "https://ds9.lemmy.ml/c/main/"
    ],
    "object": "https://enterprise.lemmy.ml/p/123"
}
Field NameMandatoryDescription
ccyesID of the community where the post/comment is
objectyesThe post or comment being upvoted

Dislike Post or Comment

A downvote for a post or comment.

Sent by: User

Sent to: Community

{
    "@context": "https://www.w3.org/ns/activitystreams",
    "id": "https://enterprise.lemmy.ml/activities/dislike/fd2b8e1d-719d-4269-bf6b-2cadeebba849",
    "type": "Dislike",
    "actor": "https://enterprise.lemmy.ml/u/riker",
    "to": "https://www.w3.org/ns/activitystreams#Public",
    "cc": [
      "https://ds9.lemmy.ml/c/main/"
    ],
    "object": "https://enterprise.lemmy.ml/p/123"
}
Field NameMandatoryDescription
ccyesID of the community where the post/comment is
objectyesThe post or comment being upvoted

Delete Post or Comment

Deletes a previously created post or comment. This can only be done by the original creator of that post/comment.

Sent by: User

Sent to: Community

{
    "@context": "https://www.w3.org/ns/activitystreams",
    "id": "https://enterprise.lemmy.ml/activities/delete/f1b5d57c-80f8-4e03-a615-688d552e946c",
    "type": "Delete",
    "actor": "https://enterprise.lemmy.ml/u/riker",
    "to": "https://www.w3.org/ns/activitystreams#Public",
    "cc": [
        "https://enterprise.lemmy.ml/c/main/"
    ],
    "object": "https://enterprise.lemmy.ml/post/32"
}
Field NameMandatoryDescription
ccyesID of the community where the post/comment is
objectyesID of the post or comment being deleted

Remove Post or Comment

Removes a post or comment. This can only be done by a community mod, or by an admin on the instance where the community is hosted.

Sent by: User

Sent to: Community

{
    "@context": "https://www.w3.org/ns/activitystreams",
    "id": "https://ds9.lemmy.ml/activities/remove/aab93b8e-3688-4ea3-8212-d00d29519218",
    "type": "Remove",
    "actor": "https://ds9.lemmy.ml/u/sisko",
    "to": "https://www.w3.org/ns/activitystreams#Public",
    "cc": [
        "https://ds9.lemmy.ml/c/main/"
    ],
    "object": "https://enterprise.lemmy.ml/comment/32"
}
Field NameMandatoryDescription
ccyesID of the community where the post/comment is
objectyesID of the post or comment being removed

Undo

Reverts a previous activity, can only be done by the actor of object. In case of a Like or Dislike, the vote count is changed back. In case of a Delete or Remove, the post/comment is restored. The object is regenerated from scratch, as such the activity ID and other fields are different.

Sent by: User

Sent to: Community

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "id": "https://ds9.lemmy.ml/activities/undo/70ca5fb2-e280-4fd0-a593-334b7f8a5916",
  "type": "Undo",
  "actor": "https://ds9.lemmy.ml/u/sisko",
  "to": "https://www.w3.org/ns/activitystreams#Public",
  "cc": [
    "https://ds9.lemmy.ml/c/main/"
  ],
  "object": ...
}
Field NameMandatoryDescription
objectyesAny Like, Dislike, Delete or Remove activity as described above

Announce

When the community receives a post or comment activity, it wraps that into an Announce and sends it to all followers.

Sent by: Community

Sent to: User

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "id": "https://ds9.lemmy.ml/activities/announce/b98382e8-6cb1-469e-aa1f-65c5d2c31cc4",
  "type": "Announce",
  "actor": "https://ds9.lemmy.ml/c/main",
  "to": "https://www.w3.org/ns/activitystreams#Public",
  "cc": [
    "https://ds9.lemmy.ml/c/main/followers"
  ],
  "object": ...
}
Field NameMandatoryDescription
objectyesAny Create, Update, Like, Dislike, Delete Remove or Undo activity as described above

Remove or Delete Community

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "id": "http://ds9.lemmy.ml/activities/remove/e4ca7688-af9d-48b7-864f-765e7f9f3591",
  "type": "Remove",
  "actor": "http://ds9.lemmy.ml/c/some_community",
  "cc": [
    "http://ds9.lemmy.ml/c/some_community/followers"
  ],
  "to": "https://www.w3.org/ns/activitystreams#Public",
  "object": "http://ds9.lemmy.ml/c/some_community"
}
Field NameMandatoryDescription
typeyesEither Remove or Delete

Restore Removed or Deleted Community

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "id": "http://ds9.lemmy.ml/activities/like/0703668c-8b09-4a85-aa7a-f93621936901",
  "type": "Undo",
  "actor": "http://ds9.lemmy.ml/c/some_community",
  "to": "https://www.w3.org/ns/activitystreams#Public",
  "cc": [
    "http://ds9.lemmy.ml/c/testcom/followers"
  ],
  "object": {
    "@context": "https://www.w3.org/ns/activitystreams",
    "id": "http://ds9.lemmy.ml/activities/remove/1062b5e0-07e8-44fc-868c-854209935bdd",
    "type": "Remove",
    "actor": "http://ds9.lemmy.ml/c/some_community",
    "object": "http://ds9.lemmy.ml/c/testcom",
    "to": "https://www.w3.org/ns/activitystreams#Public",
    "cc": [
      "http://ds9.lemmy.ml/c/testcom/followers"
    ]
  }
}

Field NameMandatoryDescription
object.typeyesEither Remove or Delete

Create or Update Private message

Creates a new private message between two users.

Sent by: User

Sent to: User

{
    "@context": "https://www.w3.org/ns/activitystreams",
    "id": "https://ds9.lemmy.ml/activities/create/202daf0a-1489-45df-8d2e-c8a3173fed36",
    "type": "Create",
    "actor": "https://ds9.lemmy.ml/u/sisko",
    "to": "https://enterprise.lemmy.ml/u/riker/inbox",
    "object": ...
}
Field NameMandatoryDescription
typeyesEither Create or Update

Delete Private Message

Deletes a previous private message.

Sent by: User

Sent to: User

{
    "@context": "https://www.w3.org/ns/activitystreams",
    "id": "https://ds9.lemmy.ml/activities/delete/2de5a5f3-bf26-4949-a7f5-bf52edfca909",
    "type": "Delete",
    "actor": "https://ds9.lemmy.ml/u/sisko",
    "to": "https://enterprise.lemmy.ml/u/riker/inbox",
    "object": "https://ds9.lemmy.ml/private_message/341"
}

Undo Delete Private Message

Restores a previously deleted private message. The object is regenerated from scratch, as such the activity ID and other fields are different.

Sent by: User

Sent to: User

{
    "@context": "https://www.w3.org/ns/activitystreams",
    "id": "https://ds9.lemmy.ml/activities/undo/b24bc56d-5db1-41dd-be06-3f1db8757842",
    "type": "Undo",
    "actor": "https://ds9.lemmy.ml/u/sisko",
    "to": "https://enterprise.lemmy.ml/u/riker/inbox",
    "object": ...
}