> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.goodflag.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.goodflag.com/_mcp/server.

# Provisionnement des utilisateurs

> Création, idempotence par email, cycle de vie, contacts, organisations

# Provisionnement des utilisateurs

Les personnes qui interviennent dans vos parapheurs — gestionnaires, signataires,
validateurs — sont des **utilisateurs** de votre tenant. Avant de les faire intervenir, il
faut les **provisionner** : les créer, ou réutiliser ceux qui existent déjà. Chaque
utilisateur appartient à **un groupe** (fondation [*Groupes, rôles & droits*](/wm/api-reference/concepts/groupes-roles-droits)), qui porte ses droits.

## Créer un utilisateur

```http
POST /api/tenants/{tenantId}/users
Authorization: Bearer act_<id>.<secret>
Content-Type: application/json

{
  "groupId": "grp_…",
  "email": "roy.neary@example.org",
  "firstName": "Roy",
  "lastName": "Neary",
  "phoneNumber": "+33 6 12 34 56 78",
  "country": "FR"
}
```

| Champ                | Type                   | Rôle                                                                                                                                                                                                                                                                                                                                                                 |
| -------------------- | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `groupId`            | String                 | **Groupe** de l'utilisateur — donc ses **droits** (fondation [*Groupes, rôles & droits*](/wm/api-reference/concepts/groupes-roles-droits)).                                                                                                                                                                                                                          |
| `email`              | String                 | Adresse e-mail.                                                                                                                                                                                                                                                                                                                                                      |
| `firstName`          | String                 | Prénom.                                                                                                                                                                                                                                                                                                                                                              |
| `lastName`           | String                 | Nom.                                                                                                                                                                                                                                                                                                                                                                 |
| `phoneNumber`        | String *(facultatif)*  | Numéro de téléphone au **format international commençant par `+` et l'indicatif pays** (ex. `+33612345678` ou `+33 6 12 34 56 78`) — voir la note ci‑dessous. Exigé par plusieurs pages de consentement, et pas seulement celles qui authentifient par **OTP SMS** — voir section [*Organisations & fonction du signataire*](#organisations-fonction-du-signataire). |
| `country`            | String *(facultatif)*  | Pays de l'utilisateur (son rôle exact dépend du niveau de signature requis — voir la fondation [*Pages de consentement*](/wm/api-reference/concepts/pages-de-consentement) et les cas d'usage).                                                                                                                                                                      |
| `isDisabled`         | Boolean *(facultatif)* | Utilisateur désactivé ou non.                                                                                                                                                                                                                                                                                                                                        |
| `picture`            | String *(facultatif)*  | Image (URL ou *data URI*).                                                                                                                                                                                                                                                                                                                                           |
| `comments`           | String *(facultatif)*  | Commentaires libres.                                                                                                                                                                                                                                                                                                                                                 |
| `subject`            | String *(facultatif)*  | Identifiant de l'utilisateur dans votre fournisseur d'identité externe (SSO).                                                                                                                                                                                                                                                                                        |
| `organizationTitles` | Array *(facultatif)*   | Fonctions de l'utilisateur : liste d'objets `{ organizationId, title }` (l'`organizationId` et le `title` peuvent apparaître sur le pavé de signature).                                                                                                                                                                                                              |

`groupId`, `email`, `firstName` et `lastName` sont **requis**. L'appel s'authentifie avec
un jeton d'API dont l'utilisateur porte les droits nécessaires (par ex. *Administrateur
des utilisateurs*, ou une **autorisation inter-groupes** de création — fondation [*Groupes, rôles & droits*](/wm/api-reference/concepts/groupes-roles-droits)).

> **Format du `phoneNumber`.** Le numéro doit être **international, commençant par `+`
> suivi de l'indicatif pays** (E.164). Les **espaces sont facultatifs** : `+33612345678`
> et `+33 6 12 34 56 78` sont tous deux acceptés, et l'API **renvoie une forme normalisée**
> (regroupée par blocs selon le pays). En revanche :
>
> * un **numéro national** sans indicatif (`0612345678`) est **rejeté** (`InvalidRequestField`) —
>   la plateforme n'a pas de « pays par défaut » et ne peut pas le déduire ;
> * ⚠️ le préfixe d'appel **`00`** (`0033612345678`) n'est **pas** reconnu comme préfixe
>   international : il est **accepté sans erreur mais mal interprété** (aboutit à un numéro
>   erroné) — n'utilisez **jamais** `00`, toujours **`+`**.
>
> Autrement dit, il n'est pas nécessaire de connaître le « format d'affichage » d'un
> pays : il suffit de fournir `+<indicatif><numéro>`, la mise en forme est faite par la
> plateforme.

La réponse renvoie l'utilisateur créé (identifiant préfixé `usr_`), enrichi de champs
**calculés** :

```json
{
  "id": "usr_LqVk5fa8mxFccrfBRAi433Ry",
  "groupId": "grp_…",
  "email": "roy.neary@example.org",
  "firstName": "Roy", "lastName": "Neary", "name": "Roy Neary",
  "phoneNumber": "+33 6 12 34 56 78", "country": "FR",
  "signAllowed": true, "approveAllowed": true, "comanageAllowed": false,
  "isDisabled": false, "lastLogin": 0,
  "tenantId": "ten_…", "created": 1782821445591, "updated": 1782821445591
}
```

* `name` — nom complet calculé (`firstName` + `lastName`).
* `signAllowed` / `approveAllowed` / `comanageAllowed` — **capacités déduites des rôles du
  groupe** (indicateurs en lecture seule) : l'utilisateur peut-il signer, valider, cogérer.
* `viewAuthorizedGroups` — groupes autorisés à voir cet utilisateur.

## Réutiliser un utilisateur existant (idempotence par e-mail)

Au sein d'un tenant, une adresse e-mail est **unique** : deux utilisateurs ne peuvent pas
partager le même e-mail. Avant de créer l'utilisateur, réfléchissez aux différentes options possibles :

* **Ne tenez pas compte de l'existant et créez le compte même s'il existe déjà** : cette option est particulièrement pertinente si votre application est la seule à utiliser l'utilisateur en question et vous maîtrisez alors complètement à l'instant t la définition de l'utilisateur avec la requête POST ci-dessus.
* **Recherchez l'utilisateur par e-mail et réutilisez le compte s'il existe déjà** : cette option est particulièrement pertinente si d'autres applications ont besoin d'accéder à cet utilisateur ou bien si l'utilisateur dispose du droit de se connecter au portail ; dans ce cas utilisez la requête ci-dessous.

```http
GET /api/users?items.email=roy.neary@example.org
```

→ la réponse contient un tableau `items` ; si un utilisateur **actif** correspond,
réutilisez son `id` plutôt que d'en recréer un. Sinon, créez-le (section [*Créer un utilisateur*](#creer-un-utilisateur)). Ce contrôle
d'idempotence se fait côté application.

## Cycle de vie d'un utilisateur

* **Consulter** — `GET /api/users/{id}` ; `GET /api/users/me` renvoie l'utilisateur du
  jeton d'API courant.
* **Modifier** — `PATCH /api/users/{id}` (concurrence optimiste `If-Match`, fondation [*Structure > Concurrence : l'en-tête conditionnel `If-Match`*](/wm/api-reference/structure#concurrence-len-tete-conditionnel-if-match)) : mettre à jour l'identité, le téléphone, le pays, le groupe…
* **Anonymiser** — un utilisateur ne se **supprime** pas ; il s'**anonymise** (finalité
  RGPD), via l'endpoint dédié (*Anonymize user*).
* **Rechercher** — `GET /api/users` avec filtres `items.<champ>` (`items.email`,
  `items.groupId`, `items.isDisabled`…) et pagination (fondation [*Structure > Recherche & pagination*](/wm/api-reference/structure#recherche-pagination)).

## Contacts : des signataires privés à un utilisateur

Outre les utilisateurs, l'API permet de gérer des **contacts** propres à un utilisateur. Un contact est une personne (signataire ou validateur) qu'un utilisateur enregistre **pour son propre usage** :

```http
POST /api/users/{userId}/contacts
```

Champs : `email`, `firstName`, `lastName` (requis), `phoneNumber`, `country`, `comments`
(facultatifs) ; l'identifiant renvoyé est préfixé `con_`. Créer des contacts requiert le
rôle **Créateur de contacts** (`contactCreator`, fondation [*Groupes, rôles & droits*](/wm/api-reference/concepts/groupes-roles-droits)). Ainsi, un utilisateur
autorisé à créer des parapheurs peut désigner, pour ses étapes de signature ou de
validation, **soit des utilisateurs, soit ses propres contacts**.

**Particularités importantes :**

* Un contact est **propre et exclusif à l'utilisateur qui l'a créé** : personne d'autre n'y
  a accès, y compris un superadministrateur. Un utilisateur, à l'inverse, est partagé à l'échelle du tenant.
* Un document signé par un contact **n'apparaît pas** dans le compte Goodflag de cette
  personne — même si elle en possède un sur le tenant où le parapheur a été créé.

**Quand les utiliser ?** Les contacts conviennent surtout aux **organisations cloisonnées**,
où l'on ne souhaite pas partager les informations des signataires entre utilisateurs.

**Recommandation.** Dans un déploiement d'entreprise, **préférez provisionner les
signataires comme utilisateurs** : ils sont réutilisables d'un service à l'autre. Un
signataire client qui signe un bon de commande émis par le service commercial pourra ainsi
être également signataire d'un accord de confidentialité émis par le service juridique.

> Dans la suite de cette documentation et dans les cas d'usage, **les signataires et les
> validateurs sont toujours des utilisateurs**.

## Organisations & fonction du signataire

Un signataire peut signer **au nom d'une organisation** (en tant que représentant) et faire
apparaître une **fonction** sur sa signature (par exemple « Membre », « Directeur des
achats », « Par délégation de pouvoir de Mme XYZ », …).

### Quand le téléphone est-il exigé ?

Le réflexe est d'associer `phoneNumber` à la seule authentification par **OTP SMS**. C'est
insuffisant : **plusieurs pages de consentement l'exigent**, pour des raisons différentes. C'est
notamment le cas de la page de **signature avancée conforme au standard ETSI LCP**, qui procède à
une **vérification de la pièce d'identité** — et cela sans que l'authentification passe par un
code SMS.

La règle pratique est donc plus simple à retenir dans l'autre sens : **renseignez le téléphone dès
que vous le connaissez**, plutôt que de chercher à deviner si le niveau de signature visé
l'imposera. Un numéro inutile ne coûte rien ; un numéro manquant interrompt la signature au moment
le plus visible, devant le signataire.

### Les organisations

Une organisation se crée au niveau du tenant (identifiant renvoyé préfixé `org_`) :

```http
POST /api/tenants/{tenantId}/organizations
{ "name": "Goodflag", "organizationIdentifier": "NTRFR-480622257" }
```

| Champ                    | Rôle                                                                                                 |
| ------------------------ | ---------------------------------------------------------------------------------------------------- |
| `name`                   | Nom de l'organisation (requis).                                                                      |
| `organizationIdentifier` | Identifiant au sens **ETSI EN 319 412-1** — préfixe `VAT` ou `NTR` (ex. `NTRFR-480622257`) (requis). |
| `additionalInfo`         | Informations complémentaires *(facultatif)*.                                                         |

### La fonction du signataire

La **fonction** (titre) est toujours rattachée à une organisation. On peut la définir :

* **sur l'utilisateur**, via `organizationTitles` — une liste d'objets
  `{ organizationId, title }` (section [*Créer un utilisateur*](#creer-un-utilisateur)) ;
* **sur le destinataire d'une étape**, via `organizationId` + `title` — ce qui **prime**
  pour cette étape (la même personne peut ainsi signer avec une fonction différente d'un
  parapheur à l'autre).

Le `title` est le libellé affiché (« Membre », « Président de séance »…). Pour qu'un
signataire puisse signer au nom d'une organisation, la **page de consentement** doit
l'autoriser (`allowOrganization`, voir la fondation [*Pages de consentement*](/wm/api-reference/concepts/pages-de-consentement)).

**Le modèle en une phrase** : les organisations existent indépendamment des utilisateurs ; on
rattache ensuite un utilisateur à une organisation, et c'est à ce moment qu'on lui donne sa
fonction. Un utilisateur peut appartenir à **plusieurs organisations**, mais il ne peut avoir
qu'**une seule fonction par organisation** — le couple est unique. Pour lui en attribuer une
autre au sein de la même organisation, on retire le couple `{ organizationId, title }` et on en
recrée un.

> ⚠️ **Le `title` envoyé sur le destinataire n'est pas restitué.** En relisant un parapheur créé
> avec `organizationId` **et** `title` sur son destinataire, on retrouve l'`organizationId` mais
> **pas** le `title`. Deux lectures possibles — le champ est ignoré, ou il est conservé sans être
> renvoyé — et l'API ne permet pas de trancher. Conséquence pratique : ne comptez pas sur une
> relecture pour vérifier la fonction ; contrôlez-la sur le **document signé**, où le cartouche
> l'affiche (fondation [*Profils de signature*](/wm/api-reference/concepts/profils-de-signature)).

> ⚠️ **L'organisation n'est pas héritée de la fiche.** Désigner un destinataire par son `userId`
> reprend bien son identité — e-mail, nom, téléphone, pays — mais **ni son organisation ni sa
> fonction** — et pour une raison de fond : une personne peut appartenir à **plusieurs**
> organisations, avec une fonction dans chacune. La plateforme ne peut donc pas deviner laquelle
> s'applique à ce parapheur, et c'est à vous de la **choisir**. Le destinataire reste sinon
> dépourvu d'`organizationId` et de `title`. La voie
> « sur le destinataire » n'est donc pas seulement prioritaire, elle est **la seule** qui fasse
> réellement porter l'organisation par le parapheur. Renseignez `organizationId` + `title` à la
> création, même lorsque la fiche de l'utilisateur les contient déjà.

> La fonction et l'organisation peuvent apparaître sur le **cartouche de signature**, via le
> gabarit du **profil de signature** (`{{signerOrganizationTitle}}`, `{{signerOrganization}}`) —
> voir la fondation [*Profils de signature*](/wm/api-reference/concepts/profils-de-signature).

## Bonnes pratiques

* **Tenir l'identité à jour** (`firstName`, `lastName`, `phoneNumber`, `country`) **avant**
  de faire intervenir l'utilisateur comme signataire : ces informations alimentent la
  signature (le détail est traité dans les cas d'usage).
* **Idempotence** : rechercher par e-mail avant de créer (section [*Réutiliser un utilisateur existant (idempotence par e-mail)*](#reutiliser-un-utilisateur-existant-idempotence-par-e-mail)).
* Dans un parapheur, **référencer un signataire par son `userId`** : l'identité est alors
  reprise de sa fiche (voir les cas d'usage) — **à l'exception de l'organisation et de la
  fonction**, à porter explicitement sur le destinataire (section [*Organisations & fonction du signataire*](#organisations-fonction-du-signataire)).