Créer ou mettre à jour un utilisateur
Créer et mettre à jour un utilisateur sont la même opération et partagent le même corps UpsertUserRequest. POST …/users crée l'utilisateur — ou le met à jour si l'email existe déjà. PUT …/users/{uid} met à jour un utilisateur connu par son UID. Les deux renvoient 200.
Avant de commencer, assurez-vous d'avoir un jeton d'accès valide — voir la Vue d'ensemble pour les détails d'authentification.
Étape 1 — Vérifier si l'utilisateur existe
Utilisez la référence de recherche pour rechercher l'utilisateur par email ou par nom. Une correspondance signifie que vous mettrez à jour un utilisateur existant ; aucune correspondance signifie que vous en créerez un nouveau.
Étape 2 — Rassembler les UID à attribuer
Collectez les UID de groupe et de permission que vous souhaitez attribuer à l'utilisateur. Consultez la référence de recherche pour savoir comment les récupérer depuis les points de terminaison des groupes et des permissions.
Étape 3 — Envoyer la requête
Créer ou upsert par email
POST /v2/organizations/DEMO/users
- Python
- PHP
- JavaScript
- Java
- Go
- C#
import requests
BASE_URL = "https://api.stonal.io/users"
TOKEN = "<access_token>"
resp = requests.post(
f"{BASE_URL}/v2/organizations/DEMO/users",
headers={"Authorization": f"Bearer {TOKEN}"},
json={
"email": "john.doe@example.com",
"firstName": "John",
"lastName": "Doe",
"userGroupUids": ["019619df-4768-76b7-81e3-2c56d374df46"],
"permissions": [{"uid": "019619df-4767-730f-8d31-143712a08141"}],
},
)
print(resp.status_code, resp.json())
<?php
$baseUrl = "https://api.stonal.io/users";
$token = "<access_token>";
$ch = curl_init("$baseUrl/v2/organizations/DEMO/users");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ["Authorization: Bearer $token", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => json_encode([
"email" => "john.doe@example.com",
"firstName" => "John",
"lastName" => "Doe",
"userGroupUids" => ["019619df-4768-76b7-81e3-2c56d374df46"],
"permissions" => [["uid" => "019619df-4767-730f-8d31-143712a08141"]],
]),
]);
$response = curl_exec($ch);
echo curl_getinfo($ch, CURLINFO_HTTP_CODE) . PHP_EOL . $response;
curl_close($ch);
const baseUrl = "https://api.stonal.io/users";
const token = "<access_token>";
const res = await fetch(`${baseUrl}/v2/organizations/DEMO/users`, {
method: "POST",
headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
body: JSON.stringify({
email: "john.doe@example.com",
firstName: "John",
lastName: "Doe",
userGroupUids: ["019619df-4768-76b7-81e3-2c56d374df46"],
permissions: [{ uid: "019619df-4767-730f-8d31-143712a08141" }],
}),
});
console.log(res.status, await res.json());
import java.net.URI;
import java.net.http.*;
String baseUrl = "https://api.stonal.io/users";
String token = "<access_token>";
String body = """
{"email":"john.doe@example.com","firstName":"John","lastName":"Doe",
"userGroupUids":["019619df-4768-76b7-81e3-2c56d374df46"],
"permissions":[{"uid":"019619df-4767-730f-8d31-143712a08141"}]}""";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(baseUrl + "/v2/organizations/DEMO/users"))
.header("Authorization", "Bearer " + token)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(body))
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode() + " " + response.body());
package main
import (
"bytes"
"fmt"
"io"
"net/http"
)
func main() {
baseURL := "https://api.stonal.io/users"
token := "<access_token>"
body := []byte(`{"email":"john.doe@example.com","firstName":"John","lastName":"Doe","userGroupUids":["019619df-4768-76b7-81e3-2c56d374df46"],"permissions":[{"uid":"019619df-4767-730f-8d31-143712a08141"}]}`)
req, _ := http.NewRequest("POST", baseURL+"/v2/organizations/DEMO/users", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+token)
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
out, _ := io.ReadAll(resp.Body)
fmt.Println(resp.StatusCode, string(out))
}
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
var baseUrl = "https://api.stonal.io/users";
var token = "<access_token>";
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
var json = """
{"email":"john.doe@example.com","firstName":"John","lastName":"Doe",
"userGroupUids":["019619df-4768-76b7-81e3-2c56d374df46"],
"permissions":[{"uid":"019619df-4767-730f-8d31-143712a08141"}]}
""";
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client.PostAsync($"{baseUrl}/v2/organizations/DEMO/users", content);
Console.WriteLine($"{(int)response.StatusCode} {await response.Content.ReadAsStringAsync()}");
Mettre à jour par UID
PUT /v2/organizations/DEMO/users/019619df-4768-76b7-81e3-2c56d374df46
- Python
- PHP
- JavaScript
- Java
- Go
- C#
import requests
BASE_URL = "https://api.stonal.io/users"
TOKEN = "<access_token>"
resp = requests.put(
f"{BASE_URL}/v2/organizations/DEMO/users/019619df-4768-76b7-81e3-2c56d374df46",
headers={"Authorization": f"Bearer {TOKEN}"},
json={
"email": "john.doe@example.com",
"firstName": "John",
"lastName": "Doe",
"userGroupUids": ["019619df-4768-76b7-81e3-2c56d374df46"],
"permissions": [{"uid": "019619df-4767-730f-8d31-143712a08141"}],
},
)
print(resp.status_code, resp.json())
<?php
$baseUrl = "https://api.stonal.io/users";
$token = "<access_token>";
$ch = curl_init("$baseUrl/v2/organizations/DEMO/users/019619df-4768-76b7-81e3-2c56d374df46");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_HTTPHEADER => ["Authorization: Bearer $token", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => json_encode([
"email" => "john.doe@example.com",
"firstName" => "John",
"lastName" => "Doe",
"userGroupUids" => ["019619df-4768-76b7-81e3-2c56d374df46"],
"permissions" => [["uid" => "019619df-4767-730f-8d31-143712a08141"]],
]),
]);
$response = curl_exec($ch);
echo curl_getinfo($ch, CURLINFO_HTTP_CODE) . PHP_EOL . $response;
curl_close($ch);
const baseUrl = "https://api.stonal.io/users";
const token = "<access_token>";
const res = await fetch(`${baseUrl}/v2/organizations/DEMO/users/019619df-4768-76b7-81e3-2c56d374df46`, {
method: "PUT",
headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
body: JSON.stringify({
email: "john.doe@example.com",
firstName: "John",
lastName: "Doe",
userGroupUids: ["019619df-4768-76b7-81e3-2c56d374df46"],
permissions: [{ uid: "019619df-4767-730f-8d31-143712a08141" }],
}),
});
console.log(res.status, await res.json());
import java.net.URI;
import java.net.http.*;
String baseUrl = "https://api.stonal.io/users";
String token = "<access_token>";
String body = """
{"email":"john.doe@example.com","firstName":"John","lastName":"Doe",
"userGroupUids":["019619df-4768-76b7-81e3-2c56d374df46"],
"permissions":[{"uid":"019619df-4767-730f-8d31-143712a08141"}]}""";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(baseUrl + "/v2/organizations/DEMO/users/019619df-4768-76b7-81e3-2c56d374df46"))
.header("Authorization", "Bearer " + token)
.header("Content-Type", "application/json")
.PUT(HttpRequest.BodyPublishers.ofString(body))
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode() + " " + response.body());
package main
import (
"bytes"
"fmt"
"io"
"net/http"
)
func main() {
baseURL := "https://api.stonal.io/users"
token := "<access_token>"
body := []byte(`{"email":"john.doe@example.com","firstName":"John","lastName":"Doe","userGroupUids":["019619df-4768-76b7-81e3-2c56d374df46"],"permissions":[{"uid":"019619df-4767-730f-8d31-143712a08141"}]}`)
req, _ := http.NewRequest("PUT", baseURL+"/v2/organizations/DEMO/users/019619df-4768-76b7-81e3-2c56d374df46", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+token)
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
out, _ := io.ReadAll(resp.Body)
fmt.Println(resp.StatusCode, string(out))
}
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
var baseUrl = "https://api.stonal.io/users";
var token = "<access_token>";
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
var json = """
{"email":"john.doe@example.com","firstName":"John","lastName":"Doe",
"userGroupUids":["019619df-4768-76b7-81e3-2c56d374df46"],
"permissions":[{"uid":"019619df-4767-730f-8d31-143712a08141"}]}
""";
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client.PutAsync($"{baseUrl}/v2/organizations/DEMO/users/019619df-4768-76b7-81e3-2c56d374df46", content);
Console.WriteLine($"{(int)response.StatusCode} {await response.Content.ReadAsStringAsync()}");
Corps de la requête
{
"email": "john.doe@example.com",
"firstName": "John",
"lastName": "Doe",
"fromExternalIdp": false,
"allAssets": false,
"userGroupUids": ["019619df-4768-76b7-81e3-2c56d374df46"],
"permissions": [
{ "uid": "019619df-4767-730f-8d31-143712a08141" },
{ "uid": "019619df-4768-76b3-8ab3-4414dcf29ff1" }
]
}
Référence des champs
| Champ | Requis | Type | Notes |
|---|---|---|---|
email | ✅ | string | Unique ; immuable à la mise à jour |
firstName | ✅ | string | |
lastName | ✅ | string | |
uid | — | string | Identifie l'utilisateur lors de la mise à jour |
password | — | string | ≥ 8 caractères ; majuscule + minuscule + chiffre + caractère spécial |
fromExternalIdp | — | boolean | Contrôle l'email d'activation (voir l'avertissement) |
allAssets | — | boolean | Accorde tous les objets au lieu de lister les permissions ASSET |
userGroupUids | — | string[] | UID des groupes |
permissions | — | { uid }[] | UID des permissions |
fromExternalIdpL'indicateur fromExternalIdp est ce qui contrôle si Stonal envoie au nouvel utilisateur un email d'activation de compte (le message « Définissez votre mot de passe STONAL »). C'est le seul paramètre qui régit ce comportement pour l'API — le commutateur SSO du frontend de l'organisation n'a aucun effet dessus.
fromExternalIdp: false(la valeur par défaut) — le compte est créé avec un mot de passe local et l'utilisateur reçoit l'email d'activation afin de pouvoir définir ou confirmer son mot de passe. Si vous omettez le champ, sa valeur par défaut estfalse, donc l'email est envoyé.fromExternalIdp: true— le compte est traité comme fédéré : aucun email d'activation n'est envoyé et l'utilisateur doit s'authentifier via son fournisseur d'identité externe (SSO).
Si vos utilisateurs se connectent via SSO et que vous ne voulez pas qu'ils reçoivent l'email « Définissez votre mot de passe STONAL », vous devez explicitement passer "fromExternalIdp": true dans l'appel de création. Le laisser à false (ou l'omettre) pour des utilisateurs SSO est la cause la plus courante d'emails d'activation inattendus.
Mettre à jour ou créer
PUTrequiert leuidde l'utilisateur dans le chemin de l'URL.- L'
emailne peut pas être modifié sur un utilisateur existant. - Il n'y a aucune mise à jour partielle — envoyez l'ensemble complet des champs que vous voulez sur l'utilisateur.
- Les
permissionsetuserGroupUidsfournis remplacent ceux existants ; tout groupe ou permission précédemment attribué non inclus dans la nouvelle requête sera supprimé.
Exemple complet de bout en bout
Cet exemple parcourt trois recherches pour collecter les UID, puis crée un utilisateur.
1. Trouver le groupe à attribuer
GET /v1/organizations/DEMO/groups
Réponse abrégée :
{
"content": [
{ "uid": "019619df-4768-76b7-81e3-2c56d374df46", "name": "Analysts" }
]
}
UID de groupe à utiliser : 019619df-4768-76b7-81e3-2c56d374df46
2. Trouver la permission de profil
GET /v1/organizations/DEMO/users/permissions?type=PROFILE
Réponse abrégée :
{
"content": [
{ "uid": "019619df-4767-730f-8d31-143712a08141", "name": "Standard profile" }
]
}
UID de la permission de profil : 019619df-4767-730f-8d31-143712a08141
3. Trouver la permission de portefeuille
GET /v1/organizations/DEMO/users/permissions?type=ASSET&subType=PORTFOLIO
Réponse abrégée :
{
"content": [
{ "uid": "019619df-4768-76b3-8ab3-4414dcf29ff1", "name": "All portfolios" }
]
}
UID de la permission de portefeuille : 019619df-4768-76b3-8ab3-4414dcf29ff1
4. Créer l'utilisateur
Les trois UID issus des recherches alimentent directement le corps de la requête :
POST /v2/organizations/DEMO/users
{
"email": "john.doe@example.com",
"firstName": "John",
"lastName": "Doe",
"fromExternalIdp": false,
"allAssets": false,
"userGroupUids": ["019619df-4768-76b7-81e3-2c56d374df46"],
"permissions": [
{ "uid": "019619df-4767-730f-8d31-143712a08141" },
{ "uid": "019619df-4768-76b3-8ab3-4414dcf29ff1" }
]
}
5. Réponse
200 OK
L'utilisateur est créé (ou mis à jour si l'email existait déjà) et attribué au groupe Analysts avec le profil standard et les permissions sur tous les portefeuilles.
Réponses
200— utilisateur créé ou mis à jour avec succès.
Les API Stonal renvoient une enveloppe d'erreur cohérente : { "type", "title", "detail" }. Les échecs de validation (422) remplacent detail par un tableau errors détaillant chaque champ.
| Statut | type | Signification |
|---|---|---|
400 | tag:InvalidBody / tag:InvalidContentType | Le corps de la requête ou le type de contenu est invalide |
401 | tag:Unauthenticated | Jeton d'authentification manquant ou expiré |
403 | tag:ForbiddenAccess | Le jeton n'a pas la permission d'accéder à cette ressource |
422 | tag:ValidationError | Un ou plusieurs champs ont échoué à la validation (voir errors[]) |
500 | tag:InternalError | Erreur serveur inattendue |
{
"type": "tag:ValidationError",
"title": "Invalid request",
"errors": [
{ "field": "email", "detail": "Email is required" }
]
}