AXIUM Identity API
Service central d'identité pour les applications AXIUM. Il gère l'authentification via OAuth2 et Keycloak, ainsi que le chargement des rôles et permissions de chaque utilisateur. Cette page vous montre comment vous connecter, rafraîchir un token, et gérer chaque cas de réponse possible.
Présentation
client_id / client_secret),
authentifie l'utilisateur via Keycloak, charge ses rôles et permissions, puis vous retourne
un access_token et un refresh_token.
Démarrage rapide
Nouveau sur cette API ? Voici les 3 étapes à connaître avant de coder.
Obtenir un token
Envoyez vos identifiants à POST /api/oauth/token. Vous recevez un
access_token valable 300 secondes.
Appeler l'API
Ajoutez le header Authorization: Bearer {access_token} à chaque requête
protégée.
Rafraîchir avant expiration
Utilisez POST /api/oauth/refresh avec le refresh_token pour
obtenir un nouveau couple de tokens sans redemander le mot de passe.
Flux d'authentification
- L'application cliente fournit son
client_idetclient_secret. - AXIUM Identity valide l'application.
- L'utilisateur est authentifié via Keycloak.
- Les rôles et permissions sont chargés.
- Un
access_tokenet unrefresh_tokensont retournés.
Connexion utilisateur
Authentifie un utilisateur et retourne ses tokens, rôles et permissions.
Paramètres
| Paramètre | Type | Obligatoire | Description |
|---|---|---|---|
client_id | string | Oui | Identifiant public de l'application cliente. |
client_secret | string | Oui | Secret privé fourni lors de la création de l'application. |
username | string | Oui | Email ou identifiant utilisateur. |
password | string | Oui | Mot de passe utilisateur. |
Exemple de requête
POST /api/oauth/token
Content-Type: application/json
{
"client_id": "axium-stock",
"client_secret": "xxxxxxxx",
"username": "byao@sifogroup.com",
"password": "123456"
}
Réponses possibles
Cliquez sur un code pour voir le format exact retourné par l'API.
{
"success": true,
"token_type": "Bearer",
"access_token": "eyJhbGciOiJSU.....",
"refresh_token": "eyJhbGciOiJI.....",
"expires_in": 300,
"user": {
"id": 1,
"email": "byao@sifogroup.com",
"first_name": "Benjamin",
"last_name": "YAO",
"active": true
},
"roles": [
"ROLE_USER",
"ROLE_ADMIN",
"ROLE_COMMERCIAL"
],
"permissions": [
"CREATE_USER",
"CREATE_CARD",
"CREATE_VOYAGE",
"VIEW_USER_DASHBOAD"
]
}
permissions si vous avez juste besoin de vérifier
des droits dans votre code (ex. if permissions.includes('CREATE_CARD')).
{
"success": false,
"error": {
"code": "INVALID_CLIENT",
"message": "Client inconnu.",
"details": []
}
}
client_id envoyé n'existe pas côté AXIUM Identity. Vérifiez qu'il correspond bien à celui de votre application.{
"success": false,
"error": {
"code": "INVALID_CLIENT_SECRET",
"message": "Client secret invalide.",
"details": []
}
}
client_id est correct mais le client_secret ne correspond pas.{
"success": false,
"error": {
"code": "AUTHENTICATION_FAILED",
"message": "Identifiants incorrects.",
"details": []
}
}
username existe mais le password est incorrect.{
"success": false,
"error": {
"code": "AUTHENTICATION_FAILED",
"message": "Utilisateur invalide.",
"details": []
}
}
code que ci-dessus (AUTHENTICATION_FAILED) mais message différent :
ici le username ne correspond à aucun compte. Si vous distinguez les deux cas côté
front, testez sur le champ message, pas seulement sur code.
{
"success": false,
"error": {
"code": "APP_ACCESS_DENIED",
"message": "Accès refusé. Votre compte ne dispose pas des autorisations requises pour utiliser cette application.",
"details": []
}
}
Rafraîchir un token
Génère un nouveau access_token à partir du refresh_token, sans redemander les identifiants.
Paramètres
| Paramètre | Type | Obligatoire | Description |
|---|---|---|---|
refresh_token | string | Oui | Token de rafraîchissement obtenu lors de la connexion. |
Exemple de requête
POST /api/oauth/refresh
Content-Type: application/json
{
"refresh_token": "eyJhbGciOi..."
}
Réponse — 200 OK
{
"success": true,
"token_type": "Bearer",
"access_token": "eyJhbGciOi...",
"refresh_token": "eyJhbGciOi...",
"expires_in": 300
}
refresh_token expiré ou invalide).Déconnexion
Révoque le refresh token et termine la session utilisateur côté Keycloak.
Paramètres
| Paramètre | Type | Obligatoire | Description |
|---|---|---|---|
refresh_token | string | Oui | Refresh token à invalider. |
Exemple de requête
POST /api/oauth/logout
Content-Type: application/json
{
"refresh_token": "eyJhbGciOi..."
}
Réponse — 200 OK
{
"success": true,
"message": "Déconnexion réussie."
}
Utiliser le token
Toutes les API protégées nécessitent l'ajout du header HTTP suivant à chaque requête :
Authorization: Bearer {access_token}
Créer un utilisateur
Crée un nouvel utilisateur et l'associe à l'application cliente appelante. Si un utilisateur possédant déjà cet email existe, il est mis à jour et l'application cliente lui est simplement ajoutée (aucune duplication de compte).
Paramètres
| Paramètre | Type | Obligatoire | Description |
|---|---|---|---|
client_id | string | Oui | Identifiant de l'application cliente qui sera associée à l'utilisateur. |
email | string | Non | Email de l'utilisateur. Il peut être absent si le compte est identifié autrement. |
firstName | string | Oui | Prénom de l'utilisateur. |
lastName | string | Oui | Nom de l'utilisateur. |
phone | string | Non | Numéro de téléphone au format international (ex: +2250709502322). |
password | string | Oui | Mot de passe de l'utilisateur. |
Exemple de requête
POST /api/user/create
Content-Type: application/json
{
"client_id": "op0a1a84-f8a6-461a-graz1-fd32fdcbf2cb",
"email": "byao@sifogroup.com",
"firstName": "Benjamin",
"lastName": "YAO",
"phone": "+2250709502322",
"password": "123456"
}
Réponses possibles
Cliquez sur un code pour voir le format exact retourné par l'API.
{
"success": true,
"message": "Utilisateur créé avec succès.",
"client": "Axium Stock",
"user": {
"id": 14,
"email": "byao@sifogroup.com"
}
}
email fourni n'existe encore dans aucun
compte AXIUM Identity. Un nouvel utilisateur est créé à la fois côté Keycloak et côté base AXIUM Identity,
puis associé à l'application client_id fournie.
{
"success": true,
"message": "Utilisateur modifié avec succès.",
"client": "Axium Stock",
"user": {
"id": 7,
"email": "byao@sifogroup.com"
}
}
email (ou ce keycloak_id) existe
déjà. Le compte n'est pas dupliqué : l'application cliente client_id est simplement
ajoutée à la liste des applications de l'utilisateur existant, et ses informations
(nom, téléphone, etc.) sont mises à jour avec celles envoyées.
{
"success": false,
"message": "Client application invalide."
}
client_id envoyé n'existe pas côté AXIUM Identity.Importer des employés depuis Excel
Importe un fichier Excel d'employés et crée ou met à jour chaque compte utilisateur associé à l'application cliente. Le fichier doit respecter le modèle officiel avec les colonnes matricule, nom, prenoms, date_entree, date_embauche et nom_utilisateur.
multipart/form-data car il reçoit un fichier Excel.Paramètres
| Paramètre | Type | Obligatoire | Description |
|---|---|---|---|
client_id | string | Oui | Identifiant public de l'application cliente concernée. |
employeeFile | file | Oui | Fichier Excel (.xlsx ou .xls) contenant la liste des employés à importer. |
Structure du fichier Excel attendu
| Colonne | Exemple | Description |
|---|---|---|
matricule | EMP-001 | Matricule interne de l'employé. |
nom | YAO | Nom de famille. |
prenoms | Benjamin | Prénoms. |
date_entree | 01/09/2026 | Date d'entrée. |
date_embauche | 01/09/2026 | Date d'embauche. |
nom_utilisateur | byao | Identifiant utilisateur à créer ou utiliser. |
Exemple de requête
POST /api/user/create/by-import Content-Type: multipart/form-data client_id: AXIUM_RH employeeFile: employes.xlsx
Réponses possibles
Cliquez sur un code pour voir le format exact retourné par l'API.
{
"success": true,
"message": "Import des employés terminé avec succès.",
"client": "AXIUM RH",
"created": 2,
"skipped": 0,
"total": 2,
"data": [
{
"action": "EDIT"
"uuid": "01a0240d-8261-7699-82db-ebe2a927fce6",
"username": "byao",
"email": "byao@sifogroup.com",
"firstName": "KOUAKOU BENJAMIN",
"lastName": "YAO",
"fullName": "YAO BENJAMIN",
"phone": 0709502322,
"active": true,
"avatar": "https://127.0.0.1:8080/uploads/avatars/019f8ea8-4ad9-7291-ad2f-8a48c23be5f7.jpg",
"signature": "https://127.0.0.1:8080/uploads/signatures/kouakou-benjamin-yao-signature-6a87401371222.png",
"stamp": "https://127.0.0.1:8080/uploads/stamps/kouakou-benjamin-yao-stamp-6a87400591e70.png",
"companyName": OPTIMUM SOLUTIONS,
"matricule": "EMP-001",
"dateEntree": "01/09/2026",
"dateEmbauche": "01/09/2026"
},
{
"action": "CREATE"
"uuid": "01a0ac27-6d4a-7731-8612-e40c0dcc5325",
"username": "akone",
"email": null,
"firstName": "ADJOUA",
"lastName": "KONE",
"fullName": "KONE ADJOUA",
"phone": null,
"active": true,
"avatar": null,
"signature": null,
"stamp": null,
"companyName": null,
"matricule": "EMP-002",
"dateEntree": "02/09/2026",
"dateEmbauche": "02/09/2026"
}
]
}
created compte les lignes réellement traitées, skipped les lignes ignorées (ex. prénom ou nom vide), et data contient le détail de chaque création ou mise à jour. Le champ action vaut CREATE ou EDIT selon le cas.
{
"success": false,
"message": "Payload JSON invalide."
}
{
"success": false,
"message": "Payload JSON invalide."
}
client_id envoyé n'existe pas côté AXIUM Identity.{
"success": false,
"message": "Payload JSON invalide."
}
nom, prenoms et nom_utilisateur.Modifier un utilisateur
Met à jour un utilisateur existant identifié par son uuid et l'associe à l'application cliente appelante. Cette route cible un compte précis pour éviter toute ambiguïté lors des mises à jour.
Paramètres
| Paramètre | Type | Obligatoire | Description |
|---|---|---|---|
client_id | string | Oui | Identifiant de l'application cliente qui est utilisée pour la mise à jour. |
uuid | string | Oui | UUID unique de l'utilisateur à modifier. Il sert de clé de ciblage. |
email | string | Non | Nouvelle adresse email de l'utilisateur. |
firstName | string | Non | Prénom de l'utilisateur. Peut être omis lors d'une modification. |
lastName | string | Non | Nom de l'utilisateur. Peut être omis lors d'une modification. |
phone | string | Non | Nouveau numéro de téléphone. |
Exemple de requête
POST /api/user/update
Content-Type: application/json
{
"client_id": "op0a1a84-f8a6-461a-graz1-fd32fdcbf2cb",
"firstName": "KOUAKOU BENJAMIN",
"lastName": "YAO"
}
Réponses possibles
Cliquez sur un code pour voir le format exact retourné par l'API.
{
"success": true,
"message": "Utilisateur créé avec succès.",
"client": "AXIUM TRANSPORT",
"user": {
"uuid": "01a0629f-e89b-7a6f-be77-16245efce7ae",
"email": null,
"username": "byao",
"firstName": "KOUAKOU BENJAMIN",
"lastName": "YAO",
"fullName": "YAO KOUAKOU BENJAMIN",
"phone": null,
"active": true,
"avatar": null,
"signature": null,
"stamp": null,
"companyName": null,
"roles": []
}
}
uuid.
Cela évite de modifier n'importe quel compte lorsqu'il y a plusieurs profils avec des données proches.
{
"success": false,
"message": "Le uuid est obligatoire pour modifier un utilisateur."
}
uuid est absent ou vide. La route refuse d'aller plus loin pour éviter une modification non ciblée.{
"success": false,
"message": "Client application invalide."
}
client_id fourni n'existe pas côté AXIUM Identity.{
"success": false,
"message": "Utilisateur introuvable pour ce uuid."
}
uuid.Réinitialiser le mot de passe
Remplace le mot de passe d'un utilisateur existant ciblé par son username.
Paramètres
| Paramètre | Type | Obligatoire | Description |
|---|---|---|---|
client_id | string | Oui | Identifiant public de l'application cliente. |
username | string | Oui | Username AXIUM IDENTITY de l'utilisateur à modifier. |
password | string | Oui | Nouveau mot de passe à appliquer. |
Exemple de requête
POST /api/user/reset-password
Content-Type: application/json
{
"client_id": "axium-stock",
"username": "byao",
"password": "NouveauMotDePasse123!"
}
Réponses possibles
Cliquez sur un code pour voir le format exact retourné par l'API.
{
"success": true,
"message": "Mot de passe réinitialisé avec succès."
}
{
"success": false,
"message": "Client application invalide."
}
client_id envoyé n'existe pas côté AXIUM Identity.{
"success": false,
"message": "Utilisateur introuvable."
}
username fourni.{
"success": false,
"message": "Le nouveau mot de passe est invalide."
}
Lister les utilisateurs par rôle ou permission
Retourne la liste des comptes qui correspondent à un rôle donné, ou à une permission donnée. Vous pouvez passer role ou permission, ou les deux si vous souhaitez filtrer plus finement.
Paramètres
| Paramètre | Type | Obligatoire | Description |
|---|---|---|---|
client_id | string | Oui | Identifiant public de l'application cliente. |
role | string | Non | Filtre sur un rôle tel que ROLE_USER. |
permission | string | Non | Filtre sur une permission telle que CREATE_USER. |
Exemples de requêtes
GET /api/user/list?client_id=axium-stock&role=ROLE_USER
GET /api/user/list?client_id=axium-stock&permission=CREATE_USER
Réponses possibles
{
"success": true,
"client": "Axium Stock",
"count": 2,
"users": [
{
"id": 12,
"uuid": "01a0629f-e89b-7a6f-be77-16245efce7ae",
"email": "byao@sifogroup.com",
"firstName": "Benjamin",
"lastName": "YAO",
"fullName": "YAO Benjamin",
"roles": ["ROLE_USER"]
},
{
"id": 27,
"uuid": "5fcb1dc4-5581-4b52-a1b7-2d14deec5c52",
"email": "ctraore@sifogroup.com",
"firstName": "Cyrille",
"lastName": "TRAORE",
"fullName": "TRAORE Cyrille",
"roles": ["ROLE_USER"]
}
]
}
CREATE_USER.
{
"success": false,
"message": "Au moins un paramètre est requis : role ou permission."
}
role ou permission est absent. La route refuse l'appel pour éviter une liste non filtrée.{
"success": false,
"message": "Client application invalide."
}
client_id ne correspond à aucune application autorisée.Uploader un avatar
Permet à une application cliente de mettre à jour la photo de profil d'un utilisateur. Le fichier est stocké et traité entièrement côté AXIUM Identity — l'application cliente ne fait que transmettre le fichier reçu depuis son formulaire.
multipart/form-data (et non du JSON), car un fichier est envoyé.Paramètres
| Paramètre | Type | Obligatoire | Description |
|---|---|---|---|
client_id | string | Oui | Identifiant public de l'application cliente. |
email | string | Oui | Email de l'utilisateur concerné. |
avatar | file | Oui | Fichier image. Formats acceptés : JPEG, PNG, WEBP. Taille max : 2 Mo. |
Exemple de requête
POST /api/user/avatar/upload Content-Type: multipart/form-data client_id: axium-stock email: byao@sifogroup.com avatar: (fichier binaire, ex: photo.jpg)
Réponses possibles
Cliquez sur un code pour voir le format exact retourné par l'API.
{
"success": true,
"message": "Avatar mis à jour avec succès.",
"client": "Axium Stock",
"user": {
"id": 1,
"email": "byao@sifogroup.com",
"avatar_url": "https://api.identity.optimumci.com/uploads/avatars/0190f3c2-....jpg"
}
}
avatar_url est une URL directement utilisable dans un
<img src="...">. L'ancien avatar de l'utilisateur (s'il existait) est automatiquement supprimé côté serveur.
{
"success": false,
"message": "Aucun fichier avatar fourni."
}
avatar est absent de la requête, ou n'a pas été envoyé comme fichier (type File, pas Text).{
"success": false,
"message": "Client application invalide."
}
client_id envoyé n'existe pas côté AXIUM Identity.{
"success": false,
"message": "Utilisateur introuvable."
}
email fourni.{
"success": false,
"message": "L'image ne doit pas dépasser 2 Mo."
}
Format des erreurs
Toutes les erreurs retournées par AXIUM Identity utilisent ce format JSON uniforme, quel que soit l'endpoint :
{
"success": false,
"error": {
"code": "ERROR_CODE",
"message": "Message utilisateur",
"details": []
}
}
success en premier dans votre code. S'il vaut
false, allez lire error.code (stable, pour votre logique) et
error.message (déjà en français, pour l'affichage à l'utilisateur).
Codes d'erreur possibles
| Code | Statut HTTP | Message | Cause |
|---|---|---|---|
INVALID_CLIENT | 401 | Client inconnu. | client_id introuvable. |
INVALID_CLIENT_SECRET | 401 | Client secret invalide. | client_secret incorrect pour ce client_id. |
AUTHENTICATION_FAILED | 401 | Identifiants incorrects. | Mot de passe erroné. |
AUTHENTICATION_FAILED | 401 | Utilisateur invalide. | Utilisateur introuvable. |
APP_ACCESS_DENIED | 403 | Accès refusé. Votre compte ne dispose pas des autorisations requises pour utiliser cette application. | Compte valide mais non autorisé sur cette application cliente. |
Codes HTTP
| Code | Description |
|---|---|
| 200 | Opération réussie. |
| 400 | Requête invalide ou paramètre manquant. |
| 401 | Authentification échouée ou client invalide. |
| 403 | Compte ou application non autorisé. |
| 422 | Fichier invalide (format ou taille non conforme). |
| 500 | Erreur interne du service AXIUM Identity. |