curl --request POST \
--url https://api.0flaw.fr/api/v1/employees/sync \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"employees": [
{
"external_id": "hr-4821",
"email": "jane.doe@acme.com",
"nom": "Doe",
"prenom": "Jane",
"secteur": "Finance"
},
{
"email": "john.smith@acme.com",
"nom": "Smith",
"prenom": "John"
}
],
"deactivate_absent": false,
"dry_run": false
}
'import requests
url = "https://api.0flaw.fr/api/v1/employees/sync"
payload = {
"employees": [
{
"external_id": "hr-4821",
"email": "jane.doe@acme.com",
"nom": "Doe",
"prenom": "Jane",
"secteur": "Finance"
},
{
"email": "john.smith@acme.com",
"nom": "Smith",
"prenom": "John"
}
],
"deactivate_absent": False,
"dry_run": False
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
employees: [
{
external_id: 'hr-4821',
email: 'jane.doe@acme.com',
nom: 'Doe',
prenom: 'Jane',
secteur: 'Finance'
},
{email: 'john.smith@acme.com', nom: 'Smith', prenom: 'John'}
],
deactivate_absent: false,
dry_run: false
})
};
fetch('https://api.0flaw.fr/api/v1/employees/sync', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.0flaw.fr/api/v1/employees/sync",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'employees' => [
[
'external_id' => 'hr-4821',
'email' => 'jane.doe@acme.com',
'nom' => 'Doe',
'prenom' => 'Jane',
'secteur' => 'Finance'
],
[
'email' => 'john.smith@acme.com',
'nom' => 'Smith',
'prenom' => 'John'
]
],
'deactivate_absent' => false,
'dry_run' => false
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.0flaw.fr/api/v1/employees/sync"
payload := strings.NewReader("{\n \"employees\": [\n {\n \"external_id\": \"hr-4821\",\n \"email\": \"jane.doe@acme.com\",\n \"nom\": \"Doe\",\n \"prenom\": \"Jane\",\n \"secteur\": \"Finance\"\n },\n {\n \"email\": \"john.smith@acme.com\",\n \"nom\": \"Smith\",\n \"prenom\": \"John\"\n }\n ],\n \"deactivate_absent\": false,\n \"dry_run\": false\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.0flaw.fr/api/v1/employees/sync")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"employees\": [\n {\n \"external_id\": \"hr-4821\",\n \"email\": \"jane.doe@acme.com\",\n \"nom\": \"Doe\",\n \"prenom\": \"Jane\",\n \"secteur\": \"Finance\"\n },\n {\n \"email\": \"john.smith@acme.com\",\n \"nom\": \"Smith\",\n \"prenom\": \"John\"\n }\n ],\n \"deactivate_absent\": false,\n \"dry_run\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.0flaw.fr/api/v1/employees/sync")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"employees\": [\n {\n \"external_id\": \"hr-4821\",\n \"email\": \"jane.doe@acme.com\",\n \"nom\": \"Doe\",\n \"prenom\": \"Jane\",\n \"secteur\": \"Finance\"\n },\n {\n \"email\": \"john.smith@acme.com\",\n \"nom\": \"Smith\",\n \"prenom\": \"John\"\n }\n ],\n \"deactivate_absent\": false,\n \"dry_run\": false\n}"
response = http.request(request)
puts response.read_body{
"ok": true,
"dry_run": false,
"summary": {
"received": 2,
"created": 1,
"updated": 1,
"reactivated": 0,
"deactivated": 0,
"skipped": 0,
"failed": 0
},
"quota": {
"cap": 200,
"renewal_before": 42,
"renewal_after": 43,
"seats_requested": 1
},
"results": [
{
"external_id": "hr-4821",
"email": "jane.doe@acme.com",
"action": "created",
"id": "b1e…"
},
{
"external_id": null,
"email": "john.smith@acme.com",
"action": "updated",
"id": "c2f…"
}
]
}{
"message": "Email invalide",
"code": "VALIDATION_ERROR"
}{
"message": "Clé API invalide ou révoquée",
"code": "API_KEY_INVALID"
}{
"message": "Quota maximum atteint (200/200 sièges facturés).",
"code": "QUOTA_MAXIMUM_ATTEINT"
}{
"message": "Trop d'employés (1500). Maximum 1000 par appel.",
"code": "TOO_MANY_RECORDS"
}{
"message": "Trop de requêtes, réessayez plus tard.",
"code": "RATE_LIMIT_EXCEEDED"
}Synchroniser une liste d'employés
Réconcilie votre liste RH avec 0flaw en un appel : crée les nouveaux, met à jour les existants, réactive les archivés, et — uniquement si vous le demandez — désactive ceux absents de la liste.
L’opération est idempotente : rejouer la même liste ne crée aucun doublon.
Le rapprochement se fait sur external_id s’il est fourni, sinon sur l’email.
Fournir un external_id stable est fortement recommandé : c’est ce qui permet
de suivre un employé même si son email change.
Commencez par dry_run: true pour obtenir le rapport complet sans rien écrire.
curl --request POST \
--url https://api.0flaw.fr/api/v1/employees/sync \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"employees": [
{
"external_id": "hr-4821",
"email": "jane.doe@acme.com",
"nom": "Doe",
"prenom": "Jane",
"secteur": "Finance"
},
{
"email": "john.smith@acme.com",
"nom": "Smith",
"prenom": "John"
}
],
"deactivate_absent": false,
"dry_run": false
}
'import requests
url = "https://api.0flaw.fr/api/v1/employees/sync"
payload = {
"employees": [
{
"external_id": "hr-4821",
"email": "jane.doe@acme.com",
"nom": "Doe",
"prenom": "Jane",
"secteur": "Finance"
},
{
"email": "john.smith@acme.com",
"nom": "Smith",
"prenom": "John"
}
],
"deactivate_absent": False,
"dry_run": False
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
employees: [
{
external_id: 'hr-4821',
email: 'jane.doe@acme.com',
nom: 'Doe',
prenom: 'Jane',
secteur: 'Finance'
},
{email: 'john.smith@acme.com', nom: 'Smith', prenom: 'John'}
],
deactivate_absent: false,
dry_run: false
})
};
fetch('https://api.0flaw.fr/api/v1/employees/sync', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.0flaw.fr/api/v1/employees/sync",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'employees' => [
[
'external_id' => 'hr-4821',
'email' => 'jane.doe@acme.com',
'nom' => 'Doe',
'prenom' => 'Jane',
'secteur' => 'Finance'
],
[
'email' => 'john.smith@acme.com',
'nom' => 'Smith',
'prenom' => 'John'
]
],
'deactivate_absent' => false,
'dry_run' => false
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.0flaw.fr/api/v1/employees/sync"
payload := strings.NewReader("{\n \"employees\": [\n {\n \"external_id\": \"hr-4821\",\n \"email\": \"jane.doe@acme.com\",\n \"nom\": \"Doe\",\n \"prenom\": \"Jane\",\n \"secteur\": \"Finance\"\n },\n {\n \"email\": \"john.smith@acme.com\",\n \"nom\": \"Smith\",\n \"prenom\": \"John\"\n }\n ],\n \"deactivate_absent\": false,\n \"dry_run\": false\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.0flaw.fr/api/v1/employees/sync")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"employees\": [\n {\n \"external_id\": \"hr-4821\",\n \"email\": \"jane.doe@acme.com\",\n \"nom\": \"Doe\",\n \"prenom\": \"Jane\",\n \"secteur\": \"Finance\"\n },\n {\n \"email\": \"john.smith@acme.com\",\n \"nom\": \"Smith\",\n \"prenom\": \"John\"\n }\n ],\n \"deactivate_absent\": false,\n \"dry_run\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.0flaw.fr/api/v1/employees/sync")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"employees\": [\n {\n \"external_id\": \"hr-4821\",\n \"email\": \"jane.doe@acme.com\",\n \"nom\": \"Doe\",\n \"prenom\": \"Jane\",\n \"secteur\": \"Finance\"\n },\n {\n \"email\": \"john.smith@acme.com\",\n \"nom\": \"Smith\",\n \"prenom\": \"John\"\n }\n ],\n \"deactivate_absent\": false,\n \"dry_run\": false\n}"
response = http.request(request)
puts response.read_body{
"ok": true,
"dry_run": false,
"summary": {
"received": 2,
"created": 1,
"updated": 1,
"reactivated": 0,
"deactivated": 0,
"skipped": 0,
"failed": 0
},
"quota": {
"cap": 200,
"renewal_before": 42,
"renewal_after": 43,
"seats_requested": 1
},
"results": [
{
"external_id": "hr-4821",
"email": "jane.doe@acme.com",
"action": "created",
"id": "b1e…"
},
{
"external_id": null,
"email": "john.smith@acme.com",
"action": "updated",
"id": "c2f…"
}
]
}{
"message": "Email invalide",
"code": "VALIDATION_ERROR"
}{
"message": "Clé API invalide ou révoquée",
"code": "API_KEY_INVALID"
}{
"message": "Quota maximum atteint (200/200 sièges facturés).",
"code": "QUOTA_MAXIMUM_ATTEINT"
}{
"message": "Trop d'employés (1500). Maximum 1000 par appel.",
"code": "TOO_MANY_RECORDS"
}{
"message": "Trop de requêtes, réessayez plus tard.",
"code": "RATE_LIMIT_EXCEEDED"
}Authorizations
Clé API créée depuis le dashboard (Réglages → Clés API). L'en-tête x-api-key: <clé> est accepté en alternative à Authorization: Bearer <clé>.
Body
1 - 1000 elementsShow child attributes
Show child attributes
⚠️ Archive tous les employés actifs absents de la liste. N'activez ce mode que si la liste envoyée est exhaustive : un export partiel archiverait tout le reste de votre effectif. L'administrateur par défaut est toujours préservé.
Envoie l'email d'accès aux employés créés par cet appel
Renvoie le rapport complet sans rien écrire. À utiliser avant un premier import.