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/jsonfor JSON request bodies.- Timestamps: UTC ISO 8601 strings in
timestampfields. - 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
GET /csrf-token→{ "token": "<hex>" }- Send the token on the next mutating request as header
x-csrf-token: <token>(alias:csrf-token). - 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 whenembed_urlis 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-dataor urlencoded form.- Fields:
message(required unless a file orembed_urlis present),embed_urloptional,mod_signoptional. Sending a file together withembed_url→400.
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
- Board list:
GET /api/{board}?limit=&offset=. - Open thread:
GET /api/{board}/{threadId}(flat list) or compose from index card. - Live thread: open
/ws/thread,sub, on{t:"reply"}callGET /api/update/{board}/{threadId}/{lastKnownPostId}or refetch the full thread. - Post text (no file):
POST /api/thread/{board}/POST /api/{board}/{threadId}with JSONmessage. - Post with file:
GET /csrf-token→ multipartPOST /{board}/threador.../thread/{id}with headerx-csrf-tokenand cookies.
duże
jeśli
prawdziwe
| ale | inba |
|---|---|
| ja | pierdole |


