These docs are a work in progress and may not be fully up to date. Some pages may contain internal notes for our team.
Skip to Content

API — Maps

CRUD for the Map resource. A Map is a curated container that groups Locations and Sets — it is the core data structure attached to a Finder. Each Finder has a “backing map” that is auto-provisioned on creation.

Maps are owner-scoped: the authenticated user must be in the map_user pivot. Workspace scoping is applied via the workspace_id query parameter.

See also:

Authentication

All endpoints require Authorization: Bearer <jwt>. Middleware stack: auth:api, auth_session, audit (routes/api.php:100–105).

Response shape

All Map endpoints return the same serialized format, built by MapController::formatMap (app/Http/Controllers/MapController.php:12):

{ "id": 7, "title": "Main Map", "description": "Primary location map", "sets": [ { "id": 3, "title": "West Coast", "locations": [101, 102, 103] } ], "locations": [101, 102, 103, 104], "owners": [42], "created_at": "2026-01-15T10:00:00.000000Z", "updated_at": "2026-04-01T12:00:00.000000Z" }
  • sets — full Set objects with nested locations as ID arrays
  • locations — flat array of all Location IDs directly attached to the Map
  • owners — array of owner user IDs

Endpoints

GET /maps

Middleware: auth:api, auth_session, audit
Controller: MapController::index (app/Http/Controllers/MapController.php:30)
Description: Lists all Maps the authenticated user owns, with Sets (and their Locations), Locations, Owners, and Workspaces eagerly loaded.

Query parameters

ParamTypeDescription
workspace_idintegerIf provided, restricts results to Maps in this workspace

Response 200 — array of Map objects.


GET /maps/{id}

Middleware: auth:api, auth_session, audit
Controller: MapController::show (app/Http/Controllers/MapController.php:49)
Description: Returns a single Map by ID. Returns 404 if not found or the user is not an owner.

Response 200 — single Map object.

Response 404

{ "message": "Map not found or unauthorized access" }

POST /maps

Middleware: auth:api, auth_session, audit
Controller: MapController::store (app/Http/Controllers/MapController.php:66)
Description: Creates a new Map. The authenticated user is attached as owner unless owners is explicitly provided.

Request body

{ "title": "Main Map", "description": "Primary location map", "sets": [3, 5], "locations": [101, 102], "owners": [42], "workspaces": [1] }
FieldTypeRequiredNotes
titlestringyes
descriptionstringnonullable
setsinteger[]noSet IDs to attach
locationsinteger[]noLocation IDs to attach directly
ownersinteger[]noUser IDs; defaults to authenticated user
workspacesinteger[]noWorkspace IDs

Response 201 — created Map object.

Error responses

StatusCondition
400Validation failure

PUT /maps/{id}

Middleware: auth:api, auth_session, audit
Controller: MapController::update (app/Http/Controllers/MapController.php:109)
Description: Updates a Map. All fields are optional. Relationship fields use sync semantics when present — sending sets: [] clears all Set associations, sending locations: [] clears all direct Location attachments. Omitting a relationship field entirely leaves it unchanged.

Request body — same fields as POST /maps, all optional.

Response 200 — updated Map object.

Error responses

StatusCondition
400Validation failure
404Map not found or user is not an owner

⚠️ Warning: sets and locations use $request->has() (not $request->filled()) to detect the sync intent, so passing null for either field clears the relationship. See MapController::update lines 137–148.


DELETE /maps/{id}

Middleware: auth:api, auth_session, audit
Controller: MapController::destroy (app/Http/Controllers/MapController.php:154)
Description: Deletes a Map. The user must be an owner.

⚠️ Warning: Deleting a Map that is the backing map for a Finder will orphan the Finder’s map association. The backing map is auto-provisioned by Finder::ensureBackingMap() and should not be deleted independently. Finders should be deleted first, or the delete should be coordinated at the application layer.

Response 204 — no content.

Response 404 — not found or unauthorized.


Relationship notes

  • A Map can have Locations attached both directly (via map_location pivot) and indirectly through Sets (via set_location and map_set pivots). The locations field in the response is the direct attachment only; Set-membered locations appear under their Set in sets[].locations.
  • The frontend maps.ts calls hydrateMapCategories after fetch to merge Set data when Sets are referenced but not yet in the local store (src/lib/api/maps.ts:7).
  • Maps are linked to Finders via a finder_map pivot. Finders surface their map list as maps: [id] (single backing map ID).