Files
hnh-map/docs/api.md
Nikolay Tatarinov 3968bdc76f Enhance API documentation and improve marker functionality
- Updated API documentation for clarity and consistency, including detailed descriptions of authentication and user account endpoints.
- Added a new cave marker image to enhance visual representation in the frontend.
- Implemented normalization for cave marker images during upload to ensure consistent storage format.
- Expanded test coverage for client services, including new tests for marker uploads and image normalization.
2026-03-04 16:57:43 +03:00

5.8 KiB
Raw Permalink Blame History

HTTP API

The API is available under the /map/api/ prefix. Requests requiring authentication use a session cookie (set on login).

Authentication

  • POST /map/api/login — sign in. Body: {"user":"...","pass":"..."}. On success returns JSON with user data and sets a session cookie. On first run, bootstrap is available: logging in as admin with the password from HNHMAP_BOOTSTRAP_PASSWORD creates the first admin user. For users created via OAuth (no password), returns 401 with {"error":"Use OAuth to sign in"}.
  • GET /map/api/me — current user (by session). Response: username, auths, and optionally tokens, prefix, email (string, optional — for Gravatar and display).
  • POST /map/api/logout — sign out (invalidates the session).
  • GET /map/api/setup — check if initial setup is needed. Response: {"setupRequired": true|false}.

OAuth

  • GET /map/api/oauth/providers — list of configured OAuth providers. Response: ["google", ...].
  • GET /map/api/oauth/{provider}/login — redirect to the provider's authorization page. Query: redirect — path to redirect to after successful login (e.g. /profile).
  • GET /map/api/oauth/{provider}/callback — callback from the provider (called automatically). Exchanges the code for tokens, creates or finds the user, creates a session, and redirects to /profile or the redirect from state.

User account

  • PATCH /map/api/me — update current user. Body: {"email": "..."}. Used to set or change the user's email (for Gravatar and profile display). Requires a valid session.
  • POST /map/api/me/tokens — generate a new upload token (requires upload permission). Response: {"tokens": ["...", ...]}.
  • POST /map/api/me/password — change password. Body: {"pass":"..."}.

Map data

  • GET /map/api/config — client configuration (title, auths). Requires a session.
  • GET /map/api/v1/characters — list of characters on the map (requires map permission; markers permission needed to see data). Each character object includes ownedByMe (boolean), which is true when the character was last updated by one of the current user's upload tokens.
  • GET /map/api/v1/markers — markers (requires map permission; markers permission needed to see data).
  • GET /map/api/maps — list of maps (filtered by permissions and hidden status). For non-admin users hidden maps are excluded; for admin, the response may include hidden maps (client should hide them in map selector if needed).

Admin (all endpoints below require admin permission)

  • GET /map/api/admin/users — list of usernames.
  • POST /map/api/admin/users — create or update a user. Body: {"user":"...","pass":"...","auths":["admin","map",...]}.
  • GET /map/api/admin/users/:name — user data.
  • DELETE /map/api/admin/users/:name — delete a user.
  • GET /map/api/admin/settings — settings (prefix, defaultHide, title).
  • POST /map/api/admin/settings — save settings. Body: {"prefix":"...","defaultHide":true|false,"title":"..."} (all fields optional).
  • GET /map/api/admin/maps — list of maps for the admin panel.
  • POST /map/api/admin/maps/:id — update a map (name, hidden, priority).
  • POST /map/api/admin/maps/:id/toggle-hidden — toggle map visibility.
  • POST /map/api/admin/wipe — wipe grids, markers, tiles, and maps from the database.
  • POST /map/api/admin/rebuildZooms — start rebuilding tile zoom levels from base tiles in the background. Returns 202 Accepted immediately; the operation can take minutes when there are many grids. The client may poll GET /map/api/admin/rebuildZooms/status until {"running": false} and then refresh the map.
  • GET /map/api/admin/rebuildZooms/status — returns {"running": true|false} indicating whether a rebuild started via POST rebuildZooms is still in progress.
  • GET /map/api/admin/export — download data export (ZIP).
  • POST /map/api/admin/merge — upload and apply a merge (ZIP with grids and markers).
  • GET /map/api/admin/wipeTile — delete a tile. Query: map, x, y.
  • GET /map/api/admin/setCoords — shift grid coordinates. Query: map, fx, fy, tx, ty.
  • GET /map/api/admin/hideMarker — hide a marker. Query: id.

Game client

The game client (e.g. Purus Pasta) communicates via /client/{token}/... endpoints using token-based authentication.

  • GET /client/{token}/checkVersion — check client protocol version. Query: version. Returns 200 if matching, 400 otherwise.
  • GET /client/{token}/locate — get grid coordinates. Query: gridID. Response: mapid;x;y.
  • POST /client/{token}/gridUpdate — report visible grids and receive upload requests.
  • POST /client/{token}/gridUpload — upload a tile image (multipart).
  • POST /client/{token}/positionUpdate — update character positions.
  • POST /client/{token}/markerUpdate — upload markers.

SSE (Server-Sent Events)

  • GET /map/updates — real-time tile and merge updates. Requires a session with map permission. Sends an initial data: message with an empty tile cache array [], then incremental data: messages with tile cache updates and event: merge messages for map merges. The client requests tiles with cache=0 when not yet in cache.

Tile images

  • GET /map/grids/{mapid}/{zoom}/{x}_{y}.png — tile image. Requires a session with map permission. Returns the tile image or a transparent 1×1 PNG if the tile does not exist.

Response codes

  • 200 — success.
  • 400 — bad request (wrong method, body, or parameters).
  • 401 — unauthorized (missing or invalid session).
  • 403 — forbidden (insufficient permissions).
  • 404 — not found.
  • 500 — internal error.

Error format: JSON body {"error": "message", "code": "CODE"}.