Markers & Icons
Read markers
Section titled “Read markers”GET /api/rooms/:roomId/markers (token permission: read){ "count": 42, "markers": [ { "id": "marker-…", "latitude": 47.56, "longitude": 7.59, "title": "…" } ] }Create one marker
Section titled “Create one marker”POST /api/rooms/:roomId/markers (token permission: write)Content-Type: application/jsonSynchronous — 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).
Read one marker
Section titled “Read one marker”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.
Update a marker
Section titled “Update a marker”PATCH /api/rooms/:roomId/markers/:markerId (token permission: write)Content-Type: application/jsonSend only what changes; omitted fields are left alone.
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:
nullclears a field;""stores an empty string — they are not the same.latitude,longitude,titleandcolorcan be changed but not cleared — a marker needs all four to render.imageKeyandthumbnailKeytravel together: send both, or both asnullto 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 are400 unknown_field:<key>— soid,createdBy,createdAtand 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 a marker
Section titled “Delete a 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.
Behaviour worth knowing
Section titled “Behaviour worth knowing”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.
Bulk-import markers
Section titled “Bulk-import markers”POST /api/rooms/:roomId/bulk-import (token permission: write)Content-Type: multipart/form-data # field: file = a point FeatureCollectionAsynchronous → { "jobId": "bulk-import-…" }; poll GET /api/jobs/:jobId. Each Point’s properties
may carry title, description, tags, eventDate, imageKey/thumbnailKey, markerIconId, and
markerIconSize.
Upload a marker photo
Section titled “Upload a marker photo”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.
Marker icons
Section titled “Marker icons”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:
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-…" }
