YouTube · catbox.moe · desu.si · fileditch (mp4, webm, jpg, png, gif, webp)

Online (unique IPs):


postuje dokumentacje api. zapraszam do tworzenia wlasnych klientow.

Client API reference


Board id

:boardId is the board slug (string), e.g. b. Unknown board → 404 { "error": "Board not found" }.


JSON conventions

  • Content-Type: application/json for JSON request bodies.
  • Timestamps: UTC ISO 8601 strings in timestamp fields.
  • Errors: failures return JSON { "error": "<message>" } with an appropriate 4xx/5xx status.

Cookies

Cookie Purpose
poster_ref Opaque identifier set by the server on first post/upload. HttpOnly, Path=/, SameSite=Lax, Secure in production. Clients should send it back like a browser would.

If absent, the server sets it on the response.


CSRF

Some POSTs require a CSRF token sent as a request header.

Flow

  1. GET /csrf-token{ "token": "<hex>" }
  2. Send the token on the next mutating request as header x-csrf-token: <token> (alias: csrf-token).
  3. Fetch a fresh token before the next protected POST.

Missing/invalid → 403 with { "error": "Missing CSRF token" } / { "error": "Invalid CSRF token" }.


Read API — prefix /api

All GET. Write endpoints under /api are subject to server-side rate limiting; exceeding limits returns 429 with a JSON error.


GET /api/:boardId — board index

Query

Param Default Range
limit 10 1–100
offset 0 ≥ 0

Response: JSON array of thread objects (newest activity first):

{
  "originalPost": { "id", "thread_id", "subject", "trip", "name", "email", "timestamp", "message", "file", ... },
  "replies": [ { "...post fields...", "isOpReply": true } ]
}
  • originalPost / replies: public post fields only.
  • isOpReply: present when a reply is from the same client identity as OP.
  • mentions: optional aggregate of backlinks (threadOpId|citingPostId, …).
  • board_post_no: 0-based index of the post on the board.
  • embed_kind / embed_youtube_id: populated when embed_url is set.

GET /api/:boardId/catalog — catalog of recent OPs

Returns an array of OP rows (not split into originalPost / replies) with the same public columns plus board_post_no, ISO timestamps, and embed augmentation. Server-side capped to a small number of threads.


GET /api/:boardId/p:id — single post by global id

Path is /api/{board}/p{numericId} in one piece (example: /api/b/p100).

Returns an array of one post, or empty/404 if not found.


GET /api/:boardId/:thread — full thread as flat post list

:thread = OP / thread root numeric id.

Returns a JSON array of posts ascending by id: [op, ...replies]. Same per-post shape as catalog rows. Not the { originalPost, replies } wrapper used on the board index.


GET /api/update/:boardId/:thread_id/:from — poll new replies

Returns posts in the thread with id greater than from. Params must be valid integers.

If you suspect missed updates, refetch the full thread via GET /api/:boardId/:thread.


Write API — JSON — prefix /api

POST /api/thread/:boardId — new thread

Body

Field Type Notes
message string Required; validated.
mod_sign string Optional.

Success: JSON array of inserted ids, e.g. [123] (new OP id equals thread id).

Common errors: 400 validation, 403 not allowed, 429 throttled.


POST /api/:boardId/:threadId — reply

Body: message, optional mod_sign.

Success: [<newPostId>].

Common errors: 400 invalid board/thread, 403 not allowed, 429 throttled.


Write API — multipart / form (attachments)

Paths under site root (no /api prefix). Require a CSRF token (see above) and are rate-limited.

POST /:boardId/thread — new thread with file and/or embed

  • multipart/form-data or urlencoded form.
  • Fields: message (required unless a file or embed_url is present), embed_url optional, mod_sign optional. Sending a file together with embed_url400.

Files are validated for type and size; oversize, disallowed type, or excessive upload volume returns 4xx/429. A duplicate file on the same board returns 409 { "error", "duplicatePostId" }.

Success: 302 redirect to /{boardId} (HTML flow). Errors may be returned as JSON.

POST /:boardId/thread/:threadId — reply with attachment

Same rules as new thread.

Success: { "success": true }.


Media URLs

Uploaded files are served under /media/. The file and thumb fields on posts are filenames relative to that path.


WebSocket (optional realtime)

Connect a WebSocket client to the same host.

GET /ws/thread — new replies in a thread

After open, send UTF-8 JSON:

Subscribe

{ "op": "sub", "boardId": "<slug>", "threadId": <number> }

Unsubscribe

{ "op": "unsub", "boardId": "<slug>", "threadId": <number> }

Server → client

t Meaning
ack Subscription ok, e.g. { "t": "ack", "op": "sub", "boardId", "threadId" }
err { "t": "err", "error": "..." } — invalid sub or other failure.
reply Someone posted in the thread: { "t": "reply", "boardId", "threadId" } — then fetch new posts via /api/update/... or refetch the thread.

Payload does not include post bodies.

GET /ws/presence — site-wide “online” estimate

Connect only; the server periodically broadcasts:

{ "t": "online", "uniqueIps": <number> }

Reverse proxies must forward Upgrade and Connection headers for WebSockets.


Suggested client flows

  1. Board list: GET /api/{board}?limit=&offset=.
  2. Open thread: GET /api/{board}/{threadId} (flat list) or compose from index card.
  3. Live thread: open /ws/thread, sub, on {t:"reply"} call GET /api/update/{board}/{threadId}/{lastKnownPostId} or refetch the full thread.
  4. Post text (no file): POST /api/thread/{board} / POST /api/{board}/{threadId} with JSON message.
  5. Post with file: GET /csrf-token → multipart POST /{board}/thread or .../thread/{id} with header x-csrf-token and cookies.
AnonimusNo.152[Reply]
Terka api
AnonimusNo.153[Reply]
>GET /csrf-token xDD ty wiesz w ogóle po co jest csrf?
AnonimusNo.154[Reply]
Czemu robisz strony z wirusami
Anonimus 🍀 Admin[op]No.155[Reply]
>>153 wiem, natomiast ty chyba nie do konca. publiczny dostep do csrfow nic nie zmienia, zwykle sa wstrzykiwane w templatke, w przypadku api pobiera sie je endpointem. csrf chroni przed sytuacja gdy inna strona odpala request do tej domeny, a przegladarka dokleja do niego cookies. token musi byc dolaczony w headerze, ktorego obcy origin nie odczyta ani nie wysle bez przejscia przez CORS/preflight, wiec taki request konczy sie 403. sam GET /csrf-token nic nie daje bez cudzych cookies i mozliwosci uzycia tokenu w poprawnym requescie.
AnonimusNo.156[Reply]
czy to pierwszy czan z markdownem?

duże

jeśli

prawdziwe

ale inba
ja pierdole
AnonimusNo.157[Reply]
AnonimusNo.158[Reply]

crosscripting jedziemy

AnonimusNo.159[Reply]
Czy masz jaja duże
Anonimus 🍀 Admin[op]szluger man.gif · 795 KBNo.160[Reply]
>>158 jest whitelista dozwolonych zrodel dla obrazkow
AnonimusNo.163[Reply]
Dodaj logowanie przez discorda
Anonimus[op]No.166[Reply]
>>163 >raczek lurkujacy z mobilnego z autokapitalizacja zdan bedzie pisac cos o logowaniu przez discorda nalezy to skwitowac chlodnym usmieszkiem
AnonimusNo.168[Reply]
>>166 co ci diskord przeszkadza pedale, pewnie sam się logujesz przez maila albo kluczem pgp, no bo nie samym hasłem do panelu admina xDD?
Anonimus[op]No.169[Reply]
musialem zrobic migracje zmieniajaca numerowanie postow. cytaty z przeszlosci moga celowac do zlych postow. prosze o wyrozumialosc, sram psa, jak sra
AnonimusNo.170[Reply]
opie, pierwszy chan w którym jesteś choćby w moderacji?
AnonimusNo.171[Reply]

dens dens dens dens dens dens dens dens dens dens dens dens

>>160 żelbooru chyba ogólnie nie pozwala na hotlinkowanie
AnonimusNo.172[Reply]
to zupełnie custom kuc projekcik co? tz ani to vichan ani nic z dawnych phpowych, chociażby bo websockety, ani to jschan, ani lynxchan nawet nie postanowiłeś nic forkować tylko pojechałeś od zera długo już w nodejs klepiesz?
Anonimus[op]No.173[Reply]
>>170 nie do konca. dawno temu jeszcze przed pandemia wykucowalem jednego martwego czana
Anonimus[op]No.174[Reply]
>>172 tak, zupelnie customowy. wszystko od zera robie. ponad 5 lat stazu w nodejs
AnonimusNo.175[Reply]
``` :root{ --lt-box-bg: #222; --lt-background:#111; --lt-box-shadow: 1px 1px 1px 0 #333; --lt-navbar-bg:#222; --lt-navbar-shadow: 0px 1px 1px 1px #444444ad; --fg:#aaa; } body {color:var(--fg)} hr { color:#444 !important; border-color:#444 !important; background-color:#444 !important; } .main-form { background-color: var(--lt-navbar-bg); } .main-form input, .main-form textarea { background-color: var(--lt-navbar-bg) !important; color:var(--fg); scrollbar-color:var(--lt-box-bg) var(--lt-navbar-bg); } ``` chujowy darkmode dopóki admin nie wykucuje swojego
AnonimusNo.176[Reply]
section.absolute , .main-form { background-color: var(--lt-navbar-bg) !important; } bo jeszcze hoverposty
Anonimus[op]No.177[Reply]
>>175 uwu
Anonimus[op]No.183[Reply]
>>175 dodalem custom css w ustawienaich, zachecam do customizowania ciana
AnonimusNo.185[Reply]
>>183 dziękuje, jestem białoskóry i używam stylusa