lemmy/docs/src/contributing_websocket_http_api.md
Dessalines 5c6258390c
Isomorphic docker (#1124)
* Adding a way to GetComments for a community given its name only.

* Adding getcomments to api docs.

* A first pass at locally working isomorphic integration.

* Testing out cargo-husky.

* Testing a fail hook.

* Revert "Testing a fail hook."

This reverts commit 0941cf1736.

* Moving server to top level, now that UI is gone.

* Running cargo fmt using old way.

* Adding nginx, fixing up docker-compose files, fixing docs.

* Trying to re-add API tests.

* Fixing prod dockerfile.

* Redoing nightly fmt

* Trying to fix private message api test.

* Adding CommunityJoin, PostJoin instead of joins from GetComments, etc.

- Fixes #1122

* Fixing fmt.

* Fixing up docs.

* Removing translations.

* Adding apps / clients to readme.

* Fixing main image.

* Using new lemmy-isomorphic-ui with better javascript disabled.

* Try to fix image uploads in federation test

* Revert "Try to fix image uploads in federation test"

This reverts commit a2ddf2a90b.

* Fix post url federation

* Adding some more tests, some still broken.

* Don't need gitattributes anymore.

* Update local federation test setup

* Fixing tests.

* Fixing travis build.

* Fixing travis build, again.

* Changing lemmy-isomorphic-ui to lemmy-ui

* Error in travis build again.

Co-authored-by: Felix Ableitner <me@nutomic.com>
2020-09-15 15:26:47 -04:00

31 KiB

Lemmy API

Note: this may lag behind the actual API endpoints here. The API should be considered unstable and may change any time.

Data types

  • i16, i32 and i64 are respectively 16-bit, 32-bit and 64-bit integers.
  • Option<SomeType> designates an option which may be omitted in requests and not be present in responses. It will be of type SomeType.
  • Vec<SomeType> is a list which contains objects of type SomeType.
  • chrono::NaiveDateTime is a timestamp string in ISO 8601 format. Timestamps will be UTC.
  • Other data types are listed here.

Basic usage

Request and response strings are in JSON format.

WebSocket

Connect to ws://host/api/v1/ws to get started.

If the host supports secure connections, you can use wss://host/api/v1/ws.

To receive websocket messages, you must join a room / context. The three available are:

  • UserJoin. Receives replies, private messages, etc.
  • PostJoin. Receives new comments on a post.
  • CommunityJoin. Receives front page / community posts.

Testing with Websocat

Websocat link

websocat ws://127.0.0.1:8536/api/v1/ws -nt

A simple test command: {"op": "ListCategories"}

Testing with the WebSocket JavaScript API

WebSocket JavaScript API

var ws = new WebSocket("ws://" + host + "/api/v1/ws");
ws.onopen = function () {
  console.log("Connection succeed!");
  ws.send(JSON.stringify({
    op: "ListCategories"
  }));
};

HTTP

Endpoints are at http://host/api/v1/endpoint. They'll be listed below for each action.

Testing with Curl

Get Example
curl /community/list?sort=Hot
Post Example
curl -i -H \
"Content-Type: application/json" \
-X POST \
-d '{
  "comment_id": X,
  "post_id": X,
  "score": X,
  "auth": "..."
}' \
/comment/like

Rate limits

  • 1 per hour for signups and community creation.
  • 1 per 10 minutes for post creation.
  • 30 actions per minute for post voting and comment creation.
  • Everything else is not rate-limited.

Errors

{
  op: String,
  message: String,
}

API documentation

Sort Types

These go wherever there is a sort field. The available sort types are:

  • Active - the hottest posts/communities, depending on votes, and newest comment publish date.
  • Hot - the hottest posts/communities, depending on votes and publish date.
  • New - the newest posts/communities
  • TopDay - the most upvoted posts/communities of the current day.
  • TopWeek - the most upvoted posts/communities of the current week.
  • TopMonth - the most upvoted posts/communities of the current month.
  • TopYear - the most upvoted posts/communities of the current year.
  • TopAll - the most upvoted posts/communities on the current instance.

Undoing actions

Whenever you see a deleted: bool, removed: bool, read: bool, locked: bool, etc, you can undo this action by sending false.

Websocket vs HTTP

  • Below are the websocket JSON requests / responses. For HTTP, ignore all fields except those inside data.
  • For example, an http login will be a POST {username_or_email: X, password: X}

User / Authentication / Admin actions

Login

The jwt string should be stored and used anywhere auth is called for.

Request
{
  op: "Login",
  data: {
    username_or_email: String,
    password: String
  }
}
Response
{
  op: "Login",
  data: {
    jwt: String,
  }
}
HTTP

POST /user/login

Register

Only the first user will be able to be the admin.

Request
{
  op: "Register",
  data: {
    username: String,
    email: Option<String>,
    password: String,
    password_verify: String,
    admin: bool,
    captcha_uuid: Option<String>, // Only checked if these are enabled in the server
    captcha_answer: Option<String>,
  }
}
Response
{
  op: "Register",
  data: {
    jwt: String,
  }
}
HTTP

POST /user/register

Get Captcha

These expire after 10 minutes.

Request
{
  op: "GetCaptcha",
}
Response
{
  op: "GetCaptcha",
  data: {
    ok?: { // Will be undefined if captchas are disabled
      png: String, // A Base64 encoded png
      wav: Option<String>, // A Base64 encoded wav audio file
      uuid: String,
    }
  }
}
HTTP

GET /user/get_captcha

Get User Details

Request
{
  op: "GetUserDetails",
  data: {
    user_id: Option<i32>,
    username: Option<String>,
    sort: String,
    page: Option<i64>,
    limit: Option<i64>,
    community_id: Option<i32>,
    saved_only: bool,
    auth: Option<String>,
  }
}
Response
{
  op: "GetUserDetails",
  data: {
    user: UserView,
    follows: Vec<CommunityFollowerView>,
    moderates: Vec<CommunityModeratorView>,
    comments: Vec<CommentView>,
    posts: Vec<PostView>,
  }
}
HTTP

GET /user

Save User Settings

Request
{
  op: "SaveUserSettings",
  data: {
    show_nsfw: bool,
    theme: String, // Default 'darkly'
    default_sort_type: i16, // The Sort types from above, zero indexed as a number
    default_listing_type: i16, // Post listing types are `All, Subscribed, Community`
    lang: String,
    avatar: Option<String>,
    banner: Option<String>,
    preferred_username: Option<String>,
    email: Option<String>,
    bio: Option<String>,
    matrix_user_id: Option<String>,
    new_password: Option<String>,
    new_password_verify: Option<String>,
    old_password: Option<String>,
    show_avatars: bool,
    send_notifications_to_email: bool,
    auth: String,
  }
}
Response
{
  op: "SaveUserSettings",
  data: {
    jwt: String
  }
}
HTTP

PUT /user/save_user_settings

Get Replies / Inbox

Request
{
  op: "GetReplies",
  data: {
    sort: String,
    page: Option<i64>,
    limit: Option<i64>,
    unread_only: bool,
    auth: String
  }
}
Response
{
  op: "GetReplies",
  data: {
    replies: Vec<ReplyView>,
  }
}
HTTP

GET /user/replies

Get User Mentions

Request
{
  op: "GetUserMentions",
  data: {
    sort: String,
    page: Option<i64>,
    limit: Option<i64>,
    unread_only: bool,
    auth: String,
  }
}
Response
{
  op: "GetUserMentions",
  data: {
    mentions: Vec<UserMentionView>,
  }
}
HTTP

GET /user/mention

Mark User Mention as read

Only the recipient can do this.

Request
{
  op: "MarkUserMentionAsRead",
  data: {
    user_mention_id: i32,
    read: bool,
    auth: String,
  }
}
Response
{
  op: "MarkUserMentionAsRead",
  data: {
    mention: UserMentionView,
  }
}
HTTP

POST /user/mention/mark_as_read

Get Private Messages

Request
{
  op: "GetPrivateMessages",
  data: {
    unread_only: bool,
    page: Option<i64>,
    limit: Option<i64>,
    auth: String,
  }
}
Response
{
  op: "GetPrivateMessages",
  data: {
    messages: Vec<PrivateMessageView>,
  }
}
HTTP

GET /private_message/list

Create Private Message

Request
{
  op: "CreatePrivateMessage",
  data: {
    content: String,
    recipient_id: i32,
    auth: String,
  }
}
Response
{
  op: "CreatePrivateMessage",
  data: {
    message: PrivateMessageView,
  }
}
HTTP

POST /private_message

Edit Private Message

Request
{
  op: "EditPrivateMessage",
  data: {
    edit_id: i32,
    content: String,
    auth: String,
  }
}
Response
{
  op: "EditPrivateMessage",
  data: {
    message: PrivateMessageView,
  }
}
HTTP

PUT /private_message

Delete Private Message

Request
{
  op: "DeletePrivateMessage",
  data: {
    edit_id: i32,
    deleted: bool,
    auth: String,
  }
}
Response
{
  op: "DeletePrivateMessage",
  data: {
    message: PrivateMessageView,
  }
}
HTTP

POST /private_message/delete

Mark Private Message as Read

Only the recipient can do this.

Request
{
  op: "MarkPrivateMessageAsRead",
  data: {
    edit_id: i32,
    read: bool,
    auth: String,
  }
}
Response
{
  op: "MarkPrivateMessageAsRead",
  data: {
    message: PrivateMessageView,
  }
}
HTTP

POST /private_message/mark_as_read

Mark All As Read

Marks all user replies and mentions as read.

Request
{
  op: "MarkAllAsRead",
  data: {
    auth: String
  }
}
Response
{
  op: "MarkAllAsRead",
  data: {
    replies: Vec<ReplyView>,
  }
}
HTTP

POST /user/mark_all_as_read

Delete Account

Permanently deletes your posts and comments

Request
{
  op: "DeleteAccount",
  data: {
    password: String,
    auth: String
  }
}
Response
{
  op: "DeleteAccount",
  data: {
    jwt: String,
  }
}
HTTP

POST /user/delete_account

Add admin

Request
{
  op: "AddAdmin",
  data: {
    user_id: i32,
    added: bool,
    auth: String
  }
}
Response
{
  op: "AddAdmin",
  data: {
    admins: Vec<UserView>,
  }
}
HTTP

POST /admin/add

Ban user

Request
{
  op: "BanUser",
  data: {
    user_id: i32,
    ban: bool,
    remove_data: Option<bool>, // Removes/Restores their comments, posts, and communities
    reason: Option<String>,
    expires: Option<i64>,
    auth: String
  }
}
Response
{
  op: "BanUser",
  data: {
    user: UserView,
    banned: bool,
  }
}
HTTP

POST /user/ban

User Join

Request
{
  op: "UserJoin",
  data: {
    auth: String
  }
}
Response
{
  op: "UserJoin",
  data: {
    joined: bool,
  }
}
HTTP

POST /user/join

Site

List Categories

Request
{
  op: "ListCategories"
}
Response
{
  op: "ListCategories",
  data: {
    categories: Vec<Category>
  }
}
HTTP

GET /categories

Search types are All, Comments, Posts, Communities, Users, Url

Request
{
  op: "Search",
  data: {
    q: String,
    type_: String,
    community_id: Option<i32>,
    sort: String,
    page: Option<i64>,
    limit: Option<i64>,
    auth?: Option<String>,
  }
}
Response
{
  op: "Search",
  data: {
    type_: String,
    comments: Vec<CommentView>,
    posts: Vec<PostView>,
    communities: Vec<CommunityView>,
    users: Vec<UserView>,
  }
}
HTTP

GET /search

Get Modlog

Request
{
  op: "GetModlog",
  data: {
    mod_user_id: Option<i32>,
    community_id: Option<i32>,
    page: Option<i64>,
    limit: Option<i64>,
  }
}
Response
{
  op: "GetModlog",
  data: {
    removed_posts: Vec<ModRemovePostView>,
    locked_posts: Vec<ModLockPostView>,
    removed_comments: Vec<ModRemoveCommentView>,
    removed_communities: Vec<ModRemoveCommunityView>,
    banned_from_community: Vec<ModBanFromCommunityView>,
    banned: Vec<ModBanView>,
    added_to_community: Vec<ModAddCommunityView>,
    added: Vec<ModAddView>,
  }
}
HTTP

GET /modlog

Create Site

Request
{
  op: "CreateSite",
  data: {
    name: String,
    description: Option<String>,
    icon: Option<String>,
    banner: Option<String>,
    auth: String
  }
}
Response
{
  op: "CreateSite",
    data: {
    site: SiteView,
  }
}
HTTP

POST /site

Edit Site

Request
{
  op: "EditSite",
  data: {
    name: String,
    description: Option<String>,
    icon: Option<String>,
    banner: Option<String>,
    auth: String
  }
}
Response
{
  op: "EditSite",
  data: {
    site: SiteView,
  }
}
HTTP

PUT /site

Get Site

Request
{
  op: "GetSite"
  data: {
    auth: Option<String>,
  }

}
Response
{
  op: "GetSite",
  data: {
    site: Option<SiteView>,
    admins: Vec<UserView>,
    banned: Vec<UserView>,
    online: usize, // This is currently broken
    version: String,
    my_user: Option<User_>, // Gives back your user and settings if logged in
  }
}
HTTP

GET /site

Transfer Site

Request
{
  op: "TransferSite",
  data: {
    user_id: i32,
    auth: String
  }
}
Response
{
  op: "TransferSite",
  data: {
    site: Option<SiteView>,
    admins: Vec<UserView>,
    banned: Vec<UserView>,
  }
}
HTTP

POST /site/transfer

Get Site Config

Request
{
  op: "GetSiteConfig",
  data: {
    auth: String
  }
}
Response
{
  op: "GetSiteConfig",
  data: {
    config_hjson: String,
  }
}
HTTP

GET /site/config

Save Site Config

Request
{
  op: "SaveSiteConfig",
  data: {
    config_hjson: String,
    auth: String
  }
}
Response
{
  op: "SaveSiteConfig",
  data: {
    config_hjson: String,
  }
}
HTTP

PUT /site/config

Community

Get Community

Request
{
  op: "GetCommunity",
  data: {
    id: Option<i32>,
    name: Option<String>,
    auth: Option<String>
  }
}
Response
{
  op: "GetCommunity",
  data: {
    community: CommunityView,
    moderators: Vec<CommunityModeratorView>,
  }
}
HTTP

GET /community

Create Community

Request
{
  op: "CreateCommunity",
  data: {
    name: String,
    title: String,
    description: Option<String>,
    icon: Option<String>,
    banner: Option<String>,
    category_id: i32 ,
    auth: String
  }
}
Response
{
  op: "CreateCommunity",
  data: {
    community: CommunityView
  }
}
HTTP

POST /community

List Communities

Request
{
  op: "ListCommunities",
  data: {
    sort: String,
    page: Option<i64>,
    limit: Option<i64>,
    auth: Option<String>
  }
}
Response
{
  op: "ListCommunities",
  data: {
    communities: Vec<CommunityView>
  }
}
HTTP

GET /community/list

Ban from Community

Request
{
  op: "BanFromCommunity",
  data: {
    community_id: i32,
    user_id: i32,
    ban: bool,
    remove_data: Option<bool>, // Removes/Restores their comments and posts for that community
    reason: Option<String>,
    expires: Option<i64>,
    auth: String
  }
}
Response
{
  op: "BanFromCommunity",
  data: {
    user: UserView,
    banned: bool,
  }
}
HTTP

POST /community/ban_user

Add Mod to Community

Request
{
  op: "AddModToCommunity",
  data: {
    community_id: i32,
    user_id: i32,
    added: bool,
    auth: String
  }
}
Response
{
  op: "AddModToCommunity",
  data: {
    moderators: Vec<CommunityModeratorView>,
  }
}
HTTP

POST /community/mod

Edit Community

Only mods can edit a community.

Request
{
  op: "EditCommunity",
  data: {
    edit_id: i32,
    title: String,
    description: Option<String>,
    icon: Option<String>,
    banner: Option<String>,
    category_id: i32,
    auth: String
  }
}
Response
{
  op: "EditCommunity",
  data: {
    community: CommunityView
  }
}
HTTP

PUT /community

Delete Community

Only a creator can delete a community

Request
{
  op: "DeleteCommunity",
  data: {
    edit_id: i32,
    deleted: bool,
    auth: String,
  }
}
Response
{
  op: "DeleteCommunity",
  data: {
    community: CommunityView
  }
}
HTTP

POST /community/delete

Remove Community

Only admins can remove a community.

Request
{
  op: "RemoveCommunity",
  data: {
    edit_id: i32,
    removed: bool,
    reason: Option<String>,
    expires: Option<i64>,
    auth: String,
  }
}
Response
{
  op: "RemoveCommunity",
  data: {
    community: CommunityView
  }
}
HTTP

POST /community/remove

Follow Community

Request
{
  op: "FollowCommunity",
  data: {
    community_id: i32,
    follow: bool,
    auth: String
  }
}
Response
{
  op: "FollowCommunity",
  data: {
    community: CommunityView
  }
}
HTTP

POST /community/follow

Get Followed Communities

Request
{
  op: "GetFollowedCommunities",
  data: {
    auth: String
  }
}
Response
{
  op: "GetFollowedCommunities",
  data: {
    communities: Vec<CommunityFollowerView>
  }
}
HTTP

GET /user/followed_communities

Transfer Community

Request
{
  op: "TransferCommunity",
  data: {
    community_id: i32,
    user_id: i32,
    auth: String
  }
}
Response
{
  op: "TransferCommunity",
  data: {
    community: CommunityView,
    moderators: Vec<CommunityModeratorView>,
    admins: Vec<UserView>,
  }
}
HTTP

POST /community/transfer

Community Join

The main / frontpage community is community_id: 0.

Request
{
  op: "CommunityJoin",
  data: {
    community_id: i32
  }
}
Response
{
  op: "CommunityJoin",
  data: {
    joined: bool,
  }
}
HTTP

POST /community/join

Post

Create Post

Request
{
  op: "CreatePost",
  data: {
    name: String,
    url: Option<String>,
    body: Option<String>,
    nsfw: bool,
    community_id: i32,
    auth: String,
  }
}
Response
{
  op: "CreatePost",
  data: {
    post: PostView
  }
}
HTTP

POST /post

Get Post

Request
{
  op: "GetPost",
  data: {
    id: i32,
    auth: Option<String>
  }
}
Response
{
  op: "GetPost",
  data: {
    post: PostView,
    comments: Vec<CommentView>,
    community: CommunityView,
    moderators: Vec<CommunityModeratorView>,
  }
}
HTTP

GET /post

Get Posts

Post listing types are All, Subscribed, Community

Request
{
  op: "GetPosts",
  data: {
    type_: String,
    sort: String,
    page: Option<i64>,
    limit: Option<i64>,
    community_id: Option<i32>,
    community_name: Option<String>,
    auth: Option<String>
  }
}
Response
{
  op: "GetPosts",
  data: {
    posts: Vec<PostView>,
  }
}
HTTP

GET /post/list

Create Post Like

score can be 0, -1, or 1

Request
{
  op: "CreatePostLike",
  data: {
    post_id: i32,
    score: i16,
    auth: String
  }
}
Response
{
  op: "CreatePostLike",
  data: {
    post: PostView
  }
}
HTTP

POST /post/like

Edit Post

Request
{
  op: "EditPost",
  data: {
    edit_id: i32,
    name: String,
    url: Option<String>,
    body: Option<String>,
    nsfw: bool,
    auth: String,
  }
}
Response
{
  op: "EditPost",
  data: {
    post: PostView
  }
}
HTTP

PUT /post

Delete Post

Request
{
  op: "DeletePost",
  data: {
    edit_id: i32,
    deleted: bool,
    auth: String,
  }
}
Response
{
  op: "DeletePost",
  data: {
    post: PostView
  }
}
HTTP

POST /post/delete

Remove Post

Only admins and mods can remove a post.

Request
{
  op: "RemovePost",
  data: {
    edit_id: i32,
    removed: bool,
    reason: Option<String>,
    auth: String,
  }
}
Response
{
  op: "RemovePost",
  data: {
    post: PostView
  }
}
HTTP

POST /post/remove

Lock Post

Only admins and mods can lock a post.

Request
{
  op: "LockPost",
  data: {
    edit_id: i32,
    locked: bool,
    auth: String,
  }
}
Response
{
  op: "LockPost",
  data: {
    post: PostView
  }
}
HTTP

POST /post/lock

Sticky Post

Only admins and mods can sticky a post.

Request
{
  op: "StickyPost",
  data: {
    edit_id: i32,
    stickied: bool,
    auth: String,
  }
}
Response
{
  op: "StickyPost",
  data: {
    post: PostView
  }
}
HTTP

POST /post/sticky

Save Post

Request
{
  op: "SavePost",
  data: {
    post_id: i32,
    save: bool,
    auth: String
  }
}
Response
{
  op: "SavePost",
  data: {
    post: PostView
  }
}
HTTP

POST /post/save

Post Join

Request
{
  op: "PostJoin",
  data: {
    post_id: i32
  }
}
Response
{
  op: "PostJoin",
  data: {
    joined: bool,
  }
}
HTTP

POST /post/join

Comment

Create Comment

Request
{
  op: "CreateComment",
  data: {
    content: String,
    parent_id: Option<i32>,
    post_id: i32,
    form_id: Option<String>, // An optional form id, so you know which message came back
    auth: String
  }
}
Response
{
  op: "CreateComment",
  data: {
    comment: CommentView
  }
}
HTTP

POST /comment

Edit Comment

Only the creator can edit the comment.

Request
{
  op: "EditComment",
  data: {
    content: String,
    edit_id: i32,
    form_id: Option<String>,
    auth: String,
  }
}
Response
{
  op: "EditComment",
  data: {
    comment: CommentView
  }
}
HTTP

PUT /comment

Delete Comment

Only the creator can delete the comment.

Request
{
  op: "DeleteComment",
  data: {
    edit_id: i32,
    deleted: bool,
    auth: String,
  }
}
Response
{
  op: "DeleteComment",
  data: {
    comment: CommentView
  }
}
HTTP

POST /comment/delete

Remove Comment

Only a mod or admin can remove the comment.

Request
{
  op: "RemoveComment",
  data: {
    edit_id: i32,
    removed: bool,
    reason: Option<String>,
    auth: String,
  }
}
Response
{
  op: "RemoveComment",
  data: {
    comment: CommentView
  }
}
HTTP

POST /comment/remove

Get Comments

Comment listing types are All, Subscribed, Community

Request
{
  op: "GetComments",
  data: {
    type_: String,
    sort: String,
    page: Option<i64>,
    limit: Option<i64>,
    community_id: Option<i32>,
    community_name: Option<String>,
    auth: Option<String>
  }
}
Response
{
  op: "GetComments",
  data: {
    comments: Vec<CommentView>,
  }
}
HTTP

GET /comment/list

Mark Comment as Read

Only the recipient can do this.

Request
{
  op: "MarkCommentAsRead",
  data: {
    edit_id: i32,
    read: bool,
    auth: String,
  }
}
Response
{
  op: "MarkCommentAsRead",
  data: {
    comment: CommentView
  }
}
HTTP

POST /comment/mark_as_read

Save Comment

Request
{
  op: "SaveComment",
  data: {
    comment_id: i32,
    save: bool,
    auth: String
  }
}
Response
{
  op: "SaveComment",
  data: {
    comment: CommentView
  }
}
HTTP

PUT /comment/save

Create Comment Like

score can be 0, -1, or 1

Request
{
  op: "CreateCommentLike",
  data: {
    comment_id: i32,
    score: i16,
    auth: String
  }
}
Response
{
  op: "CreateCommentLike",
  data: {
    comment: CommentView
  }
}
HTTP

POST /comment/like

RSS / Atom feeds

All

/feeds/all.xml?sort=Hot

Community

/feeds/c/community-name.xml?sort=Hot

User

/feeds/u/user-name.xml?sort=Hot