Skip to content

API Reference ​

The backend exposes a single REST API under /api/v1 (registry.server.prefix = /api, version in the path). Responses are reactive JSON. Every call requires a bearer JWT except the four public authentication endpoints. Project-scoped endpoints live under /api/v1/projects/{projectId}/… and are guarded by a project-scoped permission — combined with an option gate when the resource belongs to an optional module.

Conventions ​

The contract grew feature by feature and applies these conventions unevenly:

  • Versioning — one version, /api/v1, in the path. There is no /api/v2.
  • Paths — plural nouns, nested under their owner (/projects/{projectId}/participants/{id}); lowercase, kebab-case segments. Global resources sit directly under /api/v1 (/users, /metadata, /purge).
  • Verbs — GET read, POST create, PATCH field edit and state transition, DELETE remove. State transitions are their own endpoints (PATCH /{id}/disable|enable|block|unblock), each with its own @PreAuthorize.
  • Bodies / params — camelCase JSON. Pagination and filtering are query params (see below).
  • Errors — RegistryControllerAdvice returns a localized ErrorDto (HTTP status, stable code, i18n title/message); language from Accept-Language (en default, fr).
  • Known irregularities (frozen — one first-party client, not worth a breaking change): two transitions carry the value in the path — POST /projects/{projectId}/profiles/{id}/accept/{accepted} (boolean) and PATCH /projects/{projectId}/alerts/{id}/status/{status} (enum); the account-anonymisation endpoints are named impersonate.

Notation. The Permission column names the authority required. REGISTRY_USER_R (and other REGISTRY_* names without a PROJECT_ project segment) is a global check, hasAuthority('…'). A name shown as PROJECT_MOVEMENT_C is the project-scoped check hasPermission(projectId, 'REGISTRY_PROJECT_MOVEMENT_C'). option X marks an endpoint additionally gated by hasPermission(projectId, 'REGISTRY_PROJECT_OPTION_X'). See Security for enforcement and Roles & Permissions for who holds each.

List query grammar. List endpoints accept pageNumber (≥ 0, default 0) and pageSize (1–200, default 20), returning a page envelope (content + page metadata). Free-text search is textSearched (trigram-backed, ADR 006); other filters are flat typed params per endpoint (visibilitySearched, withProfile, availabilitySearched, dateTimeSearched, …). There is no general sort parameter. /search/* picker endpoints return a capped list (configured maximum, default 10), not a page. Bodies and query params are camelCase.

When registry.feature.documentation.enabled is true, springdoc serves the generated OpenAPI at /api-docs and Swagger UI at /swagger-ui.html (also at the root). The generated document is authoritative on payload shapes.

Authentication — /api/v1/authentication ​

MethodPathPurposePermission
GET/login/uri?redirectUri=Build the provider login URLpublic
GET/logout/uri?redirectUri=Build the provider logout URLpublic
POST/tokenExchange an authorization code for tokenspublic
POST/token/refreshExchange a refresh tokenpublic
GET/user/currentCurrent user, authorities and preferencesauthenticated

Users — /api/v1/users (global) ​

MethodPathPurposePermission
GET/Search / list usersREGISTRY_USER_R
GET/{id}Get a userREGISTRY_USER_R
GET/rolesAssignable global rolesREGISTRY_USER_METADATA_R
PATCH/{id}/roleChange a user's global role (body: role)REGISTRY_USER_U
PATCH/{id}/block · /{id}/unblockBlock / unblock an accountREGISTRY_USER_U
PATCH/{id}/impersonateAnonymise (GDPR scramble + purge) another userREGISTRY_USER_D
PATCH/impersonateAnonymise the caller's own accountauthenticated
DELETE/{id}Delete a userREGISTRY_USER_D

impersonate is a legacy name for anonymisation — it is not account switching. See Security → Data protection.

Preferences — /api/v1/users/preferences (self) ​

MethodPathPurposePermission
POST/themeSet the theme (param: theme ∈ SYSTEM/LIGHT/DARK)authenticated
POST/languageSet the language (param: language, e.g. en, fr)authenticated
POST/profile/selectSelect the active profile by profile idauthenticated
POST/projects/{projectId}/profile/selectSelect the active profile by project idauthenticated

My profiles — /api/v1/users/profiles (self) ​

MethodPathPurposePermission
GET/List the caller's project profilesauthenticated
POST/{id}/accept/{accepted}Accept (true) or reject (false) an invitation, from INVITEDauthenticated
POST/{projectId}/supportCreate a 1-hour support administrator profile on the projectREGISTRY_PROFILE_C
DELETE/{id}Leave a project (refused for the last permanent administrator)authenticated

Projects — /api/v1/projects ​

MethodPathPurposePermission
GET/List projects. Default withProfile=true (the caller's own); withProfile=false lists all and requires global REGISTRY_PROJECT_Rauthenticated
GET/{id}Get a projectglobal REGISTRY_PROJECT_R or PROJECT_R
GET/optionsAvailable option modulesREGISTRY_PROJECT_METADATA_R
POST/Create a project (creator becomes its administrator)REGISTRY_PROJECT_C
PATCH/{id}Update name / dates / optionsPROJECT_U
PATCH/{id}/disable · /{id}/enableSoft disable / enablePROJECT_U
DELETE/{id}Delete a projectPROJECT_D

Project profiles (membership) — /api/v1/projects/{projectId}/profiles ​

MethodPathPurposePermission
GET/ · /{id}List / get membersPROJECT_PROFILE_R
GET/search/usersUsers assignable to this projectPROJECT_PROFILE_METADATA_R
GET/rolesAssignable project rolesPROJECT_PROFILE_METADATA_R
POST/Invite one or more users (batch)PROJECT_PROFILE_C
PATCH/{id}Update role / access windowPROJECT_PROFILE_U
PATCH/{id}/block · /{id}/unblockBlock / unblock a memberPROJECT_PROFILE_U
DELETE/{id}Remove a memberPROJECT_PROFILE_D

Participants — /api/v1/projects/{projectId}/participants ​

MethodPathPurposePermission
GET/ · /{id}List / get participantsPROJECT_PARTICIPANT_R
GET/birthdayParticipants whose birthday is todayPROJECT_PARTICIPANT_R
GET/search/users · /search/groupsUsers linkable to a participant · groups a participant can joinPROJECT_PARTICIPANT_METADATA_R
GET/{id}/movementsA participant's movement historyPROJECT_PARTICIPANT_HISTORY_R
POST/Register a participantPROJECT_PARTICIPANT_C
PATCH/{id}Update a participantPROJECT_PARTICIPANT_U
PATCH/{id}/disable · /{id}/enableSoft disable / enablePROJECT_PARTICIPANT_U
DELETE/{id}Delete a participantPROJECT_PARTICIPANT_D

Groups — /api/v1/projects/{projectId}/groups ​

MethodPathPurposePermission
GET/ · /{id} · /{id}/membersList / get / list membersPROJECT_GROUP_R
GET/search/participantsParticipants assignable to a groupPROJECT_GROUP_METADATA_R
POST/Create a groupPROJECT_GROUP_C
PATCH/{id}Update a groupPROJECT_GROUP_U
PATCH/{id}/membersAdd members (body: participant ids)PROJECT_GROUP_U
DELETE/{id}/members/{memberId}Remove one memberPROJECT_GROUP_U
PATCH/{id}/disable · /{id}/enableSoft disable / enablePROJECT_GROUP_U
DELETE/{id}Delete a groupPROJECT_GROUP_D

Movements — /api/v1/projects/{projectId}/movements ​

MethodPathPurposePermission
GET/ · /contents · /{id}List / list with content / getPROJECT_MOVEMENT_R
GET/search/reasonsReasons and activities usable to justify a movementPROJECT_MOVEMENT_METADATA_R
GET/search/participants-and-groups · /search/vehiclesEntities movable in a movement · assignable vehiclesPROJECT_MOVEMENT_METADATA_R
GET/participants/statusLive participant headcount (present minors/majors, absent, guests on site)PROJECT_R
GET/vehicles/statusLive vehicle presencePROJECT_R · option VEHICLE
GET/{id}/communicationsMovement discussion threadPROJECT_MOVEMENT_COMMUNICATION_R · option COMMUNICATION
POST/ · /guestsRecord a registered movement / a guest movementPROJECT_MOVEMENT_C
PATCH/{id} · /guests/{id}Correct a registered / guest movementPROJECT_MOVEMENT_U
PATCH/{id}/disable · /{id}/enableSoft disable / enablePROJECT_MOVEMENT_U
DELETE/{id}Delete a movementPROJECT_MOVEMENT_D

Vehicles — /api/v1/projects/{projectId}/vehicles · option VEHICLE ​

MethodPathPurposePermission
GET/ · /{id}List / get vehiclesPROJECT_VEHICLE_R
GET/{id}/movementsA vehicle's movement historyPROJECT_VEHICLE_HISTORY_R
POST/Register a vehiclePROJECT_VEHICLE_C
PATCH/{id}Update a vehiclePROJECT_VEHICLE_U
PATCH/{id}/disable · /{id}/enableSoft disable / enablePROJECT_VEHICLE_U
DELETE/{id}Delete a vehiclePROJECT_VEHICLE_D

Activities — /api/v1/projects/{projectId}/activities · option ACTIVITY ​

MethodPathPurposePermission
GET/ · /{id}List / get activitiesPROJECT_ACTIVITY_R
GET/{id}/movementsAn activity's movement historyPROJECT_ACTIVITY_HISTORY_R
POST/Plan an activityPROJECT_ACTIVITY_C
PATCH/{id}Update an activityPROJECT_ACTIVITY_U
PATCH/{id}/disable · /{id}/enableSoft disable / enablePROJECT_ACTIVITY_U
DELETE/{id}Delete an activityPROJECT_ACTIVITY_D

Communications — /api/v1/projects/{projectId}/communications · option COMMUNICATION ​

MethodPathPurposePermission
GET/ · /{id}List / get communicationsPROJECT_COMMUNICATION_R
GET/search/movements · /search/alertsMovements / alerts a message can attach toPROJECT_COMMUNICATION_METADATA_R
POST/Post a messagePROJECT_COMMUNICATION_C
PATCH/{id}Edit a messagePROJECT_COMMUNICATION_U
PATCH/{id}/disable · /{id}/enableSoft disable / enablePROJECT_COMMUNICATION_U
DELETE/{id}Delete a messagePROJECT_COMMUNICATION_D

The two /search/* endpoints check only PROJECT_COMMUNICATION_METADATA_R — they are not behind the COMMUNICATION option gate that every other endpoint here carries.

Alerts — /api/v1/projects/{projectId}/alerts · option ALERT ​

MethodPathPurposePermission
GET/ · /{id}List / get alertsPROJECT_ALERT_R
GET/{id}/communicationsAlert discussion threadPROJECT_ALERT_COMMUNICATION_R
POST/Raise an alertPROJECT_ALERT_C
PATCH/{id}Edit an alertPROJECT_ALERT_U
PATCH/{id}/status/{status}Set status (IN_PROGRESS / RESOLVED / CANCELED) — enum in the pathPROJECT_ALERT_U
PATCH/{id}/disable · /{id}/enableSoft disable / enablePROJECT_ALERT_U
DELETE/{id}Delete an alertPROJECT_ALERT_D

Metadata — /api/v1/metadata (global) ​

Localized label lookups for the frontend. Authenticated; no special permission.

MethodPath
GET/presences/status · /availabilities/status · /profiles/status · /movements/types · /participants/types · /alerts/status

Purge (scheduled jobs) — /api/v1/purge ​

MethodPathPurposePermission
POST/users · /projects · /projects/contents · /projects/configurationsData-retention purges past a configurable age thresholdREGISTRY_JOB_C

REGISTRY_JOB_C is a global authority carried only by the USER_ADMINISTRATOR role (seed V1_9_0). There is no in-process scheduler: an external caller invokes these endpoints on the cron schedules in registry.feature.purge.*, authenticating as the system's non-human SERVICE_ACCOUNT user (provisioned with USER_ADMINISTRATOR). Any platform administrator can call them too.