Skip to content
EN

Markers & Icons

GET /api/rooms/:roomId/markers (token permission: read)
{ "count": 42, "markers": [ { "id": "marker-…", "latitude": 47.56, "longitude": 7.59, "title": "" } ] }
POST /api/rooms/:roomId/markers (token permission: write)
Content-Type: application/json

Synchronous — returns the created marker. Only latitude/longitude are required.

{ "latitude": 47.5596, "longitude": 7.5886, "title": "Site A", "description": "first visit", "tags": ["survey"] }

201 { "success": true, "marker": { "id": "marker-…", ... } }

Optional fields: color (hex), tags (≤50), eventDate (epoch ms), markerIconId, markerIconSize (8–256), imageKey/thumbnailKey (from markers/upload-image), embeddedMediaUrl, mediaSize (sm | md | lg).

GET /api/rooms/:roomId/markers/:markerId (token permission: read)

200 { "success": true, "marker": { … } }, or 404 if it does not exist. Anonymous callers can read a marker in a public room, the same as the list endpoint.

This view omits the creator’s email and the legacy inline image blobs — fetch images through GET /api/rooms/:roomId/markers/image?key=… instead.

PATCH /api/rooms/:roomId/markers/:markerId (token permission: write)
Content-Type: application/json

Send only what changes; omitted fields are left alone.

Terminal window
curl -X PATCH "$API/api/rooms/$ROOM/markers/$MARKER" -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"title":"Site A (revisited)","description":null,"color":"#ef4444"}'
# → 200 { "success": true, "marker": { … } }

Accepts the same fields as create. The rules worth knowing:

  • null clears a field; "" stores an empty string — they are not the same.
  • latitude, longitude, title and color can be changed but not cleared — a marker needs all four to render.
  • imageKey and thumbnailKey travel together: send both, or both as null to remove the image. Replacing them also drops the previous photo’s EXIF, so a new image never inherits the old one’s camera or GPS provenance.
  • An empty body is 400 empty_update, and unknown fields are 400 unknown_field:<key> — so id, createdBy, createdAt and the inline blob fields are read-only here.
  • Titles may not contain newlines.

A caller holding write but not read gets back only the fields it submitted, never the stored marker.

DELETE /api/rooms/:roomId/markers/:markerId (token permission: write)

200 { "success": true, "markerId": "marker-…" }, or 404 if it is already gone. Deleting also removes the marker’s images from storage, unless another marker still references them.

Other status codes: 403 insufficient permission · 502 the change could not be broadcast · 503 room state momentarily unreadable, retry.

Every update and delete reaches open browsers immediately and is recorded in the room’s history. Reads are eventually consistent — one issued straight after a write may briefly show the previous state, so poll rather than trusting a single read. Back-to-back writes are safe. Concurrent edits to one marker resolve last-write-wins on the whole marker, so a PATCH can overwrite an edit somebody is making in the app at the same moment.

POST /api/rooms/:roomId/bulk-import (token permission: write)
Content-Type: multipart/form-data # field: file = a point FeatureCollection

Asynchronous → { "jobId": "bulk-import-…" }; poll GET /api/jobs/:jobId. Each Point’s properties may carry title, description, tags, eventDate, imageKey/thumbnailKey, markerIconId, and markerIconSize.

POST /api/rooms/:roomId/markers/upload-image (token permission: write)
Content-Type: multipart/form-data # fields: image, thumbnail

{ "imageKey": "markers/…jpg", "thumbnailKey": "markers/…_thumb.jpg" }. The returned keys must be referenced from a marker (via its properties/fields) to appear on the map.

GET /api/rooms/:roomId/marker-icons (token permission: read) — list (icon blob omitted)
POST /api/rooms/:roomId/marker-icons (token permission: write) — register an SVG/PNG (≤1 MB)

Register a reusable icon, then reference its returned iconId from markers via markerIconId:

Terminal window
curl -X POST "$API/api/rooms/$ROOM/marker-icons" -H "Authorization: Bearer $TOKEN" \
-F "icon=@tree.svg" -F "name=Tree" -F "size=32"
# → 201 { "iconId": "icon-api-…" }