Introduction
This is the API documentation for open source imageboard jschan.
- Golang SDK (Official, work in progress)
- TypeScript SDK, Typings (Unofficial)
In the data examples, arrays can contain more than one item however only one is included to reduce the size of this document.
In data parameters, note that data is always submitted as a strings, that is how urlencoded/multipart forms work. There is no concept of "types". "number" simply means a string only including numbers. For "boolean", any value with length > 0 = true, 0 length or missing = false.
Public Endpoints
Board list
curl "https://fatchan.org/boards.json"
ctx := context.Background()
client := jschan.NewClient("https://fatchan.org")
getBoardsPublicOptions := &jschan.GetBoardsPublicOptions{
Search: "tech",
}
boards, err := client.GetBoardsPublic(ctx, getBoardsPublicOptions)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%+v", boards)
The above command returns JSON structured like this:
{
"boards": [
{
"_id": "61a45ea2c5f3b57f31789cfc",
"uri": "a",
"sequence_value": 709261,
"ips": 109,
"pph": 25,
"webring": true
"path": "https://smuglo.li/a",
"siteName": "Smug",
"lastPostTimestamp": {
"text": "12 minutes ago",
"color": "#14d900"
},
"settings": {
"sfw": false,
"name": "Anime & Manga",
"description": "Stay away from 3DPD"
},
"tags": [
"anime",
"manga"
]
},
{
"_id": "b",
"sequence_value": 320,
"ips": 4,
"pph": 0,
"ppd": 5,
"webring": false
"lastPostTimestamp": {
"text": "1 hour ago",
"color": "#72d900"
},
"settings": {
"name": "Random",
"description": "Anything and everything",
"sfw": false,
"unlistedLocal": false
},
"tags": [
"random",
"b",
"rand",
"anything",
"everything"
],
},
],
"page": 1,
"maxPage": 1
}
Returns a list of boards, max 30 per page. Unlisted boards are not included in search results. Also return the current page and maximum page with the current search and sites parameters.
HTTP Request
GET https://fatchan.org/boards.json
Query Parameters
Parameter | Default | Description |
---|---|---|
search | A string to search by board name and tags, including prefix matches. | |
sort | popularity |
popularity sorts by a compound of (ips, pph, sequence_value), activity sorts by lastPostTimestamp. |
direction | desc |
desc or asc for descending or ascending sort order respectively. |
local_first | false |
If true , put local sites grouped before webring sites. Sort and direction for local and webring sites will be independent. |
sites | Sites to include by siteName, can be repeated to include multiple sites. Blank includes all sites. | |
page | Page number. 30 per page. Blank is first page. Page numbering starts at 1. Included in all responses is maxPage . |
Overboard index
curl "https://fatchan.org/overboard.json"
ctx := context.Background()
client := jschan.NewClient("https://fatchan.org")
overboardOptions := &jschan.GetOverboardOptions{
IncludeDefault: true,
}
overboard, err := client.GetOverboardIndex(ctx, overboardOptions)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%+v", overboard.Threads)
The above command returns JSON structured like this:
{
"threads": [
{
"_id": "619b5c90de842499502c366c",
"date": "2021-11-22T09:02:08.852Z",
"u": 1637571728852,
"name": "Anon",
"country": null,
"board": "b",
"tripcode": null,
"capcode": null,
"subject": "My music",
"message": null,
"messagehash": null,
"nomarkup": null,
"thread": null,
"email": null,
"spoiler": false,
"banmessage": null,
"userId": null,
"files": [
{
"filename": "a631c506f8884d263a3cf79023399504d600b0ab3219b515ac1e658d746f5d38.mp4",
"spoiler": null,
"hash": "a631c506f8884d263a3cf79023399504d600b0ab3219b515ac1e658d746f5d38",
"originalFilename": "the matrixx - black moon.mp4",
"mimetype": "video/mp4",
"size": 17745211,
"extension": ".mp4",
"sizeString": "16.9MB",
"duration": 191.379,
"durationString": "03:11",
"thumbextension": ".jpg",
"geometry": {
"width": 640,
"height": 368,
"thumbwidth": 250,
"thumbheight": 143
},
"geometryString": "640x368",
"hasThumb": true
}
],
"quotes": [],
"crossquotes": [],
"backlinks": [],
"replyposts": 3,
"replyfiles": 7,
"sticky": 0,
"locked": 0,
"bumplocked": 0,
"cyclic": 0,
"bumped": "2021-11-29T03:54:32.232Z",
"postId": 309,
"replies": [
{
"_id": "619b832b009b4a926fb37f36",
"date": "2021-11-22T11:46:51.776Z",
"u": 1637581611776,
"name": "Anon",
"country": null,
"board": "b",
"tripcode": null,
"capcode": null,
"subject": null,
"message": "fuck dude those russians left as fast as they came",
"messagehash": "NNRY6z0VURq58lfsJ80CXqSHR/fvtokjVmFT2lE5IkM=",
"nomarkup": "fuck dude those russians left as fast as they came",
"thread": 309,
"email": null,
"spoiler": false,
"banmessage": null,
"userId": null,
"files": [
{
"filename": "421049b5beedb751c05be7f53f3a4bb781b8f03cd8fd6888293918deea9a9f64.jpg",
"spoiler": null,
"hash": "421049b5beedb751c05be7f53f3a4bb781b8f03cd8fd6888293918deea9a9f64",
"originalFilename": "cover.jpg",
"mimetype": "image/jpeg",
"size": 1214658,
"extension": ".jpg",
"sizeString": "1.2MB",
"thumbextension": ".jpg",
"geometry": {
"width": 1403,
"height": 1400,
"thumbwidth": 250,
"thumbheight": 249
},
"geometryString": "1403x1400",
"hasThumb": true
}
],
"quotes": [],
"crossquotes": [],
"backlinks": [],
"postId": 310
}
]
}
]
}
Returns a list of threads with preview replies from multiple boards. Similar to board index pages.
HTTP Request
GET https://fatchan.org/overboard.json
Query Parameters
Parameter | Default | Description |
---|---|---|
include_default | true |
Whether to include boards that are publicly listed and by default appear on the overboard. If not true and the add_boards parameter is empty, this will be ignored and default to true (otherwise you are asking for an overboard view of no boards). |
add | Additional boards to fetch threads from. Can be repeated for multiple boards. | |
rem | Boards to remove from the default board list if include_detault is true. Can be repeated for multiple boards. |
Overboard catalog
curl "https://fatchan.org/catalog.json"
ctx := context.Background()
client := jschan.NewClient("https://fatchan.org")
overboardOptions := &jschan.GetOverboardOptions{
IncludeDefault: true,
}
overboard, err := client.GetOverboardCatalog(ctx, overboardOptions)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%+v", overboard.Threads)
The above command returns JSON structured like this:
{
"threads": [
{
"_id": "619b5c90de842499502c366c",
"date": "2021-11-22T09:02:08.852Z",
"u": 1637571728852,
"name": "Anon",
"country": null,
"board": "b",
"tripcode": null,
"capcode": null,
"subject": "My music",
"message": null,
"messagehash": null,
"nomarkup": null,
"thread": null,
"email": null,
"spoiler": false,
"banmessage": null,
"userId": null,
"files": [
{
"filename": "a631c506f8884d263a3cf79023399504d600b0ab3219b515ac1e658d746f5d38.mp4",
"spoiler": null,
"hash": "a631c506f8884d263a3cf79023399504d600b0ab3219b515ac1e658d746f5d38",
"originalFilename": "the matrixx - black moon.mp4",
"mimetype": "video/mp4",
"size": 17745211,
"extension": ".mp4",
"sizeString": "16.9MB",
"duration": 191.379,
"durationString": "03:11",
"thumbextension": ".jpg",
"geometry": {
"width": 640,
"height": 368,
"thumbwidth": 250,
"thumbheight": 143
},
"geometryString": "640x368",
"hasThumb": true
}
],
"quotes": [],
"crossquotes": [],
"backlinks": [],
"replyposts": 3,
"replyfiles": 7,
"sticky": 0,
"locked": 0,
"bumplocked": 0,
"cyclic": 0,
"bumped": "2021-11-29T03:54:32.232Z",
"postId": 309
},
{
"_id": "60aabfd6fc57a0112f5dbdc4",
"date": "2021-05-23T20:49:26.918Z",
"u": 1621802966918,
"name": "名無し",
"country": null,
"board": "lain",
"tripcode": null,
"capcode": null,
"subject": "lain Fanart thread",
"message": null,
"messagehash": null,
"nomarkup": null,
"thread": null,
"email": null,
"spoiler": false,
"banmessage": null,
"userId": null,
"files": [
{
"spoiler": null,
"hash": "10e24a1eef06d36d29a30f60e4616ef8cea9050c8f1e13b80af75b01687ef1fa",
"filename": "10e24a1eef06d36d29a30f60e4616ef8cea9050c8f1e13b80af75b01687ef1fa.jpg",
"originalFilename": "10e24a1eef06d36d29a30f60e4616ef8cea9050c8f1e13b80af75b01687ef1fa.jpg",
"mimetype": "image/jpeg",
"size": 259561,
"extension": ".jpg",
"sizeString": "253.5KB",
"thumbextension": ".jpg",
"geometry": {
"width": 1024,
"height": 768,
"thumbwidth": 250,
"thumbheight": 187
},
"geometryString": "1024x768",
"hasThumb": true
}
],
"quotes": [],
"crossquotes": [],
"backlinks": [],
"replyposts": 42,
"replyfiles": 119,
"sticky": 0,
"locked": 0,
"bumplocked": 0,
"cyclic": 0,
"bumped": "2021-11-28T18:57:37.215Z",
"postId": 362
}
]
}
Returns a list of threads without replies from multiple boards. Similar to board catalog pages.
HTTP Request
GET https://fatchan.org/catalog.json
Query Parameters
Parameter | Default | Description |
---|---|---|
include_default | true |
Whether to include boards that are publicly listed and by default appear on the overboard. If not true and the add_boards parameter is empty, this will be ignored and default to true (otherwise you are asking for an overboard view of no boards). |
add | Additional boards to fetch threads from. Can be repeated for multiple boards. | |
rem | Boards to remove from the default board list if include_detault is true. Can be repeated for multiple boards. |
Thread
curl "https://fatchan.org/t/thread/1329.json"
ctx := context.Background()
client := jschan.NewClient("https://fatchan.org")
getThreadOptions := &jschan.GetThreadOptions{
Board: "t",
ThreadId: 1329,
}
thread, err := client.GetThread(ctx, getThreadOptions)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%+v", thread)
The above command returns JSON structured like this:
{
"_id": "614de00fdd671464b69b6fe0",
"date": "2021-09-24T14:26:23.861Z",
"u": 1632493583861,
"name": "Anon",
"country": {
"code": "TOR",
"name": "Tor Hidden Service"
},
"board": "t",
"tripcode": null,
"capcode": null,
"subject": "Login and Board Abandonment",
"message": "Tom,\r\nWhat are the criteria for a board becoming available for claim? My board hardly gets any traffic, so I do not often log in, but I still monitor it closely. Does this put it at risk of being given away or deleted? How often should one log in to maintain ownership of his board?\r\nThank you.",
"messagehash": "s5Jm+bRGPlsMb78ROCTwEg0H7fAAtAhBlhd+yvdwbhE=",
"nomarkup": "Tom,\r\nWhat are the criteria for a board becoming available for claim? My board hardly gets any traffic, so I do not often log in, but I still monitor it closely. Does this put it at risk of being given away or deleted? How often should one log in to maintain ownership of his board?\r\nThank you.",
"thread": null,
"email": "",
"spoiler": false,
"banmessage": null,
"userId": "65fedc",
"files": [],
"quotes": [],
"crossquotes": [],
"backlinks": [
{
"_id": "614dfa85dd671464b69b6fe2",
"postId": 1330
}
],
"replyposts": 5,
"replyfiles": 0,
"sticky": 0,
"locked": 0,
"bumplocked": 1,
"cyclic": 0,
"bumped": "2021-10-03T22:52:13.202Z",
"postId": 1329,
"replies": [
{
"_id": "614dfa85dd671464b69b6fe2",
"date": "2021-09-24T16:19:17.465Z",
"u": 1632500357465,
"name": "Anon",
"country": {
"code": "AU",
"name": "Australia"
},
"board": "t",
"tripcode": null,
"capcode": "## Admin",
"subject": "",
"message": "<a class=\"quote\" href=\"/t/thread/1329.html#1329\">>>1329</a> <small>(OP)</small> \r\nThere is no regular claims process, but I was considering a cleanup soon. There will be a newspost and global announcement with reasonable notice before any account deletion or board forfeiture takes place. Logging into your account in that instance would be warranted, because I can see the last activity date and will delete inactive accounts.",
"messagehash": "jviA+n4rb3tYhSq2eonkuCZYzr/frpmwsDVv2N0XQUE=",
"nomarkup": ">>1329\r\nThere is no regular claims process, but I was considering a cleanup soon. There will be a newspost and global announcement with reasonable notice before any account deletion or board forfeiture takes place. Logging into your account in that instance would be warranted, because I can see the last activity date and will delete inactive accounts.",
"thread": 1329,
"email": "",
"spoiler": false,
"banmessage": null,
"userId": "b5d092",
"files": [],
"quotes": [
{
"_id": "614de00fdd671464b69b6fe0",
"thread": 1329,
"postId": 1329
}
],
"crossquotes": [],
"backlinks": [
{
"_id": "614fb22e448d10f67a8d4dff",
"postId": 1331
},
{
"_id": "61538bd4dd671464b69b7034",
"postId": 1339
},
{
"_id": "615a341db33d7abaa5f90bb5",
"postId": 1363
}
],
"postId": 1330
}
]
]
Returns a thread with all replies.
HTTP Request
GET https://fatchan.org/{board}/thread/{threadId}.json
URL Parameters
Parameter | Description |
---|---|
board | The board URI for whatever board you want |
threadId | The thread number, which is the post number of the OP. |
Board index pages
curl "https://fatchan.org/t/index.json"
ctx := context.Background()
client := jschan.NewClient("https://fatchan.org")
getIndexOptions := &jschan.GetIndexOptions{
Board: "t",
Page: 1,
}
index, err := client.GetIndex(ctx, getIndexOptions)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%+v", index)
The above command returns JSON structured like this:
[
{
"_id": "6158e81eb33d7abaa5f90ba0",
"date": "2021-10-02T23:15:42.675Z",
"u": 1633216542675,
"name": "Anon",
"country": {
"code": "AU",
"name": "Australia"
},
"board": "t",
"tripcode": null,
"capcode": "## Admin",
"subject": "Important Links",
"message": "<span class=\"title\">Git repository & issue tracker:</span> <a rel=\"nofollow\" referrerpolicy=\"same-origin\" target=\"_blank\" href=\"https://gitgud.io/fatchan/jschan\">https://gitgud.io/fatchan/jschan</a>\nGo here to see the source code, report issues or ask relevant questions.\n\n<span class=\"title\">IRC:</span> <a rel=\"nofollow\" referrerpolicy=\"same-origin\" target=\"_blank\" href=\"https://irc-web.fatpeople.lol\">https://irc-web.fatpeople.lol</a> (irc-web.fatpeople.lol port 6697 TLS on)\nJoin IRC to chat directly with staff and other users in a realtime format.\n\n<span class=\"title\">Test board:</span> <a class=\"quote\" href=\"/test/index.html\">>>>/test/</a>\nTest things on the /test/ board rather than here or anywhere else.",
"messagehash": "tkak9s72dCSv9XkocVNwceUfmtwqaTH8gL9bzcQxwP4=",
"nomarkup": "==Git repository & issue tracker:== https://gitgud.io/fatchan/jschan\nGo here to see the source code, report issues or ask relevant questions.\n\n==IRC:== https://irc-web.fatpeople.lol (irc-web.fatpeople.lol port 6697 TLS on)\nJoin IRC to chat directly with staff and other users in a realtime format.\n\n==Test board:== >>>/test/\nTest things on the /test/ board rather than here or anywhere else.",
"thread": null,
"email": "",
"spoiler": false,
"banmessage": null,
"userId": "307203",
"files": [],
"quotes": [],
"crossquotes": [],
"backlinks": [],
"replyposts": 0,
"replyfiles": 0,
"sticky": 3,
"locked": 1,
"bumplocked": 0,
"cyclic": 0,
"bumped": "2021-10-02T23:15:42.675Z",
"postId": 1360,
"edited": {
"username": "admin",
"date": "2021-11-03T00:36:36.620Z"
},
"replies": []
},
{
"_id": "614ba0e132f471fcdd2c7139",
"date": "2021-09-22T21:32:17.737Z",
"u": 1632346337737,
"name": "Anon",
"country": {
"code": "AU",
"name": "Australia"
},
"board": "t",
"tripcode": null,
"capcode": "## Admin",
"subject": "Board Requests",
"message": "1. <a rel=\"nofollow\" referrerpolicy=\"same-origin\" target=\"_blank\" href=\"/rules.html\">Global rules</a>\r\n2. <a rel=\"nofollow\" referrerpolicy=\"same-origin\" target=\"_blank\" href=\"/register.html\">Register an account</a> \r\n3. Post in this thread, format:\r\n<span class=\"code\">''Board URI:'' /example/\r\n''Board name:'' <name of the board>\r\n''Board description:'' <25 words or less>\r\n''I want it because:'' <your pathetic excuse for wanting a board>\r\n''My registered account username is:'' <username>\r\n''I have read and understand the global rules, and acknowledge the existence of the Israeli nuclear weapons program.''\r\n</span>\r\nEnjoy.",
"messagehash": "J3Sg5W1b7iXYZQAofK+HFHvrpr8IpjOKEOMZvnMWB5I=",
"nomarkup": "1. [Global rules](/rules.html)\r\n2. [Register an account](/register.html) \r\n3. Post in this thread, format:\r\n[code]plain\r\n''Board URI:'' /example/\r\n''Board name:'' <name of the board>\r\n''Board description:'' <25 words or less>\r\n''I want it because:'' <your pathetic excuse for wanting a board>\r\n''My registered account username is:'' <username>\r\n''I have read and understand the global rules, and acknowledge the existence of the Israeli nuclear weapons program.''\r\n[/code]\r\n\r\nEnjoy.",
"thread": null,
"email": "",
"spoiler": false,
"banmessage": null,
"userId": "f63865",
"files": [],
"quotes": [],
"crossquotes": [],
"backlinks": [],
"replyposts": 1,
"replyfiles": 0,
"sticky": 2,
"locked": 0,
"bumplocked": 0,
"cyclic": 0,
"bumped": "2021-11-14T14:09:39.353Z",
"postId": 1325,
"edited": {
"username": "admin",
"date": "2021-10-05T13:18:26.680Z"
},
"replies": [
{
"_id": "619118a39ca8261cc8311609",
"date": "2021-11-14T14:09:39.353Z",
"u": 1636898979353,
"name": "Anon",
"country": {
"code": "LU",
"name": "Luxembourg"
},
"board": "t",
"tripcode": null,
"capcode": null,
"subject": "",
"message": "<span class=\"bold\">Board URI:</span> /shy/\r\n<span class=\"bold\">Board name:</span> Shy Anonymous\r\n<span class=\"bold\">Board description:</span> Доска для застенчивых одиноких людей без сети социальных связей (в том числе своего пола), друзей, тян, с отсутствующими навыками НЕФОРМАЛЬНОГО общения. Обсуждение связанных с этим проблем.\r\n<span class=\"bold\">I want it because:</span> Because I can and want\r\n<span class=\"bold\">My registered account username is:</span> anonymous1234\r\n<span class=\"bold\">I have read and understand the global rules, and acknowledge the existence of the Israeli nuclear weapons program.</span>",
"messagehash": "S3r9l9svoA/ebm4c7e9U1pOq6kW1WYsE1vc/9/BHZTg=",
"nomarkup": "''Board URI:'' /shy/\r\n''Board name:'' Shy Anonymous\r\n''Board description:'' Доска для застенчивых одиноких людей без сети социальных связей (в том числе своего пола), друзей, тян, с отсутствующими навыками НЕФОРМАЛЬНОГО общения. Обсуждение связанных с этим проблем.\r\n''I want it because:'' Because I can and want\r\n''My registered account username is:'' anonymous1234\r\n''I have read and understand the global rules, and acknowledge the existence of the Israeli nuclear weapons program.''",
"thread": 1325,
"email": "",
"spoiler": false,
"banmessage": null,
"userId": "c54e7d",
"files": [],
"quotes": [],
"crossquotes": [],
"backlinks": [],
"postId": 1391
}
]
}
]
Returns a list of threads with preview replies from a page of a board.
HTTP Request
GET https://fatchan.org/{board}/{page}.json
URL Parameters
Parameter | Description |
---|---|
board | Board URI. |
page | index for page 1, or a number for subsequent pages. |
Board catalog
curl "https://fatchan.org/t/catalog.json"
ctx := context.Background()
client := jschan.NewClient("https://fatchan.org")
getCatalogOptions := &jschan.GetCatalogOptions{
Board: "t",
}
catalog, err := client.GetCatalog(ctx, getCatalogOptions)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%+v", catalog)
The above command returns JSON structured like this:
[
{
"_id": "6158e81eb33d7abaa5f90ba0",
"date": "2021-10-02T23:15:42.675Z",
"u": 1633216542675,
"name": "Anon",
"country": {
"code": "AU",
"name": "Australia"
},
"board": "t",
"tripcode": null,
"capcode": "## Admin",
"subject": "Important Links",
"message": "<span class=\"title\">Git repository & issue tracker:</span> <a rel=\"nofollow\" referrerpolicy=\"same-origin\" target=\"_blank\" href=\"https://gitgud.io/fatchan/jschan\">https://gitgud.io/fatchan/jschan</a>\nGo here to see the source code, report issues or ask relevant questions.\n\n<span class=\"title\">IRC:</span> <a rel=\"nofollow\" referrerpolicy=\"same-origin\" target=\"_blank\" href=\"https://irc-web.fatpeople.lol\">https://irc-web.fatpeople.lol</a> (irc-web.fatpeople.lol port 6697 TLS on)\nJoin IRC to chat directly with staff and other users in a realtime format.\n\n<span class=\"title\">Test board:</span> <a class=\"quote\" href=\"/test/index.html\">>>>/test/</a>\nTest things on the /test/ board rather than here or anywhere else.",
"messagehash": "tkak9s72dCSv9XkocVNwceUfmtwqaTH8gL9bzcQxwP4=",
"nomarkup": "==Git repository & issue tracker:== https://gitgud.io/fatchan/jschan\nGo here to see the source code, report issues or ask relevant questions.\n\n==IRC:== https://irc-web.fatpeople.lol (irc-web.fatpeople.lol port 6697 TLS on)\nJoin IRC to chat directly with staff and other users in a realtime format.\n\n==Test board:== >>>/test/\nTest things on the /test/ board rather than here or anywhere else.",
"thread": null,
"email": "",
"spoiler": false,
"banmessage": null,
"userId": "307203",
"files": [],
"quotes": [],
"crossquotes": [],
"backlinks": [],
"replyposts": 0,
"replyfiles": 0,
"sticky": 3,
"locked": 1,
"bumplocked": 0,
"cyclic": 0,
"bumped": "2021-10-02T23:15:42.675Z",
"postId": 1360,
"edited": {
"username": "admin",
"date": "2021-11-03T00:36:36.620Z"
}
},
{
"_id": "614ba0e132f471fcdd2c7139",
"date": "2021-09-22T21:32:17.737Z",
"u": 1632346337737,
"name": "Anon",
"country": {
"code": "AU",
"name": "Australia"
},
"board": "t",
"tripcode": null,
"capcode": "## Admin",
"subject": "Board Requests",
"message": "1. <a rel=\"nofollow\" referrerpolicy=\"same-origin\" target=\"_blank\" href=\"/rules.html\">Global rules</a>\r\n2. <a rel=\"nofollow\" referrerpolicy=\"same-origin\" target=\"_blank\" href=\"/register.html\">Register an account</a> \r\n3. Post in this thread, format:\r\n<span class=\"code\">''Board URI:'' /example/\r\n''Board name:'' <name of the board>\r\n''Board description:'' <25 words or less>\r\n''I want it because:'' <your pathetic excuse for wanting a board>\r\n''My registered account username is:'' <username>\r\n''I have read and understand the global rules, and acknowledge the existence of the Israeli nuclear weapons program.''\r\n</span>\r\nEnjoy.",
"messagehash": "J3Sg5W1b7iXYZQAofK+HFHvrpr8IpjOKEOMZvnMWB5I=",
"nomarkup": "1. [Global rules](/rules.html)\r\n2. [Register an account](/register.html) \r\n3. Post in this thread, format:\r\n[code]plain\r\n''Board URI:'' /example/\r\n''Board name:'' <name of the board>\r\n''Board description:'' <25 words or less>\r\n''I want it because:'' <your pathetic excuse for wanting a board>\r\n''My registered account username is:'' <username>\r\n''I have read and understand the global rules, and acknowledge the existence of the Israeli nuclear weapons program.''\r\n[/code]\r\n\r\nEnjoy.",
"thread": null,
"email": "",
"spoiler": false,
"banmessage": null,
"userId": "f63865",
"files": [],
"quotes": [],
"crossquotes": [],
"backlinks": [],
"replyposts": 1,
"replyfiles": 0,
"sticky": 2,
"locked": 0,
"bumplocked": 0,
"cyclic": 0,
"bumped": "2021-11-14T14:09:39.353Z",
"postId": 1325,
"edited": {
"username": "admin",
"date": "2021-10-05T13:18:26.680Z"
}
}
]
Returns a list of all threads on a board.
HTTP Request
GET https://fatchan.org/{board}/catalog.json
URL Parameters
Parameter | Description |
---|---|
board | Board URI. |
Board log list
curl "https://fatchan.org/t/logs.json"
ctx := context.Background()
client := jschan.NewClient("https://fatchan.org")
getLogsListOptions := &jschan.GetLogsListOptions{
Board: "t",
}
logs, err := client.GetLogsList(ctx, getLogsListOptions)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%+v", logs)
The above command returns JSON structured like this:
[
{
"date": {
"year": 2022,
"month": 8,
"day": 13
},
"count": 3
},
{
"date": {
"year": 2022,
"month": 8,
"day": 12
},
"count": 1
}
]
Returns a list of objects each containing a date (day, month, year) and number of log entries on that date.
HTTP Request
GET https://fatchan.org/{board}/logs.json
URL Parameters
Parameter | Description |
---|---|
board | Board URI. |
Board log (day)
curl "https://fatchan.org/t/logs/8-12-2022.json"
ctx := context.Background()
client := jschan.NewClient("https://fatchan.org")
getLogsOptions := &jschan.GetLogsOptions{
Board: "t",
Date: models.LogDate{
Year: 2022,
Month: 12,
Day: 8,
}
}
logs, err := client.GetLogs(ctx, getLogsOptions)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%+v", logs)
The above command returns JSON structured like this:
[
{
"_id": "62f5f3d1b0ffeb3e12205fa2",
"showLinks": false,
"postLinks": [
{
"postId": 143,
"thread": 138,
"board": "t"
}
],
"actions": [
"Delete"
],
"date": "2022-08-12T06:31:45.492Z",
"showUser": false,
"message": null,
"user": null,
"board": "t"
},
{
"_id": "62f5f3c0b0ffeb3e12205fa1",
"showLinks": true,
"postLinks": [
{
"postId": 144,
"thread": 138,
"board": "t"
}
],
"actions": [
"Unlink files"
],
"date": "2022-08-12T06:31:28.084Z",
"showUser": true,
"message": null,
"user": "admin",
"board": "t"
},
{
"_id": "62f5e88038f79a03efaee40c",
"showLinks": true,
"postLinks": [
{
"postId": 138,
"thread": null,
"board": "t"
}
],
"actions": [
"Sticky"
],
"date": "2022-08-12T05:43:28.800Z",
"showUser": true,
"message": null,
"user": "admin",
"board": "t"
}
]
Returns a list of log entries for a board ona a particular date.
HTTP Request
GET https://fatchan.org/{board}/logs/{mm}-{dd}-{yyyy}.json
URL Parameters
Parameter | Description |
---|---|
board | Board URI. |
mm | Month of date to fetch log entries from, 01-12. |
dd | Day of date to fetch log entries from, 01-31. |
yyyy | Year of date to fetch log entries from, 0000-9999. |
Board custom page
curl "https://fatchan.org/t/custompage/example.json"
ctx := context.Background()
client := jschan.NewClient("https://fatchan.org")
getCustomPageOptions := &jschan.GetCustomPageOptions{
Board: "t",
CustomPage: "example",
}
custompage, err := client.GetCustomPage(ctx, getCustomPageOptions)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%+v", custompage)
The above command returns JSON structured like this:
{
"board": "t",
"page": "example",
"title": "Example custompage",
"message": {
"raw": "Hello, world!\n>12345\n''wow!''",
"markdown": "Hello, world!\n<span class=\"greentext\">>12345</span>\n<span class=\"bold\">wow!</span>"
},
"date": "2022-08-25T11:47:32.073Z",
"edited": null,
"_id": "63076154f5e68d47ddd787c4"
}
Returns the data for a board custom page.
HTTP Request
GET https://fatchan.org/{board}/custompage/{page}.json
URL Parameters
Parameter | Description |
---|---|
board | Board URI. |
name | Name of the page (same as the name property). |
Board banners
curl "https://fatchan.org/t/banners.json"
ctx := context.Background()
client := jschan.NewClient("https://fatchan.org")
getBannersOptions := &jschan.GetBannersOptions{
Board: "t",
}
banners, err := client.GetBanners(ctx, getBannersOptions)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%+v", banners)
The above command returns JSON structured like this:
[
"efdff01e8310bd76f6561ea8f34ded9bca1a6ddff067fd9f024d39aad3ebf1ae.png",
"41bcdcb558954073a45a5faac7ac38f0824108062b5d0236c5b4e891b5278553.jpg"
]
Returns a list of board banner file names. Full path of a banner is /banner/{board}/{filename}
.
HTTP Request
GET https://fatchan.org/{board}/banners.json
URL Parameters
Parameter | Description |
---|---|
board | Board URI. |
Board settings
curl "https://fatchan.org/t/settings.json"
ctx := context.Background()
client := jschan.NewClient("https://fatchan.org")
getSettingsOptions := &jschan.GetSettingsOptions{
Board: "t",
}
settings, err := client.GetBanners(ctx, getSettingsOptions)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%+v", settings)
The above command returns JSON structured like this:
{
"customPages": [
"example"
],
"announcement": {
"raw": ">lol!",
"markdown": "<span class=\"greentext\">>lol!</span>"
},
"allowedFileTypes": {
"animatedImage": true,
"image": true,
"video": true,
"audio": true,
"other": true
},
"maxFiles": 5,
"captchaMode": 0,
"forceAnon": false,
"sageOnlyEmail": false,
"customFlags": false,
"forceThreadMessage": false,
"forceThreadFile": false,
"forceThreadSubject": false,
"disableReplySubject": false,
"minThreadMessageLength": 0,
"minReplyMessageLength": 0,
"maxThreadMessageLength": 20000,
"maxReplyMessageLength": 20000,
"defaultName": "Anon"
}
Returns some publicly available board settings.
HTTP Request
GET https://fatchan.org/{board}/settings.json
URL Parameters
Parameter | Description |
---|---|
board | Board URI. |
Global settings
curl "https://fatchan.org/settings.json"
ctx := context.Background()
client := jschan.NewClient("https://fatchan.org")
settings, err := client.GetGlobalSettings(ctx)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%+v", settings)
The above command returns JSON structured like this:
{
"captchaOptions": {
"type": "text",
"grid": {
"size": 4,
"question": "Select all the odd numbers."
}
}
}
Returns some publicly available global settings.
HTTP Request
GET https://fatchan.org/settings.json
Webring
curl "https://fatchan.org/webring.json"
ctx := context.Background()
client := jschan.NewClient("https://fatchan.org")
webring, err := client.GetWebring(ctx)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%+v", webring)
The above command returns JSON structured like this:
{
"name": "fatchan",
"url": "https://fatchan.org",
"endpoint": "https://fatchan.org/webring.json",
"logo": [
"https://fatchan.org/favicon.ico"
],
"following": [
"https://anon.cafe/webring.json",
...
],
"blacklist": [],
"known": [
"https://anon.cafe/webring.json",
...
],
"boards": [
{
"uri": "t",
"title": "Meta",
"subtitle": "Fatchan Official",
"path": "https://fatchan.org/t/",
"postsPerHour": 0,
"postsPerDay": 0,
"totalPosts": 1410,
"uniqueUsers": 0,
"nsfw": false,
"tags": [
"meta",
"t",
"site",
"discussion",
"fatchan",
"/t/",
"/meta/",
"jschan"
],
"lastPostTimestamp": "2021-11-23T01:11:13.122Z"
}
]
}
Returns webring information.
The webring is a system "enabling the collaborating with other imageboards to form a decentralized webring via a standardized schema."
See here for compatible implementations:
- https://gitlab.com/Tenicu/infinityaddon-webring (For infinity-based imageboards)
- https://gitlab.com/alogware/LynxChanAddon-Webring (For Lynxchan-based imageboards)
HTTP Request
GET https://fatchan.org/webring.json
Create thread/reply
# UNDER CONSTRUCTION...
ctx := context.Background()
client := jschan.NewClient("https://fatchan.org")
makePostOptions := &jschan.MakePostOptions{
Board: "test",
Thread: 277,
Name: "Test",
Message: ">test",
Email: "sage",
PostPassword: "123",
Files: []string{"./image.png"},
}
err := client.MakePost(ctx, makePostOptions)
if err != nil {
fmt.Println(err)
return
}
Make a new thread, or reply to an existing thread.
HTTP Request
POST https://fatchan.org/forms/board/{board}/post
Parameters
Parameter | Type | Description |
---|---|---|
thread | number or null | postId of the thread this post is replying to. If null, creates a new thread. |
name | string | Name |
message | string | Message |
subject | string | Subject |
string | Email, or special values such as 'sage'. | |
postpassword | string | Post password lets users action posts e.g. delete, spoiler, remove files after posting. It's useful to let anonymous users manage their own posts without requiring an account. Users can set it manually, or if they have JavaScript enabled one is randomly generated and stored in localstorage. If the post password is left empty, the post can only be actioned by staff. Staff can also action any post without needing the post password. The ability for anonymous users to action their posts can be disabled on a per-board level. |
file | file(s) | One or more files, multipart form data. |
spoiler | array(string) | Array of sha256 hash of files to be spoilered. |
spoiler_all | boolean | Whether to spoiler all files. |
strip_filename | array(string) | Array of sha256 hash of files to have filenames stripped.. The sha256 hash will be used instead. Note: the server will still receive the original filenames before stripping. |
customflag | string or null | Name of custom flag to be used. If null, will use no flag unless the board also has geoip flags enabled, then it will use the geo flag. |
captcha | array(number) or string | See Captcha/block bypass |
signature | string | Signature output of a web3 eth personal_sign request with the content of the message parameter. Will add a signature and the recovered address to the bottom of the post. |
Post actions (delete, report, etc)
# UNDER CONSTRUCTION...
Submit actions against posts e.g. report, spoiler, delete. Supports multiple posts in a single submission. Actions against OP such as delete or move will take replies with it. This endpoint does not require a session cookie or CSRF token like the staff variants, but having valid credentials will allow staff to bypass certain restrictions such as being able to delete posts when the board settings have "user post deletion" disabled. Anonymous users can submit parameters checkedposts, delete, unlink_file, spoiler, postpassword, report, global_report, report_reason and captcha. Multiple actions can be combined e.g. delete+ban. While there are no errors for submitting incompatible actions e.g. delete+report (you cannot report and delete a post simultaneously), the server will handle them in a sensible order, with delete taking precedence.
HTTP Request
POST https://fatchan.org/forms/board/{board}/actions
Parameters
Parameter | Type | Description |
---|---|---|
checkedposts | array(number) | Array of postId 's to action against. |
delete | boolean | Delete the selected posts. |
spoiler | boolean | Spoiler all files in the selected posts. |
unlink_file | boolean | Unlink files from the selected posts. If there are other copies of the file in other posts, or the global settings do not immediately prune unlinked files, the file may remain on disk. |
postpassword | string | Post password lets users action posts e.g. delete, spoiler, remove files after posting. It's useful to let anonymous users manage their own posts without requiring an account. Users can set it manually, or if they have JavaScript enabled one is randomly generated and stored in localstorage. If the post password is left empty, the post can only be actioned by staff. Staff can also action any post without needing the post password. The ability for anonymous users to action their posts can be disabled on a per-board level. |
report | boolean | Report the selected posts to board staff. |
global_report | boolean | Report the selected posts to global staff. |
report_reason | string | Reason for reporting, if report or global_report. |
captcha | array(number) or string | See Captcha/block bypass |
HTTP Request
POST https://fatchan.org/forms/board/{board}/actions
Staff Endpoints
The following endpoints are only available when properly authenticated and if your account has permission to access the respective pages.
Board staff - create thread/reply
# UNDER CONSTRUCTION...
Make a new thread, or reply to an existing thread. Staff endpoint does not require captcha completion, but requires a CSRF token and session cookie.
HTTP Request
POST https://fatchan.org/forms/board/{board}/modpost
Parameters
Parameter | Type | Description |
---|---|---|
_csrf | string | CSRF token |
thread | number or null | postId of the thread this post is replying to. If null, creates a new thread. |
name | string | Name |
message | string | Message |
subject | string | Subject |
string | Email, or special values such as 'sage'. | |
postpassword | string | Post password lets users action posts e.g. delete, spoiler, remove files after posting. It's useful to let anonymous users manage their own posts without requiring an account. Users can set it manually, or if they have JavaScript enabled one is randomly generated and stored in localstorage. If the post password is left empty, the post can only be actioned by staff. Staff can also action any post without needing the post password. The ability for anonymous users to action their posts can be disabled on a per-board level. |
file | file(s) | One or more files, multipart form data. |
spoiler | array(string) | Array of sha256 hash of files to be spoilered. |
spoiler_all | boolean | Whether to spoiler all files. |
strip_filename | array(string) | Array of sha256 hash of files to have filenames stripped.. The sha256 hash will be used instead. Note: the server will still receive the original filenames before stripping. |
customflag | string or null | Name of custom flag to be used. If null, will use no flag unless the board also has geoip flags enabled, then it will use the geo flag. |
Board staff - post actions
# UNDER CONSTRUCTION...
Submit actions against posts e.g. report, spoiler, delete. Supports multiple posts in a single submission. Actions against OP such as delete or move will take replies with it. This endpoint requires a session cookie and CSRF token, allows staff to use additional actions, and bypass certain restrictions such as being able to delete posts when the board settings have "user post deletion" disabled. Multiple actions can be combined e.g. delete+ban. While there are no errors for submitting incompatible actions e.g. delete+report (you cannot report and delete a post simultaneously), the server will handle them in a sensible order, with delete taking precedence.
HTTP Request
POST https://fatchan.org/forms/board/{board}/modactions
Parameters
Parameter | Type | Description |
---|---|---|
_csrf | string | CSRF token |
checkedposts | array(number) | Array of postId 's to action against. |
delete | boolean | Delete the selected posts. |
spoiler | boolean | Spoiler all files in the selected posts. |
unlink_file | boolean | Unlink files from the selected posts. If there are other copies of the file in other posts, or the global settings do not immediately prune unlinked files, the file may remain on disk. |
delete_file | boolean | Forcefully delete files from the selected posts, ignoring other references or server settings for delayed file pruning. |
postpassword | string | Post password lets users action posts e.g. delete, spoiler, remove files after posting. It's useful to let anonymous users manage their own posts without requiring an account. Users can set it manually, or if they have JavaScript enabled one is randomly generated and stored in localstorage. If the post password is left empty, the post can only be actioned by staff. Staff can also action any post without needing the post password. The ability for anonymous users to action their posts can be disabled on a per-board level. |
report | boolean | Report the selected posts to board staff. |
global_report | boolean | Report the selected posts to global staff. |
report_reason | string | Reason for reporting, if report or global_report. |
ban | boolean | Ban the ips for all selected posts from the board. |
global_ban | boolean | Ban the ips for all selected posts globally. |
ban_q | boolean | Ban a small ip range, /24 for ipv4 and /64 for ipv6. |
ban_h | boolean | Ban a larger ip range, /16 for ipv4 and /48 for ipv6. |
no_appeal | boolean | Removes the ability to appeal a ban. |
preserve_post | boolean | Whether to preserve the post and show it in the ban page. If the server prunes files, the files may no longer exist. |
hide_name | boolean | Whether the username of the staff should be hidden from public modlogs. |
sticky | number | Set the sticky priority for a thread. Threads are sorted in descending order, with 0 being the default or not sticky. |
lock | boolean | Toggles if a thread is locked, so no more repies are allowed from unauthenticated users. |
bumplock | boolean | Toggles if a thread is bumplocked, so replies will no longer bump the thread. |
cyclic | boolean | Toggles if a thread is cyclic, i.e. when it reaches thread limit earlier replies are deleted and replaced by new posts instead of locking the thread. |
checkedreports | array(string) | Array of report ids, for report actions such as dismiss or report_ban. |
edit | boolean | Whether to edit the selected post. Staff only. Must have only a single checkedposts . |
ban_reason | string | Reason for banning if ban or global_ban. |
log_message | string | Message to show in modlog explaining the reason for post actions. |
ban_duration | Time format string | Time format string for how long until the ban expires. |
report_ban | boolean | Whether to ban a reporter. Must submit the checkedpost and relevant checkedreports. |
move | boolean | Whether to move selected posts to another thread. |
move_to_thread | The postId of the destination thread for moving. |
Board staff - recent posts
curl -v 'https://fatchan.org/t/manage/recent.json' \
-H 'Cookie: connect.sid=s%REDACTED;'
The above command returns JSON structured like this:
[
{
"_id": "6182b5f2013eb3d1e8313300",
"date": "2021-11-03T16:16:50.257Z",
"u": 1635956210257,
"name": "Anon",
"country": {
"code": "TOR",
"name": "Tor Hidden Service"
},
"board": "t",
"tripcode": null,
"capcode": null,
"subject": "",
"message": "<a class=\"quote\" href=\"/t/thread/1376.html#1377\">>>1377</a>\r\nOh yeah. Did you change the default from iwakura to lain? Looks good.",
"messagehash": "uD7zsFXapRsocZPJzUeroVsND9KvX4FQ0AmAl54FXxg=",
"nomarkup": ">>1377\r\nOh yeah. Did you change the default from iwakura to lain? Looks good.",
"thread": 1376,
"email": "",
"spoiler": false,
"banmessage": null,
"userId": "546403",
"ip": {
"raw": "redacted",
"cloak": "redacted"
},
"files": [],
"reports": [],
"quotes": [
{
"_id": "61820031804c0bf6d2271026",
"thread": 1376,
"postId": 1377
}
],
"crossquotes": [],
"backlinks": [
{
"_id": "6182ba0da5af18e5ee5b3f2b",
"postId": 1382
}
],
"postId": 1381
}
]
Returns a list of the most recent posts made on a specific board.
HTTP Request
GET https://fatchan.org/{board}/manage/recent.json
URL Parameters
Parameter | Type | Description |
---|---|---|
board | string | The board to fetch recent posts from. |
Query Parameters
Parameter | Default | Description |
---|---|---|
page | Page number. 30 per page. Blank is first page. Page numbering starts at 1. |
Board staff - reports
curl -v 'https://fatchan.org/t/manage/reports.json' \
-H 'Cookie: connect.sid=s%REDACTED;'
The above command returns JSON structured like this:
{
"reports": [
{
"_id": "61a06777c3ba8becf5be6303",
"date": "2021-11-26T04:49:59.832Z",
"u": 1637902199832,
"name": "Anon",
"country": {
"code": "TOR",
"name": "Tor Hidden Service"
},
"board": "test",
"tripcode": null,
"capcode": null,
"subject": "",
"message": "test",
"messagehash": "n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg=",
"nomarkup": "test",
"thread": null,
"email": "",
"spoiler": false,
"banmessage": null,
"userId": "1e22fb",
"ip": {
"raw": "redacted",
"cloak": "redacted"
},
"files": [],
"reports": [
{
"id": "61a63249a2e147d7c0f382dd",
"reason": "test",
"date": "2021-11-30T14:16:41.780Z",
"ip": {
"cloak": "redacted"
}
}
],
"quotes": [],
"crossquotes": [],
"backlinks": [],
"replyposts": 0,
"replyfiles": 0,
"sticky": 0,
"locked": 0,
"bumplocked": 0,
"cyclic": 0,
"bumped": "2021-11-26T04:49:59.832Z",
"postId": 224
}
]
}
Returns a list of posts that were reported with the board reports attached.
HTTP Request
GET https://fatchan.org/{board}/manage/reports.json
Global staff - post actions
# UNDER CONSTRUCTION...
Submit actions against posts e.g. report, spoiler, delete. Supports multiple posts in a single submission. Actions against OP such as delete or move will take replies with it. This endpoint requires a session cookie and CSRF token, allows global staff to use additional actions, and bypass restrictions. Multiple actions can be combined e.g. delete+ban. While there are no errors for submitting incompatible actions e.g. delete+report (you cannot report and delete a post simultaneously), the server will handle them in a sensible order, with delete taking precedence. Certain actions such as "move" are not present compared to the board-specific endpoints because global actions can apply to posts from multiple different boards. Global actions use posts _id (mongo id) in the globalcheckedposts array instead of postIds because global actions can apply to posts from multiple different boards and cannot just reference postIds.
HTTP Request
POST https://fatchan.org/forms/global/actions
Parameters
Parameter | Type | Description |
---|---|---|
globalcheckedposts | array(string) | Array of post _ids to action against. |
delete | boolean | Delete the selected posts. |
spoiler | boolean | Spoiler all files in the selected posts. |
unlink_file | boolean | Unlink files from the selected posts. If there are other copies of the file in other posts, or the global settings do not immediately prune unlinked files, the file may remain on disk. |
delete_file | boolean | Forcefully delete files from the selected posts, ignoring other references or server settings for delayed file pruning. |
global_report | boolean | Report the selected posts to global staff. |
global_ban | boolean | Ban the ips for all selected posts globally. |
ban_q | boolean | Ban a small ip range, /24 for ipv4 and /64 for ipv6. |
ban_h | boolean | Ban a larger ip range, /16 for ipv4 and /48 for ipv6. |
no_appeal | boolean | Removes the ability to appeal a ban. |
preserve_post | boolean | Whether to preserve the post and show it in the ban page. If the server prunes files, the files may no longer exist. |
hide_name | boolean | Whether the username of the staff should be hidden from public modlogs. |
checkedreports | array(string) | Array of report ids, for report actions such as dismiss or report_ban. |
edit | boolean | Whether to edit the selected post. Staff only. Must have only a single checkedposts . |
ban_reason | string | Reason for banning if ban or global_ban. |
log_message | string | Message to show in modlog explaining the reason for post actions. |
ban_duration | Time format string | Time format string for how long until the ban expires. |
report_ban | boolean | Whether to ban a reporter. Must submit the checkedpost and relevant checkedreports. |
_csrf | string | CSRF token |
Global staff - clear bypasses or login sessions
curl -v 'https://fatchan.org/forms/global/clear' -X POST \
-H 'Cookie: connect.sid=s%REDACTED;' \
--data "table=blockbypass" --data "confirm=1"
This endpoint allows you to delete all login sessions or block bypasses. Shares permissions with global manage settings (MANAGE_GLOBAL_SETTINGS
permission).
HTTP Request
POST https://fatchan.org/forms/global/clear
Parameters
Parameter | Type | Description |
---|---|---|
table | string | 'sessions' or 'blockbypass', whether to clear login sessions or blockbypasses. |
confirm | string | any value, set to confirm that you want to delete all sessions or blockbypasses |
_csrf | string | CSRF token |
Global staff - reports
curl -v 'https://fatchan.org/globalmanage/reports.json' \
-H 'Cookie: connect.sid=s%REDACTED;'
The above command returns JSON structured like this:
{
"reports": [
{
"_id": "61a06777c3ba8becf5be6303",
"date": "2021-11-26T04:49:59.832Z",
"u": 1637902199832,
"name": "Anon",
"country": {
"code": "TOR",
"name": "Tor Hidden Service"
},
"board": "test",
"tripcode": null,
"capcode": null,
"subject": "",
"message": "test",
"messagehash": "n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg=",
"nomarkup": "test",
"thread": null,
"email": "",
"spoiler": false,
"banmessage": null,
"userId": "1e22fb",
"ip": {
"raw": "redacted",
"cloak": "redacted"
},
"files": [],
"globalreports": [
{
"id": "61a63249a2e147d7c0f382dd",
"reason": "test",
"date": "2021-11-30T14:16:41.780Z",
"ip": {
"cloak": "redacted"
}
}
],
"quotes": [],
"crossquotes": [],
"backlinks": [],
"replyposts": 0,
"replyfiles": 0,
"sticky": 0,
"locked": 0,
"bumplocked": 0,
"cyclic": 0,
"bumped": "2021-11-26T04:49:59.832Z",
"postId": 224
}
],
"page": 1,
"ip": null,
"queryString": ""
}
Returns a list of posts that were globally reported with the global reports attached.
HTTP Request
GET https://fatchan.org/globalmanage/reports.json
Query Parameters
Parameter | Default | Description |
---|---|---|
page | Page number. 30 per page. Blank is first page. Page numbering starts at 1. | |
ip | Urlencoded IP address or cloak. Filters results to only posts made or reported by the IP. |
Global staff - recent posts
curl -v 'https://fatchan.org/globalmanage/recent.json' \
-H 'Cookie: connect.sid=s%REDACTED;'
The above command returns JSON structured like this:
[
{
"_id": "619c4cd4c3ba8becf5be62eb",
"date": "2021-11-23T02:07:16.339Z",
"u": 1637633236339,
"name": "Anon",
"country": null,
"board": "b",
"tripcode": null,
"capcode": null,
"subject": null,
"message": "<a rel=\"nofollow\" referrerpolicy=\"same-origin\" target=\"_blank\" href=\"https://m.youtube.com/watch?v=Fiv7nteHZPY&feature=emb_title\">https://m.youtube.com/watch?v=Fiv7nteHZPY&feature=emb_title</a>\r\n\r\nPresenting, life of childe",
"messagehash": "yzBCT0RFSk7PWwHipZdetIkymJc7HDbth2d5uVQFokk=",
"nomarkup": "https://m.youtube.com/watch?v=Fiv7nteHZPY&feature=emb_title\r\n\r\nPresenting, life of childe",
"thread": 109,
"email": null,
"spoiler": false,
"banmessage": null,
"userId": null,
"ip": {
"raw": "redacted",
"cloak": "redacted"
},
"files": [],
"globalreports": [],
"quotes": [],
"crossquotes": [],
"backlinks": [],
"postId": 311
}
]
Returns a list of the most recent posts made across all boards.
HTTP Request
GET https://fatchan.org/globalmanage/recent.json
Query Parameters
Parameter | Default | Description |
---|---|---|
page | Page number. 30 per page. Blank is first page. Page numbering starts at 1. |
Global staff - board list
curl -v 'https://fatchan.org/globalmanage/boards.json' \
-H 'Cookie: connect.sid=s%REDACTED;'
The above command returns JSON structured like this:
{
"localBoards": [
{
"_id": "lain",
"owner": "redacted",
"tags": [
"lain",
"internet",
"technology",
"transhumanism",
"anime",
"manga",
"japan"
],
"sequence_value": 572,
"pph": 0,
"ppd": 2,
"ips": 2,
"lastPostTimestamp": {
"text": "5 hours ago",
"color": "#83d900"
},
"webring": false,
"settings": {
"moderators": [],
"name": "serial experiments lain",
"description": "ANIME / GAME / PRINT / SOFTWARE",
"sfw": true,
"unlistedLocal": false
}
},
{
"_id": "b",
"owner": "redacted",
"sequence_value": 323,
"pph": 0,
"ips": 2,
"lastPostTimestamp": {
"text": "27 minutes ago",
"color": "#31d900"
},
"settings": {
"moderators": [],
"name": "Random",
"description": "Where morons argue with baiting spammers",
"sfw": false,
"unlistedLocal": false
},
"ppd": 2,
"tags": [
"random",
"b",
"rand",
"anything",
"everything"
],
"webring": false
},
],
"page": 1,
"maxPage": 1
}
Returns a list of boards, 30 per page. Unlike the public endpoint it does not include webring boards, includes unlisted boards and shows whether a board is abandoned (has no owner). Can be filtered and sorted like the public board list.
HTTP Request
GET https://fatchan.org/globalmanage/boards.json
Query Parameters
Parameter | Default | Description |
---|---|---|
page | Page number. 30 per page. Blank is first page. Page numbering starts at 1. | |
search | A string to search by board name and tags, including prefix matches. | |
sort | popularity |
popularity sorts by a compound of (ips, pph, sequence_value), activity sorts by lastPostTimestamp. |
direction | desc |
desc or asc for descending or ascending sort order respectively. |
filter_unlisted | false |
Filter to only unlisted boards. |
filter_sfw | false |
Filter to only sfw boards. |
filter_abandoned | false |
Filter to only abandoned boards. |
Filters used in conjunction will AND together. That is, filter_unlited=true&filter_sfw=true will show only boards that are both unlisted and sfw.
Authentication
Register
curl -v 'https://fatchan.org/forms/register' -X POST \
-H 'Referer: https://fatchan.org/registration.html' -H 'x-using-xhr: true' \
--data "username=admin" --data "password=hunter2" --data "passwordconfirm=hunter2" --data "captcha=abc123"
# if the account is created successfully, 302 redirect to login.
...
< HTTP/2 302
< location: /login.html
...
Registers a new account.
HTTP Request
POST https://fatchan.org/forms/register
Parameters
Parameter | Type | Description |
---|---|---|
username | string | Account username |
password | string | Account password |
passwordconfirm | string | Account password repeated |
captcha | array(number) or string | See Captcha/block bypass |
nonce | string | Optional, for web3 registration: the nonce fetched from the nonce endpoint |
address | string | Optional, for web3 registration: eth address |
signature | string | Optional, for web3 registration: web3 signature output of signing the nonce |
Login
curl -v 'https://fatchan.org/forms/login' -X POST \
-H 'Referer: https://fatchan.org/login.html' -H 'x-using-xhr: true' \
--data "username=admin" --data "password=hunter2"
# if the password is correct, 302 response code and sets the 'connect.sid' cookie
...
< HTTP/2 302
< location: /account.html
< set-cookie: connect.sid=s%REDACTED; Path=/; Expires=Wed, 01 Dec 2021 10:35:03 GMT; HttpOnly; Secure; SameSite=Strict
...
# or, for an incorrect password, a 403 and an error
...
< HTTP/2 403
...
{"title":"Forbidden","message":"Incorrect username or password","redirect":"/login.html?goto=%2Faccount.html"}
Login to an account to get a session cookie. The connect.sid
cookie must be sent in requests to endpoints that require authentication.
Expiry is rolling, so each time the session is used, the expiry is reset to 24 hours and this will be reflected in the expiry value in set-cookie headers.
HTTP Request
POST https://fatchan.org/forms/login
Parameters
Parameter | Type | Description |
---|---|---|
username | string | Account username |
password | string | Account password |
nonce | string | Optional, for web3 login: the nonce fetched from the nonce endpoint |
address | string | Optional, for web3 login: eth address |
signature | string | Optional, for web3 login: web3 signature output of signing the nonce |
Logout
curl 'https://fatchan.org/forms/logout' -X POST \
-H 'Referer: https://fatchan.org/account.html' -H 'x-using-xhr: true' \
-H 'Cookie: connect.sid=s%REDACTED;'
Logs out and invalidate the connect.sid session cookie.
HTTP Request
POST https://fatchan.org/forms/logout
CSRF token
curl -v 'https://fatchan.org/csrf.json' \
-H 'Referer: https://fatchan.org/csrf.json' \
-H 'Cookie: connect.sid=s%REDACTED;'
# Returns a csrf token if the session cookie is valid.
...
< HTTP/2 200
...
{"token":"REDACTED"}
Returns a token used as an additional security field by some endpoints. For more information about CSRF (cross site request forgery), see https://owasp.org/www-community/attacks/csrf'
HTTP Request
GET https://fatchan.org/csrf.json
Captcha/block bypass
To solve a captcha when posting, or to separately solve a block bypass, submit the captchaid
cookie and data captcha
. Depending on captcha type, there are different options.
The example requests below are for blockbypass endpoint, however the same captchaid
cookie and captcha
data should be submitted to the reporting and posting endpoint when captcha is enabled.
If a form submission requires a block bypass and the form also requires a captcha, solving the captcha correctly will count as a block bypass, so it is not necessary to solve an additional block bypass captcha beforehand.
# Get a captchaid cookie
curl -v 'https://fatchan.org/captcha'
# returns 302 to the captcha image, and sets the cookie.
< HTTP/2 302
< set-cookie: captchaid=61b55e3e49e367be7c5a818c; Max-Age=300; Path=/; Expires=Sun, 12 Dec 2021 02:33:14 GMT; Secure; SameSite=Strict
< location: /captcha/61b55e3e49e367be7c5a818c.jpg
...
Web3 Nonce
curl -v 'https://fatchan.org/nonce/{address}.json' -X POST \
-H 'Referer: https://fatchan.org/login.html' \
# Returns json with the nonce
...
< HTTP/2 200 OK
...
< {"nonce":"diPRlfjSVQs78DGE3YKcENb4pgRqB1Bdlv3RH/yiE6Y="}
...
Fetches a nonce used as part of the web3 login process.
### HTTP Request
`GET https://fatchan.org/nonce/{address}.json`
### URL Parameters
Parameter | Type | Description
--------- | ---- | -----------
address | string | Ethereum address e.g. 0x68b637f227953eeb081a3b591c218adbeaa4c489
### Captcha cookie
To solve a captcha, you need a `captchaid` cookie.
Visiting `/captcha` will set the captchaid cookie (if you do not already have one), and redirect you to the captcha image `/captcha/<captchaid>.jpg`.
The cookie is required to be submitted when solving the captcha as described in the next sections. Captcha id cookies are valid for ~5 minutes in a default jschan configuration.
### HTTP Request
`GET https://fatchan.org/captcha`
```shell
# Grid v1 captcha example
curl 'https://fatchan.org/forms/blockbypass' -X POST \
-H 'Referer: https://fatchan.org/bypass.html' -H 'x-using-xhr: true' \
-H 'Cookie: captchaid=61a60064a2e147d7c0f382d8' \
--data 'captcha=1' --data 'captcha=3' --data 'captcha=11'
# returns 200 and a bypassid cookie if correct
< HTTP/2 200
< set-cookie: bypassid=s%REDACTED; Max-Age=86400; Path=/; Expires=Wed, 01 Dec 2021 11:12:21 GMT; Secure; SameSite=Strict
{"title":"Success","message":"Completed block bypass, you may go back and make your post."}
Grid v1 captcha
Grid v1 captcha consists of a nxn (by default 4x4) square grid of characters, and a question text. The characters are separated into "correct" and "incorrect" character groups, with a minimum of at least one correct character in the grid. Follow the question text and select only the "correct" characters. The character groups and question text can be completely customised, so it is not possible to document exact instructions for each. The captcha may have image effects applied such as noise, edge detection and distortion.
The default grid v1 configuration of jschan is:
- correct:
['●','■','♞','♦','▼','▲','♜','✦','♚','♞','♛','♝','♟','♣']
- incorrect:
['○','□','♘','♢','▽','△','♖','✧','♔','♘','♕','♗','♙','♧']
- question: 'Select the solid/filled icons'
The grid positions start from 0 and go from left to right, top to bottom i.e:
0 | 1 | 2 | 3 |
4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 |
Example (the example request is for this image):
Question: "Select the solid/filled icons"
![]() |
|
The solution is 1, 3, 11.
Other examples:
Question: "Select the odd numbers"
![]() |
|
The solution is 1, 3, 4, 12, 13, 14.
HTTP Request
POST https://fatchan.org/forms/blockbypass
Parameters
Parameter | Type | Description |
---|---|---|
captcha | array(number) | One or more numbers for the correct grid square indexes. |
# Grid v2 captcha example
curl 'https://fatchan.org/forms/blockbypass' -X POST \
-H 'Referer: https://fatchan.org/bypass.html' -H 'x-using-xhr: true' \
-H 'Cookie: captchaid=61a60064a2e147d7c0f382d8' \
--data 'captcha=2' --data 'captcha=6' --data 'captcha=11' --data 'captcha=14'
# returns 200 and a bypassid cookie if correct
< HTTP/2 200
< set-cookie: bypassid=s%REDACTED; Max-Age=86400; Path=/; Expires=Wed, 01 Dec 2021 11:12:21 GMT; Secure; SameSite=Strict
{"title":"Success","message":"Completed block bypass, you may go back and make your post."}
Grid v2 captcha
Grid v2 captcha consists of a nxn (by default 4x4) square grid of characters and arrows, and a question text. The characters are separated into "correct" and "incorrect" character groups, with one correct character in the grid. The rest of the grid will be incorrect characters and arrows. The objective is to select all arrows pointing at the "correct" character. The character groups (excluding arrows) and question text can be completely customised, so it is not possible to document exact instructions for each. The captcha may have image effects applied such as noise, edge detection and distortion. Grid v2 configuration is shared with v1.
The grid positions start from 0 and go from left to right, top to bottom i.e:
0 | 1 | 2 | 3 |
4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 |
Example (the example request is for this image):
![]() |
|
The solution is 2, 6, 11, 14.
HTTP Request
POST https://fatchan.org/forms/blockbypass
Parameters
Parameter | Type | Description |
---|---|---|
captcha | array(number) | One or more numbers for the correct grid square indexes. |
# Text captcha example
curl 'https://fatchan.org/forms/blockbypass' -X POST \
-H 'Referer: https://fatchan.org/bypass.html' -H 'x-using-xhr: true' \
-H 'Cookie: captchaid=61a60064a2e147d7c0f382d8' \
--data 'captcha=bxw9yt'
# returns 200 and a bypassid cookie if correct
< HTTP/2 200
< set-cookie: bypassid=s%REDACTED; Max-Age=86400; Path=/; Expires=Wed, 01 Dec 2021 11:12:21 GMT; Secure; SameSite=Strict
{"title":"Success","message":"Completed block bypass, you may go back and make your post."}
Text captcha
Text captcha is a simple 6 character captcha containing numbers and letters only. The captcha may have a different font, and image effects applied such as wave, noise, paint, strikethrough, and distortion.
Example (the example request is for this image):
Solution:
bxw9yt
.
Other examples:
Solution:
3dhm6f
.
Solution:
lcvpya
.
Solution:
xnkosc
.
HTTP Request
POST https://fatchan.org/forms/blockbypass
Parameters
Parameter | Type | Description |
---|---|---|
captcha | string | The text shown in the image. |
Objects & Properties
Board
Two example boards. The first a webring board, the second a local board.
{
"_id": "61a45ea2c5f3b57f31789cfc",
"uri": "a",
"sequence_value": 709261,
"ips": 109,
"pph": 25,
"webring": true
"path": "https://smuglo.li/a",
"siteName": "Smug",
"lastPostTimestamp": {
"text": "12 minutes ago",
"color": "#14d900"
},
"settings": {
"sfw": false,
"name": "Anime & Manga",
"description": "Stay away from 3DPD"
},
"tags": [
"anime",
"manga"
]
}
{
"_id": "b",
"sequence_value": 320,
"ips": 4,
"pph": 0,
"ppd": 5,
"webring": false
"lastPostTimestamp": {
"text": "1 hour ago",
"color": "#72d900"
},
"settings": {
"name": "Random",
"description": "Anything and everything",
"sfw": false,
"unlistedLocal": false
},
"tags": [
"random",
"b",
"rand",
"anything",
"everything"
],
},
Returned from boards endpoint and global staff boards endpoint. Can be a local board, or one fetched from a federated site through the "webring" system. Local and webring boards have slightly different data.
Parameters
Parameter | Type | Description |
---|---|---|
_id | string | The board URI if webring is false, otherwise a unique identifier for a webring board. |
uri | string | The board URI if webring is true, otherwise not present. |
sequence_value | number | The current highest post number. |
ips | number | Number of IPs from active users. In webring false boards, represents the number of unique IPs that have posted in the last 24 hours. In webring true, implementations vary and the timeframe may be different. |
pph | number | Number of posts made in the last hour. |
ppd | number | Number of posts made in the last day. Not present in all webring implementations. |
webring | boolean | Whether a board is a webring board, or a local board. |
path | string | The URL of the board if webring true, otherwise not present. |
siteName | string | The site name if webring true, otherwise not preesnt. |
lastPostTimestamp | object | |
lastPostTimestamp.text | string | Text representation of when the last post was made e.g. "13 minutes ago". |
lastPostTimestamp.color | string | Text of a hexadecimal color code prefixed with # e.g. "#14d900". |
settings | object | |
settings.sfw | boolean | Whether the board is "safe for work". |
settings.name | string | The board name. |
settings.description | string | The board description. |
settings.unlistedLocal | boolean | Whether the board is unlisted locally if webring false, otherwise not present. Always false on public boards endpoint. |
settings.moderators | array(string) | List of usernames of moderators, only present in global staff board list. |
owner | string | Board owner username, only present in global staff board list. |
tags | array(string) | List of tags for the board. |
Post
An example post
{
"_id": "6158e81eb33d7abaa5f90ba0",
"date": "2021-10-02T23:15:42.675Z",
"u": 1633216542675,
"name": "Anon",
"country": {
"code": "AU",
"name": "Australia"
},
"ip": {
"raw": "redacted",
"cloak": "redacted"
},
"board": "t",
"tripcode": null,
"capcode": "## Admin",
"subject": "Important Links",
"message": "<span class=\"title\">Git repository & issue tracker:</span> <a rel=\"nofollow\" referrerpolicy=\"same-origin\" target=\"_blank\" href=\"https://gitgud.io/fatchan/jschan\">https://gitgud.io/fatchan/jschan</a>\nGo here to see the source code, report issues or ask relevant questions.\n\n<span class=\"title\">IRC:</span> <a rel=\"nofollow\" referrerpolicy=\"same-origin\" target=\"_blank\" href=\"https://irc-web.fatpeople.lol\">https://irc-web.fatpeople.lol</a> (irc-web.fatpeople.lol port 6697 TLS on)\nJoin IRC to chat directly with staff and other users in a realtime format.\n\n<span class=\"title\">Test board:</span> <a class=\"quote\" href=\"/test/index.html\">>>>/test/</a>\nTest things on the /test/ board rather than here or anywhere else.",
"messagehash": "tkak9s72dCSv9XkocVNwceUfmtwqaTH8gL9bzcQxwP4=",
"nomarkup": "==Git repository & issue tracker:== https://gitgud.io/fatchan/jschan\nGo here to see the source code, report issues or ask relevant questions.\n\n==IRC:== https://irc-web.fatpeople.lol (irc-web.fatpeople.lol port 6697 TLS on)\nJoin IRC to chat directly with staff and other users in a realtime format.\n\n==Test board:== >>>/test/\nTest things on the /test/ board rather than here or anywhere else.",
"thread": null,
"email": "",
"spoiler": false,
"banmessage": null,
"userId": "307203",
"files": [],
"quotes": [],
"crossquotes": [],
"backlinks": [],
"replyposts": 0,
"replyfiles": 0,
"sticky": 3,
"locked": 1,
"bumplocked": 0,
"cyclic": 0,
"bumped": "2021-10-02T23:15:42.675Z",
"postId": 1360,
"edited": {
"username": "admin",
"date": "2021-11-03T00:36:36.620Z"
},
"replies": []
}
Returned from overboard endpoints, board endpoints, staff recent posts and staff reports endpoints. A post can be a thread of a reply. The thread being the first post under which replies are made. Threads include a few extra properties for things such as being "sticky". Where included (such as index pages and threads), replies are nested within the "replies" property of a thread.
Parameters
Parameter | Type | Description |
---|---|---|
_id | string | Unique identifier for the post. |
date | string | The ISO format date string of when the post was made. |
u | string | Unix timestamp format of when the post was made. |
name | string | The poster name. |
board | string | The board URI. |
country | object | Geoip or custom flag information, if enabled on a board. |
country.code | string | Custom flag name if country.custom is true. Otherwise ISO 2 character country code, or "T1" for Tor exit nodes, "TOR" for Tor .onion, "LOKI" for lokinet, or "XX" for unknown (no geoip information). |
country.name | string | Custom flag name if country.custom is true. Otherwise the country name. "Europe" for unknown european country. "Unknown" when no geoip information is available. "Tor Exit Node" for Tor exit node. "Tor Hidden Service" for Tor .onion. |
country.custom | boolean | Whether the flag is a board custom flag. |
country.src | string | The filename of a board custom flag. The absolute path of the flag file is /flag/{board}/{country.src} . |
ip | object | |
ip.raw | string | IP (or ip.cloak if raw ips are not stored). |
ip.cloak | string | Cloaked IP. |
tripcode | string or null | The tripcode if one was used, otherwise null. Traditional ("insecure") tripcodes start with ! , "secure" tripcodes use !! . |
capcode | string or null | The staff capcode if one is used e.g. '## Admin'. |
subject | string | The post subject. |
message | string | HTML formatted message |
nomarkup | string | Original message before HTML formatting. |
messagehash | string | sha256 hash of nomarkup. |
postId | number | The post number, increasing by 1 for each post. |
thread | number of null | For threads, null. For replies, a number equal to the postId of the thread. |
string or null | The poster email. Not necessarily an email, can be any string or special values like "sage" meaning the post will not bump a thread. | |
spoiler | boolean | Whether all files in a post are spoilered. |
signature | string or null | Web3 eth personal_sign signature of signed message content. |
address | string or null | Recovered ethereum address from web3 signature. |
banmessage | string or null | The public ban message attached to a post, optionally set when a staff member bans the poster without deleting the post. |
userId | string or null | The user ID which is a substring of a hash of poster IP + server side per-thread secret e.g. substring(hash(poster IP + thread secret)). |
files | array(File) | Array of files, explained in the File subsection |
quotes | array(object) | Array of quotes, posts within the same thread that this post mentions. |
quotes[]._id | string | Corresponds to the _id property of a post. |
quotes[].thread | number | Corresponds to the thread property of a post. |
quotes[].postId | number | Corresponds to the postId property of a post. |
crossquotes | array(object) | Array of crossquotes, posts in other threads on the same board that this post mentions. |
crossquotes[]._id | string | Corresponds to the _id property of a post. |
crossquotes[].thread | number | Corresponds to the thread property of a post. |
crossquotes[].postId | number | Corresponds to the postId property of a post. |
backlinks | array(object) | Array of backlinks, posts in the same thread that mention this post. |
backlinks[]._id | string | Corresponds to the _id property of a post. |
backlinks[].postId | number | Corresponds to the postId property of a post. |
replyposts | number | Threads only, the number of replies to this post. |
replyfiles | number | Threads only, the total number of files in all replie sto this post. |
sticky | number | Threads only, The "sticky" priority of a thread. Higher number = higher priority and sorted earlier. 0 = Not sticky. |
locked | number | Threads only, 0 = not locked, 1 = locked. Locked prevents non-staff from replying to the thread. |
cyclic | number | Threads only, 0 = not cyclic, 1 = locked. Cyclic means earlier replies will be deleted to make room for new replies, instead of the thread reaching a bump limit and locking. |
bumplocked | number | Threads only, 0 = not locked, 1 = locked. Bumplocked prevents the thread from being bumped when a reply is posted. |
bumped | string | Threads only, the ISO format date string of when the thread was last bumped. Note, this is not equal to the date of the most recent reply because it could have used "sage" email, the thread may be bumplocked, or have reached the bump limit. |
edited | object | Object with information about when the post was last edited. |
edited.username | string | Username of the staff who edited the post. |
edited.date | string | ISO format date string of when the post was edited. |
replies | array(Post) | Array of replies (other non-thread posts). Only present in threads, or index pages with > 0 preview replies. |
reports | array(Report) | Array of board reports. Only present when fetched from board staff endpoints. |
globalreports | array(Report) | Array of global reports. Only present when fetched from global staff endpoints. |
File
An example file
{
"spoiler": null,
"hash": "10e24a1eef06d36d29a30f60e4616ef8cea9050c8f1e13b80af75b01687ef1fa",
"filename": "10e24a1eef06d36d29a30f60e4616ef8cea9050c8f1e13b80af75b01687ef1fa.jpg",
"originalFilename": "10e24a1eef06d36d29a30f60e4616ef8cea9050c8f1e13b80af75b01687ef1fa.jpg",
"mimetype": "image/jpeg",
"size": 259561,
"extension": ".jpg",
"sizeString": "253.5KB",
"thumbextension": ".jpg",
"geometry": {
"width": 1024,
"height": 768,
"thumbwidth": 250,
"thumbheight": 187
},
"geometryString": "1024x768",
"hasThumb": true
}
Files uploaded by users, in the files
array of a Post object.
Parameter | Type | Description |
---|---|---|
spoiler | boolean | If the individual file is spoilered |
hash | string | Sha256 hash of the file |
filename | string | Filename (sha256sum + extension). Absolute path of files are /file/{filename} |
originalFilename | string | The original filename (non hash) of the file when uploaded. |
mimetype | string | Mimetype of the file e.g. "image/png" or "video/webm" |
extension | string | The file extension with . e.g. ".jpg" |
size | number | Size in bytes of the file |
sizeString | string | Friendly string format of filesize, a number with up to 1 decimal place followed by the unit B, KB, MB, GB, TB. |
duration | number | Floating point number, how many seconds a video or audio file is. |
durationString | string | Friendly string format of duration, in hours:minutes:seconds format. Hours are the largest unit and can be a number larger than 99. Number in each segment are left padded with 0. Duration less than 60 seconds will have 00: prefixed. Will not show 00: for hours. e.g. 35 seconds = 00:35, 1 minute 25 seconds = 01:35, 1 hour 35 minutes = 01:35:00 |
thumbextension | string | The file extension of the thumbnail with . e.g. ".jpg". Can be different from extension due to thumbnails using different format. |
geometry | object | Object containing information about file and thumbnail dimensions. |
geometry.width | string | Width in pixels of the file. |
geometry.height | string | Height in pixels of the file. |
geometry.thumbwidth | string | Width in pixels of the thumbnail. |
geometry.thumbheight | string | Height in pixels of the thumbnail. |
geometryString | string | Friendly string format of the file geometry as {width}x{height} . |
hasThumb | boolean | Whether the file has a thumbnail. |
attachment | boolean | Whether the file is an "attachment" type, a file that is not an image, video or audio. |
Report
An example report
{
"id": "61a5d504ed285eccf2909dee",
"reason": "spam",
"date": "2021-11-30T07:38:44.971Z",
"ip": {
"raw": "redacted",
"cloak": "redacted"
}
}
Parameter | Type | Description |
---|---|---|
id | string | Unique identifier of the report. |
reason | string | Report reason entered by the reporter. |
date | string | ISO format date string when the report was made. |
ip | object | |
ip.raw | string | IP (or ip.cloak if raw ips are not stored). |
ip.cloak | string | Cloaked IP. |
Webring.json
Example webring.json data
{
"name": "fatchan",
"url": "https://fatchan.org",
"endpoint": "https://fatchan.org/webring.json",
"logo": [
"https://fatchan.org/favicon.ico"
],
"following": [
"https://anon.cafe/webring.json",
...
],
"blacklist": [],
"known": [
"https://anon.cafe/webring.json",
...
],
"boards": [
]
}
Webring.json data.
Parameter | Type | Description |
---|---|---|
name | string | The name of this site. |
url | string | The primary url of this site. |
endpoint | string | The url of the webring.json file. Typically {url}/webring.json |
logo | array(string) | Array of URLs to logo images to use. |
following | array(string) | Array of URLs of other sites endpoint to follow. |
known | array(string) | Array of known endpoints found through crawling, starting from endpoints in following . |
blacklist | array(string) | Array of hostnames to blacklist and not crawl. |
boards | array(Webring Board) | Array of webring-listed board on this site in webring format. |
Webring.json board
Example webring.json board
{
"uri": "t",
"title": "Meta",
"subtitle": "Fatchan Official",
"path": "https://fatchan.org/t/",
"postsPerHour": 0,
"postsPerDay": 0,
"totalPosts": 1410,
"uniqueUsers": 0,
"nsfw": false,
"tags": [
"meta",
"t",
"site",
"discussion",
"fatchan",
"/t/",
"/meta/",
"jschan"
],
"lastPostTimestamp": "2021-11-23T01:11:13.122Z"
}
A board from webring.json.
Parameter | Type | Description |
---|---|---|
uri | string | The uri of the board on this site. |
title | string | The board title/name. |
subtitle | string | The board subtitle. |
path | string | Full URL of the board. |
postsPerHour | number | Number of posts made per hour on this board. |
postsPerDay | number | Number of posts made per day on this board. |
totalPosts | number | The total number of posts ever made on this board. |
uniqueUsers | number | The number of unique user IP/IDs that have posted on this board in the past 24 hours. |
nsfw | boolean | Whether the board is nsfw (not safe for work). |
tags | array(string) | List of tags for the board. |
lastPostTimeStamp | string | ISO format date string of when the last post was made on the board. |
Miscellaneous
Time format string
Some moderation interfaces, for example the ban duration when moderating posts, or the ban duration for post filtering use a shorthand for times/length. This format supports years, months, weeks, days, hours, minutes and seconds. An input of "3mo" would mean 3 months and "1y2mo3w4d5h6m7s" would mean 1 year, 2 months, 3 weeks, 4 days, 5 hours, 6 minutes and 7 seconds. Units of time should be in descending order, so "2w1mo" is invalid. However you may use "6w" for example to input 6 weeks, and are not required to use "1mo2w".
Errors
The jschan API uses the following error codes:
Error Code | Meaning |
---|---|
400 | Bad Request -- Your request is invalid. |
403 | Forbidden -- You are not logged in, or do not have permission to access the requested resource. |
404 | Not Found -- The specified resource could not be found. |
405 | Method Not Allowed -- You tried to access a resource with an invalid method. |
429 | Too Many Requests -- You're sending too many requests too quickly. |
500 | Internal Server Error -- We had a problem with our server. Try again later. |
503 | Service Unavailable -- We're temporarily offline for maintenance. Please try again later. |