Skip to content
getgeolens.com

Sharing groups API

Groups are created and filled by admins, then datasets and maps are shared with them. The behavior behind these routes is described in Sharing with groups. Request and response schemas are in the API reference.

Replace https://geolens.example.com, $TOKEN and the ids below with your own values. Send the token as a bearer token or API key, as described in API authentication.

These need the manage_users permission. Names are unique, and a duplicate answers 409.

Method and pathPurpose
GET /admin/groups/List groups by name, with member_count. Takes skip and limit.
POST /admin/groups/Create a group from {"name": "Planning"}. Answers 201.
GET /admin/groups/{group_id}Read one group.
PATCH /admin/groups/{group_id}Rename it with {"name": "..."}.
DELETE /admin/groups/{group_id}Delete it and its memberships. Answers 204.
GET /admin/groups/{group_id}/members/List members by username.
POST /admin/groups/{group_id}/members/Add users with {"user_ids": [...]}, up to 500. Users already in the group are skipped. An unknown id answers 404 and adds nobody.
DELETE /admin/groups/{group_id}/members/{user_id}Remove one member. Answers 204.
Terminal window
curl -X POST https://geolens.example.com/api/admin/groups/ \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "Planning"}'

Deleting a group removes its grants at once. A restricted map shared only with it becomes private. Adding a member answers 422 when a virtual raster dataset shared with the group would then reach someone who can’t read one of its sources.

Terminal window
curl "https://geolens.example.com/api/groups/mine/" \
-H "Authorization: Bearer $TOKEN"

Returns {"groups": [{"id": "...", "name": "..."}], "total": 1}. The groups are the ones the caller belongs to, or every group for an admin. skip and limit (default 50, at most 200) page the list.

Terminal window
curl -X PUT "https://geolens.example.com/api/datasets/$DATASET_ID/groups/" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"group_ids": ["'"$GROUP_ID"'"]}'

group_ids is the full list, up to 100, and replaces what the dataset had. An empty list removes every group. The caller needs the edit_metadata permission and must own the dataset or be an admin.

  • A private dataset with a group becomes restricted. A restricted dataset left with no group becomes private. Internal and public datasets keep their visibility.
  • An owner who adds a group they don’t belong to gets 403. An unknown group answers 404.
  • A change that would strand a layer in one of the owner’s shared maps, or expose a source through a virtual raster dataset, answers 422.

Dataset detail returns groups to the owner and admins only.

Terminal window
curl -X PUT "https://geolens.example.com/api/maps/$MAP_ID/groups/" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"group_ids": ["'"$GROUP_ID"'"]}'

The body and the visibility rules match the dataset route, with the map’s own owner-or-admin check. The response carries visibility, groups, shared_dataset_ids and hidden_layers. Becoming restricted revokes the map’s share link and embed tokens.

Confirm sharing layers the groups can’t read

Section titled “Confirm sharing layers the groups can’t read”

When a member of a new group can’t read a layer’s dataset, nothing is written and the route answers 409:

{
"detail": {
"code": "layers_hidden_from_groups",
"message": "...",
"layers": [
{
"layer_id": "...",
"layer_title": "Parcels",
"dataset_id": "...",
"dataset_title": "Parcels 2026",
"group_ids": ["..."],
"can_share": true
}
]
}
}

Repeat the request with confirm:

  • "share_datasets" also shares each dataset with can_share: true with the groups that lack it. A refusal on any of those shares rolls back the whole request, the map’s groups included.
  • "map_only" shares the map alone. The response’s hidden_layers lists the layers still out of reach.

Branch on detail.code. A 409 without it means another change holds the map’s lock, and the request can be retried.

GET /maps/{id}/visibility-check/ also returns hidden_from_groups: on a restricted map, the layers some of its groups can’t read, among those the caller can read.

A map can now be restricted. Older generated clients reject a visibility value they don’t know, so a map response names restricted only to clients that send this request header:

X-GeoLens-Map-Visibility: restricted

Every map-returning endpoint answers with Vary: X-GeoLens-Map-Visibility. Without the header a restricted map reads as private, and the visibility=private list filter also finds restricted maps. Writing private to a map that has groups keeps it restricted, so a client that can’t see the groups doesn’t remove them by accident. Remove them with PUT /maps/{id}/groups/ and an empty list. PUT /maps/{id} with visibility: restricted and no group answers 422.

The web app, the CLI, the MCP server and both SDKs send the header. A later release will name restricted to every client, header or not, so a client that sends it now sees no change then.

Map write and management routes answer 404, not 403, for a map the caller can’t read, so they no longer reveal that it exists. A caller who can read the map but doesn’t own it still gets 403.