Files
api/REFERENCE.md
T
2026-07-08 13:37:36 -05:00

7.1 KiB

TACHYON API Reference

Base URL (local dev): http://localhost:3000 Base URL (once deployed behind the tunnel, e.g.): https://api.radium.wtf

All request/response bodies are JSON. POST/PUT requests must send Content-Type: application/json.


Health

GET /api/health

Liveness check — confirms the API process is up and responding.

Response 200

{ "ok": true }

Example

curl http://localhost:3000/api/health

News

Backed by the news_posts table. Powers the News panel.

GET /api/news

List news posts, newest first.

Query params

Param Type Default Notes
limit number 20 Capped at 100

Response 200

[
  {
    "id": 3,
    "title": "Placeholder announcement title",
    "content": "Short placeholder line describing an update or change.",
    "created_at": "2026-07-06T12:00:00.000Z"
  }
]

Example

curl "http://localhost:3000/api/news?limit=5"

POST /api/news

Create a news post.

Body

Field Type Required
title string yes
content string yes

Response 201 — the created row (with generated id and created_at)

{
  "id": 4,
  "title": "New post title",
  "content": "New post body text.",
  "created_at": "2026-07-08T18:30:00.000Z"
}

Response 400 — missing fields

{ "error": "title and content are required" }

Example

curl -X POST http://localhost:3000/api/news \
  -H "Content-Type: application/json" \
  -d '{"title": "New post title", "content": "New post body text."}'

DELETE /api/news/:id

Delete a news post by id.

Response 204 — no body, success. Response 404

{ "error": "not found" }

Example

curl -X DELETE http://localhost:3000/api/news/4

Media

Backed by the media_items table. Powers the Media grid.

GET /api/media

List media items, newest first.

Query params

Param Type Default Notes
limit number 24 Capped at 100

Response 200

[
  {
    "id": 1,
    "title": "placeholder clip one",
    "media_type": "image",
    "url": "https://example.com/media/1.png",
    "created_at": "2026-07-08T17:59:31.129Z"
  }
]

Example

curl "http://localhost:3000/api/media?limit=12"

POST /api/media

Add a media item.

Body

Field Type Required Notes
title string yes
media_type string yes must be "image" or "video"
url string yes

Response 201 — the created row

{
  "id": 5,
  "title": "new clip",
  "media_type": "video",
  "url": "https://example.com/media/5.mp4",
  "created_at": "2026-07-08T18:35:00.000Z"
}

Response 400

{ "error": "title, url, and media_type (image|video) are required" }

Example

curl -X POST http://localhost:3000/api/media \
  -H "Content-Type: application/json" \
  -d '{"title": "new clip", "media_type": "video", "url": "https://example.com/media/5.mp4"}'

DELETE /api/media/:id

Delete a media item by id.

Response 204 — no body, success. Response 404

{ "error": "not found" }

Example

curl -X DELETE http://localhost:3000/api/media/5

Stats

Backed by users, sessions, activity_log, and site_stats. Powers the Overview panel (Current Users / Recent Activity / General Statistics columns).

GET /api/stats/overview

The main endpoint for this panel — returns all three columns in a single call so the frontend doesn't need three round trips.

Response 200

{
  "currentUsers": [
    { "id": 1, "username": "placeholder_user_01", "started_at": "2026-07-08T18:00:00.000Z" }
  ],
  "recentActivity": [
    { "id": 1, "description": "placeholder event one", "created_at": "2026-07-08T17:00:00.000Z" }
  ],
  "general": {
    "users": {
      "total": 3,
      "mostRecent": { "username": "placeholder_user_03", "id": 3 }
    },
    "reports": { "named": "00", "associated": "00", "logged": "00" },
    "build": { "pipeline": "Completed", "buildNumber": "00000000", "version": "0.0.0" }
  }
}
  • currentUsers — users with an open session (sessions.ended_at IS NULL), most recently started first.
  • recentActivity — latest rows from activity_log.
  • general.users.total — total row count in users (not just online users).
  • general.reports / general.build — pulled from the site_stats key/value table; update these directly in the DB or add an admin endpoint if you want them editable via API.

Example

curl http://localhost:3000/api/stats/overview

GET /api/stats/users

Just the current-users list, if you want it without the rest of the overview payload (e.g. a lighter-weight poll for a live "online now" count).

Response 200

[
  { "id": 1, "username": "placeholder_user_01", "started_at": "2026-07-08T18:00:00.000Z" }
]

Example

curl http://localhost:3000/api/stats/users

POST /api/stats/session/start

Marks a user as online by opening a session. Creates the user row if the username doesn't exist yet.

Body

Field Type Required
username string yes

Response 201

{ "sessionId": 7, "userId": 3 }

Response 400

{ "error": "username is required" }

Example

curl -X POST http://localhost:3000/api/stats/session/start \
  -H "Content-Type: application/json" \
  -d '{"username": "placeholder_user_04"}'

Save the returned sessionId — you'll need it to end the session later.


POST /api/stats/session/end

Marks a session as ended (user no longer counted as "current").

Body

Field Type Required
sessionId number yes

Response 204 — no body, success. Response 400

{ "error": "sessionId is required" }

Response 404 — id doesn't exist or was already ended

{ "error": "no active session with that id" }

Example

curl -X POST http://localhost:3000/api/stats/session/end \
  -H "Content-Type: application/json" \
  -d '{"sessionId": 7}'

Error format

All error responses follow the same shape:

{ "error": "human-readable message" }

There's no auth layer on any of this yet — every endpoint above is open. Add something (API key header, session cookie, whatever fits your setup) before exposing the write endpoints (POST/DELETE) publicly, since right now anyone who can reach the API can create/delete news and media or spoof "current users."