]> Untitled Git - lemmy.git/blob - docs/src/contributing_websocket_http_api.md
Merge remote-tracking branch 'weblate/main' into main
[lemmy.git] / docs / src / contributing_websocket_http_api.md
1 # Lemmy API
2
3 *Note: this may lag behind the actual API endpoints [here](../server/src/api). The API should be considered unstable and may change any time.*
4
5 <!-- toc -->
6
7 - [Data types](#data-types)
8 - [Basic usage](#basic-usage)
9   * [WebSocket](#websocket)
10     + [Testing with Websocat](#testing-with-websocat)
11     + [Testing with the WebSocket JavaScript API](#testing-with-the-websocket-javascript-api)
12   * [HTTP](#http)
13     + [Testing with Curl](#testing-with-curl)
14       - [Get Example](#get-example)
15       - [Post Example](#post-example)
16 - [Rate limits](#rate-limits)
17 - [Errors](#errors)
18 - [API documentation](#api-documentation)
19   * [Sort Types](#sort-types)
20   * [Undoing actions](#undoing-actions)
21   * [Websocket vs HTTP](#websocket-vs-http)
22   * [User / Authentication / Admin actions](#user--authentication--admin-actions)
23     + [Login](#login)
24       - [Request](#request)
25       - [Response](#response)
26       - [HTTP](#http-1)
27     + [Register](#register)
28       - [Request](#request-1)
29       - [Response](#response-1)
30       - [HTTP](#http-2)
31     + [Get User Details](#get-user-details)
32       - [Request](#request-2)
33       - [Response](#response-2)
34       - [HTTP](#http-3)
35     + [Save User Settings](#save-user-settings)
36       - [Request](#request-3)
37       - [Response](#response-3)
38       - [HTTP](#http-4)
39     + [Get Replies / Inbox](#get-replies--inbox)
40       - [Request](#request-4)
41       - [Response](#response-4)
42       - [HTTP](#http-5)
43     + [Get User Mentions](#get-user-mentions)
44       - [Request](#request-5)
45       - [Response](#response-5)
46       - [HTTP](#http-6)
47     + [Mark User Mention as read](#mark-user-mention-as-read)
48       - [Request](#request-6)
49       - [Response](#response-6)
50       - [HTTP](#http-7)
51     + [Get Private Messages](#get-private-messages)
52       - [Request](#request-7)
53       - [Response](#response-7)
54       - [HTTP](#http-8)
55     + [Create Private Message](#create-private-message)
56       - [Request](#request-8)
57       - [Response](#response-8)
58       - [HTTP](#http-9)
59     + [Edit Private Message](#edit-private-message)
60       - [Request](#request-9)
61       - [Response](#response-9)
62       - [HTTP](#http-10)
63     + [Delete Private Message](#delete-private-message)
64       - [Request](#request-10)
65       - [Response](#response-10)
66       - [HTTP](#http-11)
67     + [Mark Private Message as Read](#mark-private-message-as-read)
68       - [Request](#request-11)
69       - [Response](#response-11)
70       - [HTTP](#http-12)
71     + [Mark All As Read](#mark-all-as-read)
72       - [Request](#request-12)
73       - [Response](#response-12)
74       - [HTTP](#http-13)
75     + [Delete Account](#delete-account)
76       - [Request](#request-13)
77       - [Response](#response-13)
78       - [HTTP](#http-14)
79     + [Add admin](#add-admin)
80       - [Request](#request-14)
81       - [Response](#response-14)
82       - [HTTP](#http-15)
83     + [Ban user](#ban-user)
84       - [Request](#request-15)
85       - [Response](#response-15)
86       - [HTTP](#http-16)
87   * [Site](#site)
88     + [List Categories](#list-categories)
89       - [Request](#request-16)
90       - [Response](#response-16)
91       - [HTTP](#http-17)
92     + [Search](#search)
93       - [Request](#request-17)
94       - [Response](#response-17)
95       - [HTTP](#http-18)
96     + [Get Modlog](#get-modlog)
97       - [Request](#request-18)
98       - [Response](#response-18)
99       - [HTTP](#http-19)
100     + [Create Site](#create-site)
101       - [Request](#request-19)
102       - [Response](#response-19)
103       - [HTTP](#http-20)
104     + [Edit Site](#edit-site)
105       - [Request](#request-20)
106       - [Response](#response-20)
107       - [HTTP](#http-21)
108     + [Get Site](#get-site)
109       - [Request](#request-21)
110       - [Response](#response-21)
111       - [HTTP](#http-22)
112     + [Transfer Site](#transfer-site)
113       - [Request](#request-22)
114       - [Response](#response-22)
115       - [HTTP](#http-23)
116     + [Get Site Config](#get-site-config)
117       - [Request](#request-23)
118       - [Response](#response-23)
119       - [HTTP](#http-24)
120     + [Save Site Config](#save-site-config)
121       - [Request](#request-24)
122       - [Response](#response-24)
123       - [HTTP](#http-25)
124   * [Community](#community)
125     + [Get Community](#get-community)
126       - [Request](#request-25)
127       - [Response](#response-25)
128       - [HTTP](#http-26)
129     + [Create Community](#create-community)
130       - [Request](#request-26)
131       - [Response](#response-26)
132       - [HTTP](#http-27)
133     + [List Communities](#list-communities)
134       - [Request](#request-27)
135       - [Response](#response-27)
136       - [HTTP](#http-28)
137     + [Ban from Community](#ban-from-community)
138       - [Request](#request-28)
139       - [Response](#response-28)
140       - [HTTP](#http-29)
141     + [Add Mod to Community](#add-mod-to-community)
142       - [Request](#request-29)
143       - [Response](#response-29)
144       - [HTTP](#http-30)
145     + [Edit Community](#edit-community)
146       - [Request](#request-30)
147       - [Response](#response-30)
148       - [HTTP](#http-31)
149     + [Delete Community](#delete-community)
150       - [Request](#request-31)
151       - [Response](#response-31)
152       - [HTTP](#http-32)
153     + [Remove Community](#remove-community)
154       - [Request](#request-32)
155       - [Response](#response-32)
156       - [HTTP](#http-33)
157     + [Follow Community](#follow-community)
158       - [Request](#request-33)
159       - [Response](#response-33)
160       - [HTTP](#http-34)
161     + [Get Followed Communities](#get-followed-communities)
162       - [Request](#request-34)
163       - [Response](#response-34)
164       - [HTTP](#http-35)
165     + [Transfer Community](#transfer-community)
166       - [Request](#request-35)
167       - [Response](#response-35)
168       - [HTTP](#http-36)
169   * [Post](#post)
170     + [Create Post](#create-post)
171       - [Request](#request-36)
172       - [Response](#response-36)
173       - [HTTP](#http-37)
174     + [Get Post](#get-post)
175       - [Request](#request-37)
176       - [Response](#response-37)
177       - [HTTP](#http-38)
178     + [Get Posts](#get-posts)
179       - [Request](#request-38)
180       - [Response](#response-38)
181       - [HTTP](#http-39)
182     + [Create Post Like](#create-post-like)
183       - [Request](#request-39)
184       - [Response](#response-39)
185       - [HTTP](#http-40)
186     + [Edit Post](#edit-post)
187       - [Request](#request-40)
188       - [Response](#response-40)
189       - [HTTP](#http-41)
190     + [Delete Post](#delete-post)
191       - [Request](#request-41)
192       - [Response](#response-41)
193       - [HTTP](#http-42)
194     + [Remove Post](#remove-post)
195       - [Request](#request-42)
196       - [Response](#response-42)
197       - [HTTP](#http-43)
198     + [Lock Post](#lock-post)
199       - [Request](#request-43)
200       - [Response](#response-43)
201       - [HTTP](#http-44)
202     + [Sticky Post](#sticky-post)
203       - [Request](#request-44)
204       - [Response](#response-44)
205       - [HTTP](#http-45)
206     + [Save Post](#save-post)
207       - [Request](#request-45)
208       - [Response](#response-45)
209       - [HTTP](#http-46)
210   * [Comment](#comment)
211     + [Create Comment](#create-comment)
212       - [Request](#request-46)
213       - [Response](#response-46)
214       - [HTTP](#http-47)
215     + [Edit Comment](#edit-comment)
216       - [Request](#request-47)
217       - [Response](#response-47)
218       - [HTTP](#http-48)
219     + [Delete Comment](#delete-comment)
220       - [Request](#request-48)
221       - [Response](#response-48)
222       - [HTTP](#http-49)
223     + [Remove Comment](#remove-comment)
224       - [Request](#request-49)
225       - [Response](#response-49)
226       - [HTTP](#http-50)
227     + [Mark Comment as Read](#mark-comment-as-read)
228       - [Request](#request-50)
229       - [Response](#response-50)
230       - [HTTP](#http-51)
231     + [Save Comment](#save-comment)
232       - [Request](#request-51)
233       - [Response](#response-51)
234       - [HTTP](#http-52)
235     + [Create Comment Like](#create-comment-like)
236       - [Request](#request-52)
237       - [Response](#response-52)
238       - [HTTP](#http-53)
239   * [RSS / Atom feeds](#rss--atom-feeds)
240     + [All](#all)
241     + [Community](#community-1)
242     + [User](#user)
243
244 <!-- tocstop -->
245
246 ## Data types
247
248 - `i16`, `i32` and `i64` are respectively [16-bit](https://en.wikipedia.org/wiki/16-bit), [32-bit](https://en.wikipedia.org/wiki/32-bit) and [64-bit](https://en.wikipedia.org/wiki/64-bit_computing) integers.
249 - <code>Option<***SomeType***></code> designates an option which may be omitted in requests and not be present in responses. It will be of type ***SomeType***.
250 - <code>Vec<***SomeType***></code> is a list which contains objects of type ***SomeType***.
251 - `chrono::NaiveDateTime` is a timestamp string in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format. Timestamps will be UTC.
252 - Other data types are listed [here](../server/src/db).
253
254 ## Basic usage
255
256 Request and response strings are in [JSON format](https://www.json.org).
257
258 ### WebSocket
259
260 Connect to <code>ws://***host***/api/v1/ws</code> to get started.
261
262 If the ***`host`*** supports secure connections, you can use <code>wss://***host***/api/v1/ws</code>.
263
264 #### Testing with Websocat
265
266 [Websocat link](https://github.com/vi/websocat)
267
268 `websocat ws://127.0.0.1:8536/api/v1/ws -nt`
269
270 A simple test command:
271 `{"op": "ListCategories"}`
272
273 #### Testing with the WebSocket JavaScript API
274
275 [WebSocket JavaScript API](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API)
276 ```javascript
277 var ws = new WebSocket("ws://" + host + "/api/v1/ws");
278 ws.onopen = function () {
279   console.log("Connection succeed!");
280   ws.send(JSON.stringify({
281     op: "ListCategories"
282   }));
283 };
284 ```
285 ### HTTP
286
287 Endpoints are at <code>http://***host***/api/v1/***endpoint***</code>. They'll be listed below for each action.
288
289 #### Testing with Curl
290
291 ##### Get Example
292
293 ```
294 curl /community/list?sort=Hot
295 ```
296
297 ##### Post Example
298
299 ```
300 curl -i -H \
301 "Content-Type: application/json" \
302 -X POST \
303 -d '{
304   "comment_id": X,
305   "post_id": X,
306   "score": X,
307   "auth": "..."
308 }' \
309 /comment/like
310 ```
311
312 ## Rate limits
313
314 - 1 per hour for signups and community creation.
315 - 1 per 10 minutes for post creation.
316 - 30 actions per minute for post voting and comment creation.
317 - Everything else is not rate-limited.
318
319 ## Errors
320 ```rust
321 {
322   op: String,
323   message: String,
324 }
325 ```
326
327 ## API documentation
328
329 ### Sort Types
330
331 These go wherever there is a `sort` field. The available sort types are:
332
333 - `Hot` - the hottest posts/communities, depending on votes, views, comments and publish date
334 - `New` - the newest posts/communities
335 - `TopDay` - the most upvoted posts/communities of the current day.
336 - `TopWeek` - the most upvoted posts/communities of the current week.
337 - `TopMonth` - the most upvoted posts/communities of the current month.
338 - `TopYear` - the most upvoted posts/communities of the current year.
339 - `TopAll` - the most upvoted posts/communities on the current instance.
340
341 ### Undoing actions
342
343 Whenever you see a `deleted: bool`, `removed: bool`, `read: bool`, `locked: bool`, etc, you can undo this action by sending `false`.
344
345 ### Websocket vs HTTP
346
347 - Below are the websocket JSON requests / responses. For HTTP, ignore all fields except those inside `data`.
348 - For example, an http login will be a `POST` `{username_or_email: X, password: X}`
349
350 ### User / Authentication / Admin actions
351
352 #### Login
353
354 The `jwt` string should be stored and used anywhere `auth` is called for.
355
356 ##### Request
357 ```rust
358 {
359   op: "Login",
360   data: {
361     username_or_email: String,
362     password: String
363   }
364 }
365 ```
366 ##### Response
367 ```rust
368 {
369   op: "Login",
370   data: {
371     jwt: String,
372   }
373 }
374 ```
375
376 ##### HTTP
377
378 `POST /user/login`
379
380 #### Register
381
382 Only the first user will be able to be the admin.
383
384 ##### Request
385 ```rust
386 {
387   op: "Register",
388   data: {
389     username: String,
390     email: Option<String>,
391     password: String,
392     password_verify: String,
393     admin: bool
394   }
395 }
396 ```
397 ##### Response
398 ```rust
399 {
400   op: "Register",
401   data: {
402     jwt: String,
403   }
404 }
405 ```
406
407 ##### HTTP
408
409 `POST /user/register`
410
411 #### Get User Details
412 ##### Request
413 ```rust
414 {
415   op: "GetUserDetails",
416   data: {
417     user_id: Option<i32>,
418     username: Option<String>,
419     sort: String,
420     page: Option<i64>,
421     limit: Option<i64>,
422     community_id: Option<i32>,
423     saved_only: bool,
424     auth: Option<String>,
425   }
426 }
427 ```
428 ##### Response
429 ```rust
430 {
431   op: "GetUserDetails",
432   data: {
433     user: UserView,
434     follows: Vec<CommunityFollowerView>,
435     moderates: Vec<CommunityModeratorView>,
436     comments: Vec<CommentView>,
437     posts: Vec<PostView>,
438   }
439 }
440 ```
441 ##### HTTP
442
443 `GET /user`
444
445 #### Save User Settings
446 ##### Request
447 ```rust
448 {
449   op: "SaveUserSettings",
450   data: {
451     show_nsfw: bool,
452     theme: String, // Default 'darkly'
453     default_sort_type: i16, // The Sort types from above, zero indexed as a number
454     default_listing_type: i16, // Post listing types are `All, Subscribed, Community`
455     auth: String
456   }
457 }
458 ```
459 ##### Response
460 ```rust
461 {
462   op: "SaveUserSettings",
463   data: {
464     jwt: String
465   }
466 }
467 ```
468 ##### HTTP
469
470 `PUT /save_user_settings`
471
472 #### Get Replies / Inbox
473 ##### Request
474 ```rust
475 {
476   op: "GetReplies",
477   data: {
478     sort: String,
479     page: Option<i64>,
480     limit: Option<i64>,
481     unread_only: bool,
482     auth: String
483   }
484 }
485 ```
486 ##### Response
487 ```rust
488 {
489   op: "GetReplies",
490   data: {
491     replies: Vec<ReplyView>,
492   }
493 }
494 ```
495 ##### HTTP
496
497 `GET /user/replies`
498
499
500 #### Get User Mentions
501 ##### Request
502 ```rust
503 {
504   op: "GetUserMentions",
505   data: {
506     sort: String,
507     page: Option<i64>,
508     limit: Option<i64>,
509     unread_only: bool,
510     auth: String,
511   }
512 }
513 ```
514 ##### Response
515 ```rust
516 {
517   op: "GetUserMentions",
518   data: {
519     mentions: Vec<UserMentionView>,
520   }
521 }
522 ```
523
524 ##### HTTP
525
526 `GET /user/mentions`
527
528 #### Mark User Mention as read
529
530 Only the recipient can do this.
531
532 ##### Request
533 ```rust
534 {
535   op: "MarkUserMentionAsRead",
536   data: {
537     user_mention_id: i32,
538     read: bool,
539     auth: String,
540   }
541 }
542 ```
543 ##### Response
544 ```rust
545 {
546   op: "MarkUserMentionAsRead",
547   data: {
548     mention: UserMentionView,
549   }
550 }
551 ```
552 ##### HTTP
553
554 `POST /user/mention/mark_as_read`
555
556 #### Get Private Messages
557 ##### Request
558 ```rust
559 {
560   op: "GetPrivateMessages",
561   data: {
562     unread_only: bool,
563     page: Option<i64>,
564     limit: Option<i64>,
565     auth: String,
566   }
567 }
568 ```
569 ##### Response
570 ```rust
571 {
572   op: "GetPrivateMessages",
573   data: {
574     messages: Vec<PrivateMessageView>,
575   }
576 }
577 ```
578
579 ##### HTTP
580
581 `GET /private_message/list`
582
583 #### Create Private Message
584 ##### Request
585 ```rust
586 {
587   op: "CreatePrivateMessage",
588   data: {
589     content: String,
590     recipient_id: i32,
591     auth: String,
592   }
593 }
594 ```
595 ##### Response
596 ```rust
597 {
598   op: "CreatePrivateMessage",
599   data: {
600     message: PrivateMessageView,
601   }
602 }
603 ```
604
605 ##### HTTP
606
607 `POST /private_message`
608
609 #### Edit Private Message
610 ##### Request
611 ```rust
612 {
613   op: "EditPrivateMessage",
614   data: {
615     edit_id: i32,
616     content: String,
617     auth: String,
618   }
619 }
620 ```
621 ##### Response
622 ```rust
623 {
624   op: "EditPrivateMessage",
625   data: {
626     message: PrivateMessageView,
627   }
628 }
629 ```
630
631 ##### HTTP
632
633 `PUT /private_message`
634
635 #### Delete Private Message
636 ##### Request
637 ```rust
638 {
639   op: "DeletePrivateMessage",
640   data: {
641     edit_id: i32,
642     deleted: bool,
643     auth: String,
644   }
645 }
646 ```
647 ##### Response
648 ```rust
649 {
650   op: "DeletePrivateMessage",
651   data: {
652     message: PrivateMessageView,
653   }
654 }
655 ```
656
657 ##### HTTP
658
659 `POST /private_message/delete`
660
661 #### Mark Private Message as Read
662
663 Only the recipient can do this.
664
665 ##### Request
666 ```rust
667 {
668   op: "MarkPrivateMessageAsRead",
669   data: {
670     edit_id: i32,
671     read: bool,
672     auth: String,
673   }
674 }
675 ```
676 ##### Response
677 ```rust
678 {
679   op: "MarkPrivateMessageAsRead",
680   data: {
681     message: PrivateMessageView,
682   }
683 }
684 ```
685
686 ##### HTTP
687
688 `POST /private_message/mark_as_read`
689
690 #### Mark All As Read
691
692 Marks all user replies and mentions as read.
693
694 ##### Request
695 ```rust
696 {
697   op: "MarkAllAsRead",
698   data: {
699     auth: String
700   }
701 }
702 ```
703 ##### Response
704 ```rust
705 {
706   op: "MarkAllAsRead",
707   data: {
708     replies: Vec<ReplyView>,
709   }
710 }
711 ```
712
713 ##### HTTP
714
715 `POST /user/mark_all_as_read`
716
717 #### Delete Account
718
719 *Permananently deletes your posts and comments*
720
721 ##### Request
722 ```rust
723 {
724   op: "DeleteAccount",
725   data: {
726     password: String,
727     auth: String
728   }
729 }
730 ```
731 ##### Response
732 ```rust
733 {
734   op: "DeleteAccount",
735   data: {
736     jwt: String,
737   }
738 }
739 ```
740
741 ##### HTTP
742
743 `POST /user/delete_account`
744
745 #### Add admin
746 ##### Request
747 ```rust
748 {
749   op: "AddAdmin",
750   data: {
751     user_id: i32,
752     added: bool,
753     auth: String
754   }
755 }
756 ```
757 ##### Response
758 ```rust
759 {
760   op: "AddAdmin",
761   data: {
762     admins: Vec<UserView>,
763   }
764 }
765 ```
766 ##### HTTP
767
768 `POST /admin/add`
769
770 #### Ban user
771 ##### Request
772 ```rust
773 {
774   op: "BanUser",
775   data: {
776     user_id: i32,
777     ban: bool,
778     reason: Option<String>,
779     expires: Option<i64>,
780     auth: String
781   }
782 }
783 ```
784 ##### Response
785 ```rust
786 {
787   op: "BanUser",
788   data: {
789     user: UserView,
790     banned: bool,
791   }
792 }
793 ```
794 ##### HTTP
795
796 `POST /user/ban`
797
798 ### Site
799 #### List Categories
800 ##### Request
801 ```rust
802 {
803   op: "ListCategories"
804 }
805 ```
806 ##### Response
807 ```rust
808 {
809   op: "ListCategories",
810   data: {
811     categories: Vec<Category>
812   }
813 }
814 ```
815 ##### HTTP
816
817 `GET /categories`
818
819 #### Search
820
821 Search types are `All, Comments, Posts, Communities, Users, Url`
822
823 ##### Request
824 ```rust
825 {
826   op: "Search",
827   data: {
828     q: String,
829     type_: String,
830     community_id: Option<i32>,
831     sort: String,
832     page: Option<i64>,
833     limit: Option<i64>,
834     auth?: Option<String>,
835   }
836 }
837 ```
838 ##### Response
839 ```rust
840 {
841   op: "Search",
842   data: {
843     type_: String,
844     comments: Vec<CommentView>,
845     posts: Vec<PostView>,
846     communities: Vec<CommunityView>,
847     users: Vec<UserView>,
848   }
849 }
850 ```
851 ##### HTTP
852
853 `POST /search`
854
855 #### Get Modlog
856 ##### Request
857 ```rust
858 {
859   op: "GetModlog",
860   data: {
861     mod_user_id: Option<i32>,
862     community_id: Option<i32>,
863     page: Option<i64>,
864     limit: Option<i64>,
865   }
866 }
867 ```
868 ##### Response
869 ```rust
870 {
871   op: "GetModlog",
872   data: {
873     removed_posts: Vec<ModRemovePostView>,
874     locked_posts: Vec<ModLockPostView>,
875     removed_comments: Vec<ModRemoveCommentView>,
876     removed_communities: Vec<ModRemoveCommunityView>,
877     banned_from_community: Vec<ModBanFromCommunityView>,
878     banned: Vec<ModBanView>,
879     added_to_community: Vec<ModAddCommunityView>,
880     added: Vec<ModAddView>,
881   }
882 }
883 ```
884
885 ##### HTTP
886
887 `GET /modlog`
888
889 #### Create Site
890 ##### Request
891 ```rust
892 {
893   op: "CreateSite",
894   data: {
895     name: String,
896     description: Option<String>,
897     auth: String
898   }
899 }
900 ```
901 ##### Response
902 ```rust
903 {
904   op: "CreateSite",
905     data: {
906     site: SiteView,
907   }
908 }
909 ```
910
911 ##### HTTP
912
913 `POST /site`
914
915 #### Edit Site
916 ##### Request
917 ```rust
918 {
919   op: "EditSite",
920   data: {
921     name: String,
922     description: Option<String>,
923     auth: String
924   }
925 }
926 ```
927 ##### Response
928 ```rust
929 {
930   op: "EditSite",
931   data: {
932     site: SiteView,
933   }
934 }
935 ```
936 ##### HTTP
937
938 `PUT /site`
939
940 #### Get Site
941 ##### Request
942 ```rust
943 {
944   op: "GetSite"
945   data: {
946     auth: Option<String>,
947   }
948
949 }
950 ```
951 ##### Response
952 ```rust
953 {
954   op: "GetSite",
955   data: {
956     site: Option<SiteView>,
957     admins: Vec<UserView>,
958     banned: Vec<UserView>,
959     online: usize, // This is currently broken
960     version: String,
961     my_user: Option<User_>, // Gives back your user and settings if logged in
962   }
963 }
964 ```
965 ##### HTTP
966
967 `GET /site`
968
969 #### Transfer Site
970 ##### Request
971 ```rust
972 {
973   op: "TransferSite",
974   data: {
975     user_id: i32,
976     auth: String
977   }
978 }
979 ```
980 ##### Response
981 ```rust
982 {
983   op: "TransferSite",
984   data: {
985     site: Option<SiteView>,
986     admins: Vec<UserView>,
987     banned: Vec<UserView>,
988   }
989 }
990 ```
991 ##### HTTP
992
993 `POST /site/transfer`
994
995 #### Get Site Config
996 ##### Request
997 ```rust
998 {
999   op: "GetSiteConfig",
1000   data: {
1001     auth: String
1002   }
1003 }
1004 ```
1005 ##### Response
1006 ```rust
1007 {
1008   op: "GetSiteConfig",
1009   data: {
1010     config_hjson: String,
1011   }
1012 }
1013 ```
1014 ##### HTTP
1015
1016 `GET /site/config`
1017
1018 #### Save Site Config
1019 ##### Request
1020 ```rust
1021 {
1022   op: "SaveSiteConfig",
1023   data: {
1024     config_hjson: String,
1025     auth: String
1026   }
1027 }
1028 ```
1029 ##### Response
1030 ```rust
1031 {
1032   op: "SaveSiteConfig",
1033   data: {
1034     config_hjson: String,
1035   }
1036 }
1037 ```
1038 ##### HTTP
1039
1040 `PUT /site/config`
1041
1042 ### Community
1043 #### Get Community
1044 ##### Request
1045 ```rust
1046 {
1047   op: "GetCommunity",
1048   data: {
1049     id: Option<i32>,
1050     name: Option<String>,
1051     auth: Option<String>
1052   }
1053 }
1054 ```
1055 ##### Response
1056 ```rust
1057 {
1058   op: "GetCommunity",
1059   data: {
1060     community: CommunityView,
1061     moderators: Vec<CommunityModeratorView>,
1062   }
1063 }
1064 ```
1065 ##### HTTP
1066
1067 `GET /community`
1068
1069 #### Create Community
1070 ##### Request
1071 ```rust
1072 {
1073   op: "CreateCommunity",
1074   data: {
1075     name: String,
1076     title: String,
1077     description: Option<String>,
1078     category_id: i32 ,
1079     auth: String
1080   }
1081 }
1082 ```
1083 ##### Response
1084 ```rust
1085 {
1086   op: "CreateCommunity",
1087   data: {
1088     community: CommunityView
1089   }
1090 }
1091 ```
1092 ##### HTTP
1093
1094 `POST /community`
1095
1096 #### List Communities
1097 ##### Request
1098 ```rust
1099 {
1100   op: "ListCommunities",
1101   data: {
1102     sort: String,
1103     page: Option<i64>,
1104     limit: Option<i64>,
1105     auth: Option<String>
1106   }
1107 }
1108 ```
1109 ##### Response
1110 ```rust
1111 {
1112   op: "ListCommunities",
1113   data: {
1114     communities: Vec<CommunityView>
1115   }
1116 }
1117 ```
1118 ##### HTTP
1119
1120 `GET /community/list`
1121
1122 #### Ban from Community
1123 ##### Request
1124 ```rust
1125 {
1126   op: "BanFromCommunity",
1127   data: {
1128     community_id: i32,
1129     user_id: i32,
1130     ban: bool,
1131     reason: Option<String>,
1132     expires: Option<i64>,
1133     auth: String
1134   }
1135 }
1136 ```
1137 ##### Response
1138 ```rust
1139 {
1140   op: "BanFromCommunity",
1141   data: {
1142     user: UserView,
1143     banned: bool,
1144   }
1145 }
1146 ```
1147 ##### HTTP
1148
1149 `POST /community/ban_user`
1150
1151 #### Add Mod to Community
1152 ##### Request
1153 ```rust
1154 {
1155   op: "AddModToCommunity",
1156   data: {
1157     community_id: i32,
1158     user_id: i32,
1159     added: bool,
1160     auth: String
1161   }
1162 }
1163 ```
1164 ##### Response
1165 ```rust
1166 {
1167   op: "AddModToCommunity",
1168   data: {
1169     moderators: Vec<CommunityModeratorView>,
1170   }
1171 }
1172 ```
1173 ##### HTTP
1174
1175 `POST /community/mod`
1176
1177 #### Edit Community
1178 Only mods can edit a community.
1179
1180 ##### Request
1181 ```rust
1182 {
1183   op: "EditCommunity",
1184   data: {
1185     edit_id: i32,
1186     title: String,
1187     description: Option<String>,
1188     category_id: i32,
1189     auth: String
1190   }
1191 }
1192 ```
1193 ##### Response
1194 ```rust
1195 {
1196   op: "EditCommunity",
1197   data: {
1198     community: CommunityView
1199   }
1200 }
1201 ```
1202 ##### HTTP
1203
1204 `PUT /community`
1205
1206 #### Delete Community
1207 Only a creator can delete a community
1208
1209 ##### Request
1210 ```rust
1211 {
1212   op: "DeleteCommunity",
1213   data: {
1214     edit_id: i32,
1215     deleted: bool,
1216     auth: String,
1217   }
1218 }
1219 ```
1220 ##### Response
1221 ```rust
1222 {
1223   op: "DeleteCommunity",
1224   data: {
1225     community: CommunityView
1226   }
1227 }
1228 ```
1229 ##### HTTP
1230
1231 `POST /community/delete`
1232
1233 #### Remove Community
1234 Only admins can remove a community.
1235
1236 ##### Request
1237 ```rust
1238 {
1239   op: "RemoveCommunity",
1240   data: {
1241     edit_id: i32,
1242     removed: bool,
1243     reason: Option<String>,
1244     expires: Option<i64>,
1245     auth: String,
1246   }
1247 }
1248 ```
1249 ##### Response
1250 ```rust
1251 {
1252   op: "RemoveCommunity",
1253   data: {
1254     community: CommunityView
1255   }
1256 }
1257 ```
1258 ##### HTTP
1259
1260 `POST /community/remove`
1261
1262 #### Follow Community
1263 ##### Request
1264 ```rust
1265 {
1266   op: "FollowCommunity",
1267   data: {
1268     community_id: i32,
1269     follow: bool,
1270     auth: String
1271   }
1272 }
1273 ```
1274 ##### Response
1275 ```rust
1276 {
1277   op: "FollowCommunity",
1278   data: {
1279     community: CommunityView
1280   }
1281 }
1282 ```
1283 ##### HTTP
1284
1285 `POST /community/follow`
1286
1287 #### Get Followed Communities
1288 ##### Request
1289 ```rust
1290 {
1291   op: "GetFollowedCommunities",
1292   data: {
1293     auth: String
1294   }
1295 }
1296 ```
1297 ##### Response
1298 ```rust
1299 {
1300   op: "GetFollowedCommunities",
1301   data: {
1302     communities: Vec<CommunityFollowerView>
1303   }
1304 }
1305 ```
1306 ##### HTTP
1307
1308 `GET /user/followed_communities`
1309
1310 #### Transfer Community
1311 ##### Request
1312 ```rust
1313 {
1314   op: "TransferCommunity",
1315   data: {
1316     community_id: i32,
1317     user_id: i32,
1318     auth: String
1319   }
1320 }
1321 ```
1322 ##### Response
1323 ```rust
1324 {
1325   op: "TransferCommunity",
1326   data: {
1327     community: CommunityView,
1328     moderators: Vec<CommunityModeratorView>,
1329     admins: Vec<UserView>,
1330   }
1331 }
1332 ```
1333 ##### HTTP
1334
1335 `POST /community/transfer`
1336
1337 ### Post
1338 #### Create Post
1339 ##### Request
1340 ```rust
1341 {
1342   op: "CreatePost",
1343   data: {
1344     name: String,
1345     url: Option<String>,
1346     body: Option<String>,
1347     nsfw: bool,
1348     community_id: i32,
1349     auth: String,
1350   }
1351 }
1352 ```
1353 ##### Response
1354 ```rust
1355 {
1356   op: "CreatePost",
1357   data: {
1358     post: PostView
1359   }
1360 }
1361 ```
1362 ##### HTTP
1363
1364 `POST /post`
1365
1366 #### Get Post
1367 ##### Request
1368 ```rust
1369 {
1370   op: "GetPost",
1371   data: {
1372     id: i32,
1373     auth: Option<String>
1374   }
1375 }
1376 ```
1377 ##### Response
1378 ```rust
1379 {
1380   op: "GetPost",
1381   data: {
1382     post: PostView,
1383     comments: Vec<CommentView>,
1384     community: CommunityView,
1385     moderators: Vec<CommunityModeratorView>,
1386   }
1387 }
1388 ```
1389 ##### HTTP
1390
1391 `GET /post`
1392
1393 #### Get Posts
1394
1395 Post listing types are `All, Subscribed, Community`
1396
1397 ##### Request
1398 ```rust
1399 {
1400   op: "GetPosts",
1401   data: {
1402     type_: String,
1403     sort: String,
1404     page: Option<i64>,
1405     limit: Option<i64>,
1406     community_id: Option<i32>,
1407     community_name: Option<String>,
1408     auth: Option<String>
1409   }
1410 }
1411 ```
1412 ##### Response
1413 ```rust
1414 {
1415   op: "GetPosts",
1416   data: {
1417     posts: Vec<PostView>,
1418   }
1419 }
1420 ```
1421 ##### HTTP
1422
1423 `GET /post/list`
1424
1425 #### Create Post Like
1426
1427 `score` can be 0, -1, or 1
1428
1429 ##### Request
1430 ```rust
1431 {
1432   op: "CreatePostLike",
1433   data: {
1434     post_id: i32,
1435     score: i16,
1436     auth: String
1437   }
1438 }
1439 ```
1440 ##### Response
1441 ```rust
1442 {
1443   op: "CreatePostLike",
1444   data: {
1445     post: PostView
1446   }
1447 }
1448 ```
1449 ##### HTTP
1450
1451 `POST /post/like`
1452
1453 #### Edit Post
1454 ##### Request
1455 ```rust
1456 {
1457   op: "EditPost",
1458   data: {
1459     edit_id: i32,
1460     name: String,
1461     url: Option<String>,
1462     body: Option<String>,
1463     nsfw: bool,
1464     auth: String,
1465   }
1466 }
1467 ```
1468 ##### Response
1469 ```rust
1470 {
1471   op: "EditPost",
1472   data: {
1473     post: PostView
1474   }
1475 }
1476 ```
1477
1478 ##### HTTP
1479
1480 `PUT /post`
1481
1482 #### Delete Post
1483 ##### Request
1484 ```rust
1485 {
1486   op: "DeletePost",
1487   data: {
1488     edit_id: i32,
1489     deleted: bool,
1490     auth: String,
1491   }
1492 }
1493 ```
1494 ##### Response
1495 ```rust
1496 {
1497   op: "DeletePost",
1498   data: {
1499     post: PostView
1500   }
1501 }
1502 ```
1503
1504 ##### HTTP
1505
1506 `POST /post/delete`
1507
1508 #### Remove Post
1509
1510 Only admins and mods can remove a post.
1511
1512 ##### Request
1513 ```rust
1514 {
1515   op: "RemovePost",
1516   data: {
1517     edit_id: i32,
1518     removed: bool,
1519     reason: Option<String>,
1520     auth: String,
1521   }
1522 }
1523 ```
1524 ##### Response
1525 ```rust
1526 {
1527   op: "RemovePost",
1528   data: {
1529     post: PostView
1530   }
1531 }
1532 ```
1533
1534 ##### HTTP
1535
1536 `POST /post/remove`
1537
1538 #### Lock Post
1539
1540 Only admins and mods can lock a post.
1541
1542 ##### Request
1543 ```rust
1544 {
1545   op: "LockPost",
1546   data: {
1547     edit_id: i32,
1548     locked: bool,
1549     auth: String,
1550   }
1551 }
1552 ```
1553 ##### Response
1554 ```rust
1555 {
1556   op: "LockPost",
1557   data: {
1558     post: PostView
1559   }
1560 }
1561 ```
1562
1563 ##### HTTP
1564
1565 `POST /post/lock`
1566
1567 #### Sticky Post
1568
1569 Only admins and mods can sticky a post.
1570
1571 ##### Request
1572 ```rust
1573 {
1574   op: "StickyPost",
1575   data: {
1576     edit_id: i32,
1577     stickied: bool,
1578     auth: String,
1579   }
1580 }
1581 ```
1582 ##### Response
1583 ```rust
1584 {
1585   op: "StickyPost",
1586   data: {
1587     post: PostView
1588   }
1589 }
1590 ```
1591
1592 ##### HTTP
1593
1594 `POST /post/sticky`
1595
1596 #### Save Post
1597 ##### Request
1598 ```rust
1599 {
1600   op: "SavePost",
1601   data: {
1602     post_id: i32,
1603     save: bool,
1604     auth: String
1605   }
1606 }
1607 ```
1608 ##### Response
1609 ```rust
1610 {
1611   op: "SavePost",
1612   data: {
1613     post: PostView
1614   }
1615 }
1616 ```
1617 ##### HTTP
1618
1619 `POST /post/save`
1620
1621 ### Comment
1622 #### Create Comment
1623 ##### Request
1624 ```rust
1625 {
1626   op: "CreateComment",
1627   data: {
1628     content: String,
1629     parent_id: Option<i32>,
1630     post_id: i32,
1631     form_id: Option<String>, // An optional form id, so you know which message came back
1632     auth: String
1633   }
1634 }
1635 ```
1636 ##### Response
1637 ```rust
1638 {
1639   op: "CreateComment",
1640   data: {
1641     comment: CommentView
1642   }
1643 }
1644 ```
1645
1646 ##### HTTP
1647
1648 `POST /comment`
1649
1650 #### Edit Comment
1651
1652 Only the creator can edit the comment.
1653
1654 ##### Request
1655 ```rust
1656 {
1657   op: "EditComment",
1658   data: {
1659     content: String,
1660     edit_id: i32,
1661     form_id: Option<String>,
1662     auth: String,
1663   }
1664 }
1665 ```
1666 ##### Response
1667 ```rust
1668 {
1669   op: "EditComment",
1670   data: {
1671     comment: CommentView
1672   }
1673 }
1674 ```
1675 ##### HTTP
1676
1677 `PUT /comment`
1678
1679 #### Delete Comment
1680
1681 Only the creator can delete the comment.
1682
1683 ##### Request
1684 ```rust
1685 {
1686   op: "DeleteComment",
1687   data: {
1688     edit_id: i32,
1689     deleted: bool,
1690     auth: String,
1691   }
1692 }
1693 ```
1694 ##### Response
1695 ```rust
1696 {
1697   op: "DeleteComment",
1698   data: {
1699     comment: CommentView
1700   }
1701 }
1702 ```
1703 ##### HTTP
1704
1705 `POST /comment/delete`
1706
1707
1708 #### Remove Comment
1709
1710 Only a mod or admin can remove the comment.
1711
1712 ##### Request
1713 ```rust
1714 {
1715   op: "RemoveComment",
1716   data: {
1717     edit_id: i32,
1718     removed: bool,
1719     reason: Option<String>,
1720     auth: String,
1721   }
1722 }
1723 ```
1724 ##### Response
1725 ```rust
1726 {
1727   op: "RemoveComment",
1728   data: {
1729     comment: CommentView
1730   }
1731 }
1732 ```
1733 ##### HTTP
1734
1735 `POST /comment/remove`
1736
1737 #### Mark Comment as Read
1738
1739 Only the recipient can do this.
1740
1741 ##### Request
1742 ```rust
1743 {
1744   op: "MarkCommentAsRead",
1745   data: {
1746     edit_id: i32,
1747     read: bool,
1748     auth: String,
1749   }
1750 }
1751 ```
1752 ##### Response
1753 ```rust
1754 {
1755   op: "MarkCommentAsRead",
1756   data: {
1757     comment: CommentView
1758   }
1759 }
1760 ```
1761 ##### HTTP
1762
1763 `POST /comment/mark_as_read`
1764
1765 #### Save Comment
1766 ##### Request
1767 ```rust
1768 {
1769   op: "SaveComment",
1770   data: {
1771     comment_id: i32,
1772     save: bool,
1773     auth: String
1774   }
1775 }
1776 ```
1777 ##### Response
1778 ```rust
1779 {
1780   op: "SaveComment",
1781   data: {
1782     comment: CommentView
1783   }
1784 }
1785 ```
1786 ##### HTTP
1787
1788 `POST /comment/save`
1789
1790 #### Create Comment Like
1791
1792 `score` can be 0, -1, or 1
1793
1794 ##### Request
1795 ```rust
1796 {
1797   op: "CreateCommentLike",
1798   data: {
1799     comment_id: i32,
1800     score: i16,
1801     auth: String
1802   }
1803 }
1804 ```
1805 ##### Response
1806 ```rust
1807 {
1808   op: "CreateCommentLike",
1809   data: {
1810     comment: CommentView
1811   }
1812 }
1813 ```
1814 ##### HTTP
1815
1816 `POST /comment/like`
1817
1818 ### RSS / Atom feeds
1819
1820 #### All
1821
1822 `/feeds/all.xml?sort=Hot`
1823
1824 #### Community
1825
1826 `/feeds/c/community-name.xml?sort=Hot`
1827
1828 #### User
1829
1830 `/feeds/u/user-name.xml?sort=Hot`
1831