* 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 commit0941cf1736
. * 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 commita2ddf2a90b
. * 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>
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
- Basic usage
- Rate limits
- Errors
- API documentation
- Sort Types
- Undoing actions
- Websocket vs HTTP
- User / Authentication / Admin actions
- Login
- Register
- Get Captcha
- Get User Details
- Save User Settings
- Get Replies / Inbox
- Get User Mentions
- Mark User Mention as read
- Get Private Messages
- Create Private Message
- Edit Private Message
- Delete Private Message
- Mark Private Message as Read
- Mark All As Read
- Delete Account
- Add admin
- Ban user
- User Join
- Site
- Community
- Post
- Comment
- RSS / Atom feeds
Data types
i16
,i32
andi64
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 ws://127.0.0.1:8536/api/v1/ws -nt
A simple test command:
{"op": "ListCategories"}
Testing with the 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/communitiesTopDay
- 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
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