1. Objet
Ce guide a pour objectif de vous familiariser avec la manipulation des API REST offertes par CARL Source sur la base d’exemples concrets.
2. Vue d’ensemble
La plupart des applications encapsulent les appels aux API REST dans le langage de votre choix, mais il est important de vous familiariser avec les méthodes HTTP de l’API sous-jacente.
Nous utiliserons donc l’outil cURL pour interagir avec les API.
2.1. Prérequis
-
La connexion entre votre poste de travail et CARL Source doit être chiffrée : en effet, des informations sensibles (mot de passe et données protégées) vont transiter par le réseau dans le cadre de ce tutoriel.
L’URL d’accès à CARL Source doit donc commencer par https://.
|
|
Il est conseillé de privilégier pour ces échanges sécurisés, l’utilisation de TLS v1.3. A noter que les versions 1.0 et 1.1 de TLS sont prohibées. |
-
Vous devez posséder un utilisateur CARL Source valide.
-
Votre mot de passe doit également être valide (i.e. ni "expiré", ni "à modifier").
Pour vous en assurer, connectez-vous à l’application CARL Source via la page de connexion.
|
|
Attention, les URL données en exemple contenant des crochets ( |
2.2. Hello World
Commençons par nous assurer que l’outil cURL et l’API sont accessibles.
Ouvrez une fenêtre de terminal et saisissez la commande suivante (adaptez les valeurs en rouge) :
> curl https://carlsource.server.com/gmaoCS02/public/status
status: ok
La réponse est une simple ligne de texte status: ok, qui confirme que CARL Source est bien installé et accessible via l’URL saisie.
3. Authentification
L’utilisation des services nécessite généralement la transmission d’informations d’authentification.
Lors d’une demande d’accès à un service protégé, si l’identifiant ou le mot de passe fourni est invalide, l’API retourne une erreur HTTP 401 (Unauthorized) :
> curl -X GET -i https://carlsource.server.com/gmaoCS02/api/entities/v1/mr
HTTP/1.1 401 Unauthorized
{
"errors" : [ {
"status" : "401",
"title" : "Unauthorized",
"detail" : "Please provide valid authentication credentials"
} ]
}
L’authentification est la clé permettant la lecture et l’écriture d’informations privées via l’API.
3.1. Authentification par jeton
Pour les besoins d’une application, le fait d’envoyer les informations d’identifiant et de mot de passe à chaque interaction avec l’API peut paraître lourd et augmente le risque de vol de mot de passe.
La meilleure façon de gérer ce cas de figure consiste à demander à l’application (en l’occurrence CARL Source) la création d’un jeton d’accès, puis d’inclure ce dernier dans les requêtes subséquentes.
Ce jeton remplace l’usage direct du couple "identifiant/mot de passe" et évite ainsi d’exposer ces informations sensibles à chaque appel.
CARL Source prend en charge deux mécanismes d’obtention de jeton d’accès :
-
Jeton CARL Source (type (carlsource_auth_v1)) : obtenu via le service /api/auth/v1/authenticate et transmis dans l’en-tête HTTP X-CS-Access-Token.
-
Jeton OAuth2 (type (Bearer)) : conforme à la norme RFC 6750, obtenu via le service /api/oauth2/v1/token et transmis dans l’en-tête standard Authorization: Bearer.
Dans les deux cas, le service d’authentification n’est appelé qu’une seule fois pour obtenir le jeton d’accès. Ce jeton est ensuite utilisé pour authentifier toutes les requêtes ultérieures, sans qu’il soit nécessaire de renvoyer les identifiants ou les informations d’authentification.
> curl -X POST -i --data "login=identifiant" --data "password=mot_de_passe" --data "origin=identifiant_de_votre_application" https://carlsource.server.com/gmaoCS02/api/auth/v1/authenticate HTTP/1.1 200 { "X-CS-Access-Token":"votre_access_token", "token_type":"carlsource_auth_v1", "expires_in":86399911, "lang":"fr_FR" }
> curl -X POST https://carlsource.server.com/gmaoCS02/api/oauth2/v1/token -H "Content-Type: application/x-www-form-urlencoded" -d "grant_type=password" -d "client_id=identifiant_de_votre_application" HTTP/1.1 200 { "access_token": "votre_access_token", "token_type": "Bearer", "expires_in": 3600 }
|
|
La valeur des attributs |
Le fragment de JSON obtenu en retour comprend en premier lieu le jeton, qui consiste en une suite aléatoire de caractères.
CARL Source vérifie la validité d’un tel jeton lorsque ce dernier est placé dans un en-tête de requête http nommé X-CS-Access-Token.
Les informations suivantes sont également présentes dans l’en-tête :
-
Le type de jeton : il existe à ce jour deux types de jeton dans CARL Source (carlsource_auth_v1) et (bearer).
Il est possible que des jetons de type refresh tokens soient disponibles dans le futur. -
Le temps de validité de ce jeton (en millisecondes).
Au-delà de ce délai, une requête embarquant ce jeton sera rejetée.
Ce délai est configurable dans les paramètres de configuration système de CARL Source. -
La langue de l’utilisateur ayant demandé le jeton.
Cette information permet à l’application demandeuse de basculer au plus tôt sur la langue convenant le mieux à l’utilisateur (par exemple si celui-ci s’est connecté depuis un navigateur configuré dans une langue différente de la sienne).
A noter que c’est la langue définie sur l’utilisateur CARL Source qui fait foi.
|
|
La langue est retournée uniquement dans le cas d’un jeton (carlsource_auth_v1) |
Une fois le jeton obtenu, voici la manière dont il peut être utilisé pour authentifier un appel :
> curl -X GET -H "X-CS-Access-Token: votre_access_token" https://carlsource.server.com/gmaoCS02/api/entities/v1/mr
> curl -X GET -H "Authorization: Bearer votre_access_token" https://carlsource.server.com/gmaoCS02/api/entities/v1/mr
3.1.1. Cas particulier du jeton OAuth2 avec JWT d’assertion
Dans le cas du mécanisme OAuth2, l’authentification du client repose sur une assertion JWT (JSON Web Token).
L’application externe construit un JWT signé pour prouver son identité à CARL Source (serveur OAuth2).
CARL Source vérifie la signature, la validité et les informations contenues dans ce JWT.
Si le jeton est valide, CARL Source renvoie un jeton d’accès OAuth2, qui sera ensuite utilisé pour consommer les APIs CARL Source.
-
soit avec une clé asymétrique (algorithme RSASSA-PKCS1-v1_5 + SHA-256),
-
soit avec une clé partagée (Pre-Shared Key, PSK, utilisant HMAC + SHA-256).
Sa durée de validité est limitée afin d’éviter les risques de réutilisation (replay attack).
CARL Source contrôle ainsi que l’âge du JWT ne dépasse pas la valeur maximale définie dans la configuration système.
3.2. Authentification HTTP-BASIC
|
|
L’authentification HTTP-BASIC (Basic Authentication) est déconseillée. |
Malgré les risques, si vous souhaitez vous authentifier de cette façon, vous devez utiliser un identifiant et un mot de passe CARL Source.
> curl -u identifiant https://carlsource.server.com/gmaoCS02/api/auth/v1/authenticate Enter host password for user 'identifiant':
L’option -u permet de définir un nom d’utilisateur.
A la validation de la commande, cURL demande alors le mot de passe associé.
Il est possible d’utiliser la syntaxe -u "identifiant:mot_de_passe" pour éviter l’invite, mais cela laisse une trace du mot de passe dans l’historique du terminal (ce qui n’est pas recommandé).
Il est également possible de désactiver ce mode d’authentification en cochant le paramètre système AuthBasicDisabled de la rubrique Authentification :
Dans ce cas les tentatives d’accès via cette méthode retourneront une erreur:
> curl -u identifiant https://carlsource.server.com/gmaoCS02/api/auth/v1/authenticate Enter host password for user 'identifiant': { "errors" : [ { "status" : "401", "title" : "Unauthorized", "detail" : "Please provide valid authentication credentials" } ] }
3.3. Authentification et sécurité en production
Au-delà de ce tutoriel, pour lequel l’outil curl est utilisé, une application en production doit invoquer le service d’authentification à l’aide d’une bibliothèque de communication http fournie par le langage dans lequel elle est programmée.
Il convient d’être très prudent sur la façon d’invoquer ce service d’authentification, car techniquement il existe deux façons différentes de transmettre les paramètres login, password et origin au service /authenticate.
3.3.1. Authentification en production : mauvaise pratique
La première façon de faire consiste à transmettre ces informations sous la forme de paramètres dans l’URL.
Cette méthode est très fortement déconseillée pour une application en production.
POST https://carlsource.server.com/gmaoCS02/api/auth/v1/authenticate?login=LOGIN&password=password&origin=ORIGIN
En procédant ainsi, les informations critiques d’identifiant et de mot de passe vont être potentiellement traitées comme des données non critiques et être exposées, notamment dans des fichiers de logs.
Bien que ce soit techniquement possible, cette pratique est fortement découragée.
3.3.2. Authentification en production : bonne pratique
Il est préconisé de transmettre les paramètres d’authentification en tant que données de formulaire, dans le corps de la requête, et d’ajuster le Content-Type en conséquence en utilisant application/x-www-form-urlencoded.
POST https://carlsource.server.com/gmaoCS02/api/auth/v1/authenticate
Content-Type: application/x-www-form-urlencoded
&login=LOGIN
&password=password
&origin=ORIGIN
4. Droits d’accès
Les droits d’accès à l’API sont pilotés par les droits positionnés sur chaque profil au niveau de CARL Source.
Un paramètre de profil global, nommé "Accès aux API de type JSON-API" et accessible depuis la catégorie "Global", autorise l’accès aux API.
|
|
Par défaut ce paramètre est positionné à la valeur 'Désactivé', ce qui bloque par conséquent l’accès aux API. |
L’accès à une entité par l’API est ensuite déterminé en fonction des autorisations de Lecture/Création/Modification/Suppression sur la fonctionnalité liée à cette entité (les autres autorisations sont ignorées).
Un algorithme applique les critères suivants (dans l’ordre) afin de faire le lien entre une entité et sa fonctionnalité :
-
Récupération de l’attribut FunctBean.entity qui indique directement si l’entité est référencée par la fonctionnalité.
-
Si l’entité n’a pas de fonctionnalité référencée : parcours des relations entre entités ; l’entité est reliée à une autre entité dont la fonctionnalité a été identifiée. Dans ce cas, il est possible qu’une entité soit référencée par plusieurs fonctionnalités.
-
Si, au terme de ce parcours, certaines entités sont toujours non rattachées à une fonctionnalité, on doit renseigner cette information dans ObjectInfoBean.relatedFunctionality.
|
|
|
Les codes HTTP suivants sont retournés en cas de droits insuffisants :
-
403 - indique que le profil n’a pas les autorisations nécessaires sur cette entité :
-
soit vis-à-vis du paramètre global "Accès aux API de type JSON-API" (voir plus haut),
-
soit vis-à-vis de ses autorisations sur la fonctionnalité associée,
-
soit par l’absence de fonctionnalité associée.
-
-
501 : indique que l’entité est uniquement accessible en lecture seule, et par conséquent que les opérations POST/PUT/PATCH/DELETE ne sont pas réalisables sur celle-ci.
5. Limite
Le paramètre de configuration ApiMaxResults indique le nombre maximum d’éléments que peut remonter une page sur un appel de l’API Rest.
La valeur maximum est fixée à 500. En effet, ce paramètre conditionne directement la mémoire consommée dans l’application; une valeur trop élevée pourrait amener rapidement à la saturation et l’arrêt de l’application.
Lorsque le nombre d’éléments retournés est supérieur à 500, il est nécessaire d’utiliser la pagination.
La pagination sert à diviser un grand ensemble de données en plusieurs "pages" plus petites, afin d’éviter de tout charger en une seule fois.
Chaque appel à l’API lit une partie des données en base (les beans), puis les transforme en entités - les objets effectivement renvoyés.
Certains filtres étant appliqués après lecture des beans et certaines entités étant issues de collections, le nombre exact d’éléments par page peut varier.
La gestion de la pagination se fait grâce aux paramètres limit et offset :
-
limit indique le nombre d’éléments désirés dans la page (ex. 100 résultats).
-
offset indique le nombre d’éléments à ignorer avant de récupérer les éléments désirés (ex. pour aller à la page suivante).
Exemples :
curl -X GET -H "X-CS-Access-Token: votre_access_token" "https://carlsource.server.com/gmaoCS02/api/entities/v1/mr?limit=100&offset=0"
curl -X GET -H "X-CS-Access-Token: [red]#votre_access_token#" "https://carlsource.server.com/gmaoCS02/api/entities/v1/mr?limit=100&offset=100"
curl -X GET -H "X-CS-Access-Token: [red]#votre_access_token#" "https://carlsource.server.com/gmaoCS02/api/entities/v1/mr?limit=100&offset=200"
|
|
Avec l’option OData, les paramètres permettant de gérer la pagination sont différents; dans ce cas, les appels API doivent utiliser $top et $skip en lieu et place de limit et offset. Exemple appel Api OData
curl -X GET -H "X-CS-Access-Token: [red]#votre_access_token#" "https://carlsource.server.com/gmaoCS02/api/odata/v1/WOPROCESS?$top=200&$skip=300 |
6. Scénario métier : l’API /entities
Maintenant que votre installation fonctionne et que vous savez comment accéder aux services protégés via le système d’authentification de votre choix, vous allez pouvoir interagir avec les objets métiers de CARL Source.
Ce scénario propose de créer et manipuler un concept central de CARL Source, la Demande d’intervention, via l’API /entities.
Techniquement, il s’agit d’une API REST - HATEOAS, s’appuyant sur la bibliothèque Crnk, elle-même implémentant la spécification JSON-API.
6.1. Anatomie d’un appel
Pour commencer, listons les demandes d’intervention existantes dans CARL Source.
Pour cela, il nous suffit de connaitre le code sous lequel est désignée une demande d’intervention dans CARL Source.
Ce code est 'mr' (nous y reviendrons plus tard).
> curl -X GET -H "X-CS-Access-Token: votre_access_token" https://carlsource.server.com/gmaoCS02/api/entities/v1/mr
|
|
Pour être accessibles au travers de l’API /entities, en lecture/modificaton/création/suppression, les attributs doivent avoir la propriété Exporté format XML cochée ou nulle dans le dictionnaire de CARL Source. Changement de valeur sur la propriété Exporté format XML
curl -X POST -i -H "X-CS-Access-Token: votre_access_token" https://carlsource.server.com/gmaoCS02/api/entities/v1?rebuildAPIs |
Avant de l’exécuter, penchons-nous sur cette commande :
-
le premier paramètre -H 'X-CS-Access-Token" permet d’indiquer le token obtenu précédemment (voir Authentification par jeton), afin de s’authentifier à l’aide de la méthode Custom Header Token,
-
la suite de la commande invoque le service REST responsable de lister les demandes d’intervention (mr).
Décomposons cette URL :
-
https://carlsource.server.com : la première partie de l’URL correspond à l’adresse de CARL Source.
-
/gmaoCS02 : indique le contexte de l’application web CARL Source.
-
/api : spécifie que l’on souhaite solliciter une API REST de CARL Source.
-
/entities/v1/ : l’API à laquelle on s’adresse est l’API /entities, dans sa première version (/v1).
-
/mr : le type des entités auxquelles on souhaite accéder est mr, les demandes d’intervention.
Si on ne fournit pas davantage d’informations, CARL Source renvoie une liste de toutes les demandes d’intervention (au format JSON).
Voici un extrait de la réponse obtenue :
> curl -X GET -H "X-CS-Access-Token: votre_access_token" https://carlsource.server.com/gmaoCS02/api/entities/v1/mr HTTP/1.1 200 { "data" : [ { "id" : "DI-1", "type" : "mr", "attributes" : { "code" : "DI-001", "statusChangedDate" : "2018-10-19T15:31:21.495+02:00", "description" : "Chauffage / Climatisation salle de réunion direction", "expEnd" : "2018-10-20T15:31:21.495+02:00", "SRID" : 0, "amount" : 0.0, "creationDate" : "2018-10-19T15:31:21.495+02:00", "workRecept" : true, "workPriority" : "HIGH", "eqptBroken" : true, "statusCode" : "REQUEST" }, "relationships" : { "address" : { "links" : { "self" : "https://carlsource.server.com/gmaoCS02/api/entities/v1/mr/DI-1/relationships/address", "related" : "https://carlsource.server.com/gmaoCS02/api/entities/v1/mr/DI-1/address" } }, "symptom" : { "links" : { "self" : "https://carlsource.server.com/gmaoCS02/api/entities/v1/mr/DI-1/relationships/symptom", "related" : "https://carlsource.server.com/gmaoCS02/api/entities/v1/mr/DI-1/symptom" } }, "site" : { "links" : { "self" : "https://carlsource.server.com/gmaoCS02/api/entities/v1/mr/DI-1/relationships/site", "related" : "https://carlsource.server.com/gmaoCS02/api/entities/v1/mr/DI-1/site" } }, "risks" : { "links" : { "self" : "https://carlsource.server.com/gmaoCS02/api/entities/v1/mr/DI-1/relationships/risks", "related" : "https://carlsource.server.com/gmaoCS02/api/entities/v1/mr/DI-1/risks" } }, "customer" : { "links" : { "self" : "https://carlsource.server.com/gmaoCS02/api/entities/v1/mr/DI-1/relationships/customer", "related" : "https://carlsource.server.com/gmaoCS02/api/entities/v1/mr/DI-1/customer" } } }, "links" : { "self" : "https://carlsource.server.com/gmaoCS02/api/entities/v1/mr/DI-1", "workflow-transitions" : "https://carlsource.server.com/gmaoCS02/api/entities/v1/mr/DI-1/workflow-transitions" } }, { "id" : "DI-2", "type" : "mr", ... } ] }
L’API /entities se conforme à la norme JSON-API.
Les données JSON retournées sont toujours encapsulées dans un tableau JSON nommé data[].
Voyons la structure de chaque objet mr retourné :
-
Les attributs identifiant (id) et type d’entité (type) sont au premier niveau.
-
Les attributs métier sont regroupés dans un objet attributes.
-
Les objets et collections liés sont considérés comme des relations et regroupés dans un objet relationships.
-
Chaque relation est nommée (par exemple risks) et comprend un sous-objet links, lui-même composé de deux attributs :
-
related présente l’URL qu’il est nécessaire d’appeler si l’on souhaite récupérer le détail de cette relation,
-
self présente l’URL vers la relation elle-même (utile si l’on veut manipuler la relation elle-même et non les deux objets liés - par exemple, supprimer la relation sans supprimer aucun des deux objets liés).
-
-
Et enfin un objet links, qui reprend le concept du self et ajoute un attribut workflow-transitions qui nous servira à faire évoluer l’objet dans son cycle de vie (nous y reviendrons plus tard).
{
"data" : [
{
"id" : <identifiant>,
"type" : <type>,
"attributes" : {
<liste des attributs>
},
"relationships" : {
<liste des objets et collections liés avec pour chacun les URL 'self' et 'related'>
},
"links" : {
"self" : <URL du service donnant le détail de cet objet>,
"workflow-transitions" : <URL du service donnant les futurs états possibles de cet objet au sein de son cycle de vie>
}
},
<les autres objets sur le même modèle>
]
}
|
|
La commande utilisée dans ce chapitre est donnée à titre d’exemple ; elle permet de récupérer un nombre important de données. |
6.2. Lister, filtrer et sélectionner
L’API /entities de CARL Source s’appuie sur Crnk, un framework qui suit les recommandations de la spécification JSON-API. Ceci étant, tout n’est pas décrit par cette spécification.
Les aspects liés au requêtage (filtre, tri, pagination, etc.) s’appuient sur l’API QuerySpec.
6.2.1. Filtres simples
Voici quelques exemples de filtres permettant d’effectuer des recherches avec les opérateurs de base :
curl -X GET -H "X-CS-Access-Token: votre_access_token" https://carlsource.server.com/gmaoCS02/api/entities/v1/mr?sort=-creationDate
curl -X GET -H "X-CS-Access-Token: votre_access_token" https://carlsource.server.com/gmaoCS02/api/entities/v1/mr?sort=-creationDate,description
curl -X GET -H "X-CS-Access-Token: votre_access_token" https://carlsource.server.com/gmaoCS02/api/entities/v1/mr?sort=id&page[offset]=0&page[limit]=2
curl -X GET -H "X-CS-Access-Token: votre_access_token" https://carlsource.server.com/gmaoCS02/api/entities/v1/mr?filter[mr][description]=Chauffage / Climatisation salle de réunion direction
LIKE (ou «contient») sur la valeur du champ 'description'curl -X GET -H "X-CS-Access-Token: votre_access_token" https://carlsource.server.com/gmaoCS02/api/entities/v1/mr?filter[mr][description][LIKE]=panne
curl -X GET -H "X-CS-Access-Token: votre_access_token" https://carlsource.server.com/gmaoCS02/api/entities/v1/mr?fields[mr]=description
6.2.2. Filtres complexes
|
|
Attention : le format utilisé pour décrire un filtre complexe contient des caractères spéciaux (crochets et accolades).
Ces caractères doivent obligatoirement être encodés; à défaut, la requête sera rejetée |
Il est possible d’effectuer des requêtes plus complexes en combinant les filtres avec des opérateurs logiques composites.
Les opérateurs actuellement supportés sont OR et AND.
Voici quelques exemples de requêtes utilisant des filtres complexes :
curl -X GET -H "X-CS-Access-Token: votre_access_token" https://carlsource.server.com/gmaoCS02/api/entities/v1/mr?filter={"OR":[{"code":"MR01"},{"id":"01"}]}
curl -X GET -H "X-CS-Access-Token: votre_access_token" https://carlsource.server.com/gmaoCS02/api/entities/v1/mr?filter={"AND":[{"eqptBroken":true},{"workPriority":"HIGH"}]}
curl -X GET -H "X-CS-Access-Token: votre_access_token" https://carlsource.server.com/gmaoCS02/api/entities/v1/mr?filter={"OR":[{"GT":{"expEnd": "2026-01-01"}},{"LT":{"expEnd": "2026-12-31"}}]}
curl -X GET -H "X-CS-Access-Token: votre_access_token" https://carlsource.server.com/gmaoCS02/api/entities/v1/mr?filter={"OR":[{"eqptBroken":true},{"eqptUnavailable":true},{"workPriority":"HIGH"}]}
Il est également possible d’imbriquer les filtres grâce aux opérateurs logiques composites. Voici un exemple :
curl -X GET -H "X-CS-Access-Token: votre_access_token" https://carlsource.server.com/gmaoCS02/api/entities/v1/mr?filter={"OR":[{"workPriority":"HIGH"},{"AND":[{"eqptBroken":true},{"GT":{"expEnd": "2026-12-31"}}]}]}
6.3. Créer, lire, modifier et supprimer
Conformément au standard REST, les verbes HTTP suivants sont disponibles, chacun étant assigné à un rôle précis :
-
POST : création
-
GET : lecture
-
PATCH : modification
-
DELETE : suppression
6.3.1. Création
A titre d’exemple, créer une demande d’intervention revient à exécuter la commande suivante :
curl -X POST -i -H "X-CS-Access-Token: votre_access_token" -H "Content-Type: application/vnd.api+json" \ -d '{ "data" : { "type" : "mr", "attributes" : { "description" : "Nouvelle demande", "workPriority" : "HIGH" } } }' \ https://carlsource.server.com/gmaoCS02/api/entities/v1/mr
Conformément à la norme JSON API, le format des données soumises en JSON reprend la structure détaillée ci-dessus ({ "data" : {..}}), et un en-tête HTTP fixe le type de contenu soumis -H "Content-Type: application/vnd.api+json".
|
|
Les données peuvent être transmises au travers d’un fichier à l’aide de la requête suivante : curl -X POST -i -H "X-CS-Access-Token: votre_access_token" -H "Content-Type: application/vnd.api+json" --data-binary "@path/to/file" https://carlsource.server.com/gmaoCS02/api/entities/v1/mr Attention : le chemin d’accès au fichier doit être précédé du symbole @. Le fichier {
"data" : {
"type" : "mr",
"attributes" : {
"description" : "Nouvelle demande",
"workPriority" : "HIGH"
}
}
}
|
Le JSON décrivant la demande d’intervention venant d’être créée est reçu en réponse à cette requête, avec un code HTTP 201.
En voici un extrait :
HTTP/1.1 201
{
"data" : {
"id" : "166ee780a94-1486",
"type" : "mr",
"attributes" : {
"code" : "000001",
"description" : "Nouvelle demande",
"workPriority" : "HIGH",
"eqptBroken" : false,
"SRID" : 0,
"amount" : 0.0,
"creationDate" : "2018-11-08T17:20:10.583+01:00",
"modifyDate" : "2018-11-08T17:20:10.600+01:00",
"expEnd" : "2018-11-08T17:20:10.585+01:00",
"statusChangedDate" : "2018-11-08T17:20:10.584+01:00",
"statusCode" : "REQUEST"
...
},
"relationships" : {
"address" : {
"links" : {
"self" : "https://carlsource.server.com/gmaoCS02/api/entities/v1/mr/166ee780a94-1486/relationships/address",
"related" : "https://carlsource.server.com/gmaoCS02/api/entities/v1/mr/166ee780a94-1486/address"
}
},
"risks" : {
"links" : {
"self" : "https://carlsource.server.com/gmaoCS02/api/entities/v1/mr/166ee780a94-1486/relationships/risks",
"related" : "https://carlsource.server.com/gmaoCS02/api/entities/v1/mr/166ee780a94-1486/risks"
}
},
...
},
"links" : {
"self" : "https://carlsource.server.com/gmaoCS02/api/entities/v1/mr/166ee780a94-1486",
"workflow-transitions" : "https://carlsource.server.com/gmaoCS02/api/entities/v1/mr/166ee780a94-1486/workflow-transitions"
}
}
}
La valeur de l’attribut links.self donne directement l’URL à appeler pour obtenir le détail de la demande d’intervention venant d’être créée.
6.3.2. Lecture
Pour récupérer un objet existant, il suffit d’ajouter son identifiant à la suite de l’URL :
curl -X GET -i -H "X-CS-Access-Token: votre_access_token" https://carlsource.server.com/gmaoCS02/api/entities/v1/mr/166ee780a94-1486
La réponse est alors identique à celle obtenue plus haut suite à une création : elle contient le détail de l’objet.
6.3.3. Modification
Pour modifier un objet existant, on utilise une syntaxe proche de celle de la création et de la lecture, mais avec un verbe HTTP approprié : PATCH.
curl -X PATCH -i -H "X-CS-Access-Token: votre_access_token" -H "Content-Type: application/vnd.api+json" \ -d '{ "data" : { "type" : "mr", "attributes" : { "description" : "Nouvelle demande urgente", "workPriority" : "VERYHIGH" } } }' \ https://carlsource.server.com/gmaoCS02/api/entities/v1/mr/166ee780a94-1486
6.3.4. Suppression
Pour supprimer un objet, l’approche est similaire ; spécifier un identifiant à la fin de l’URL et utiliser un verbe HTTP approprié : DELETE.
curl -X DELETE -i -H "X-CS-Access-Token: votre_access_token" https://carlsource.server.com/gmaoCS02/api/entities/v1/mr/166ee780a94-1486
6.3.5. Synthèse
Pour résumer les différentes actions à disposition :
-
Lister : GET /api/entities/<version de l’API>/<code du type d’objet>
+ d’éventuelles options QuerySpec -
Créer : POST /api/entities/<version de l’API>/<code du type d’objet>
+ un documentJSONutilisé pour initialiser l’objet créé -
Lire : GET /api/entities/<version de l’API>/<code du type d’objet>/<identifiant de l’objet>
-
Modifier : PATCH /api/entities/<version de l’API>/<code du type d’objet>/<identifiant de l’objet>
+ un documentJSONutilisé pour modifier l’objet -
Supprimer : DELETE /api/entities/<version de l’API>/<code du type d’objet>/<identifiant de l’objet>
6.4. Gestion du multilingue
6.4.1. Historique de la gestion du multilingue
Jusqu’en version 7.3.0, l’API /entities ne gérait pas du tout les aspects multilingues (Babylon). Cela signifie que les données manipulées par l’API étaient systématiquement les données stockées dans les tables de CARL Source (par opposition à celles stockées dans les tables de traductions), et donc exprimées dans la langue par défaut de l’application.
À partir de CARL Source 7.4.0, le paramètre de configuration système enableI18nEntitiesApi a permis d’exploiter l’API /entities dans deux modes distincts :
-
un mode dans lequel l’API supporte les capacités multilingues de CARL Source en lecture et en écriture.
C’est le mode par défaut qui permet à l’API d’envoyer des données traduites dans la langue de l’utilisateur dans la réponse en lecture, et de créer ou modifier des traductions dans la requête en écriture. -
un mode de compatibilité dans lequel on conserve le comportement historique de l’API en ne gérant pas du tout les aspects multilingues.
De plus, le support du paramètre d’URI_locale(déjà présent dans plusieurs API CARL Source) est ajouté dans l’API /entities afin de pouvoir surcharger la langue de l’utilisateur connecté.
Puis, en CARL Source 7.5.0, un ensemble de nouveaux paramètres d’URI a fait son apparition afin de permettre de filtrer et trier sur des éléments traduisibles :
-
i18nFilter: à utiliser en lieu et place defiltersi l’on souhaite que le filtre s’applique sur les éléments traduits. -
_i18nSort:falsepar défaut. Sitrue, le paramètresortpeut s’appliquer à des éléments traduits. -
_ignoreTranslations:falsepar défaut. Sitrue, les éventuelles traductions ne sont pas résolues en lecture ni en écriture.
6.4.2. Résolution de traductions et nouveaux blocs meta
Si le paramètre de configuration système enableI18nEntitiesApi est coché, les traductions sont résolues en lecture et en écriture.
La langue dans laquelle la requête est effectuée est déduite :
-
en priorité de la valeur du paramètre d’URI
_locale, -
sinon sur la langue de l’utilisateur connecté à CARL Source lors de l’appel à l’API.
Cela signifie que si des données traduites existent dans la langue demandée, elles seront résolues et retournées dans la réponse.
Afin de savoir dans quelle langue sont exprimés les éléments retournés, et d’avoir le contexte nécessaire à l’exploitation de ces données traduites, de nouveaux blocs meta, conformes à la spécification JSON:API, ont été ajoutés à la réponse.
6.4.2.1. Blocs meta et langues des attributs en lecture
On demande le détail d’un objet de type unit et d’identifiant 100 en étant connecté avec un utilisateur français :
curl -X GET /api/entities/v1/unit/100?fields=code,description,symbol
{
"data": {
"id": "CH",
"type": "unit",
"links": {
"self": "https://carlsource.server.com/api/entities/v1/unit/100"
},
"meta": {
"translatableAttributesLanguageMap": {
"symbol": "fr",
"description": "fr"
},
"entityLanguage": "fr",
"codeReference": "CH"
},
"attributes": {
"symbol": "ch",
"code": "CH",
"description": "Cheval-vapeur"
}
},
"links": {
"self": "https://carlsource.server.com/api/entities/v1/unit/100?fields=code%2Cdescription%2Csymbol"
},
"meta": {
"requestLocale": "fr_FR"
}
}
Puis le détail du même objet, avec le même utilisateur connecté, mais en spécifiant la langue anglaise :
curl -X GET /api/entities/v1/unit/100?fields=code,description,symbol&_locale=en_GB
{
"data" : {
"id": "CH",
"type": "unit",
"links": {
"self": "https://carlsource.server.com/api/entities/v1/unit/100"
},
"meta": {
"translatableAttributesLanguageMap": {
"symbol": "en",
"description": "en"
},
"entityLanguage": "fr",
"codeReference": "CH"
},
"attributes": {
"symbol": "hp",
"code": "CH",
"description": "Horsepower"
}
},
"links": {
"self": "https://carlsource.server.com/api/entities/v1/unit/100?fields=code%2Cdescription%2Csymbol&_locale=en_GB"
},
"meta": {
"requestLocale": "en_GB"
}
}
6.4.2.2. Un bloc meta global pour la langue de la requête
Si l’on observe le contenu de ces deux réponses de bas en haut, on constate tout d’abord qu’un bloc meta global rappelle systématiquement la locale dans laquelle la requête a été exécutée.
En effet, même si cela parait redondant dans le cas où locale est explicitement spécifiée en paramètre d’URI, ce paramètre reste optionnel et en son absence c’est la locale associée à l’utilisateur connecté qui fait foi.
Dans ce cas, la locale de la requête est implicite : il est donc bon de la rappeler dans la réponse.
6.4.2.3. Des attributs traduits dans la langue de la requête
Si l’entité sélectionnée possède des attributs traduisibles, et s’ils disposent d’une traduction dans la langue demandée, alors ceux-ci sont désormais résolus et proposés dans la réponse.
Dans ce cadre, un bloc meta par entité fait son apparition et porte trois informations permettant de donner du contexte :
-
translatableAttributesLanguageMaprappelle quels sont les attributs traduisibles de l’entité, et pour chacun la langue dans laquelle sa valeur est exprimée. -
entityLanguagepermet de connaitre la langue dans laquelle l’entité a été créée. -
codeReferenceest le code tel qu’il est stocké dans la table (dans la langue de l’entité donc), et qui permet de retrouver l’entité via unfilter[code]=.
6.4.3. Création et modification de traductions
Si un utilisateur français crée une entité, la requête et la réponse ressemblent à ceci :
curl -X POST /api/entities/v1/unit
{
"data": {
"type": "unit",
"attributes": {
"code": "CH",
"description": "Cheval-vapeur",
"symbol": "ch",
"decimal": "0"
}
}
}
{
"data": {
"id": "100",
"type": "unit",
"links": {
"self": "https://carlsource.server.com/api/entities/v1/unit/100"
},
"meta": {
"translatableAttributesLanguageMap": {
"symbol": "fr",
"description": "fr"
},
"entityLanguage": "fr",
"codeReference": "CH"
},
"attributes": {
"symbol": "ch",
"UOwner": "DEMO",
"code": "CH",
"modifyDate": "2026-01-16T14:38:28.128+01:00",
"description": "Cheval-vapeur",
"persoId": null,
"decimal": 0
},
"relationships": {
"secuPolicy": {
"links": {
"self": "https://carlsource.server.com/api/entities/v1/unit/100/relationships/secuPolicy",
"related": "https://carlsource.server.com/api/entities/v1/unit/100/secuPolicy"
}
}
}
},
"links": {
"self": "https://carlsource.server.com/api/entities/v1/unit"
},
"meta": {
"requestLocale": "fr_FR"
}
}
En revanche, si c’est un utilisateur anglais qui exécute cette même requête, on obtient cette réponse :
{
"data": {
"id": "100",
"type": "unit",
"links": {
"self": "https://carlsource.server.com/api/entities/v1/unit/100"
},
"meta": {
"translatableAttributesLanguageMap": {
"symbol": "en",
"description": "en"
},
"entityLanguage": "en",
"codeReference": "HP"
},
"attributes": {
"symbol": "hp",
"UOwner": "DEMO",
"code": "HP",
"modifyDate": "2026-01-16T14:48:15.065+01:00",
"description": "Horsepower",
"persoId": null,
"decimal": 0
},
"relationships": {
"translations": {
"links": {
"self": "https://carlsource.server.com/api/entities/v1/unit/100/relationships/translations",
"related": "https://carlsource.server.com/api/entities/v1/unit/100/translations"
}
},
"secuPolicy": {
"links": {
"self": "https://carlsource.server.com/api/entities/v1/unit/100/relationships/secuPolicy",
"related": "https://carlsource.server.com/api/entities/v1/unit/100/secuPolicy"
}
}
}
},
"links": {
"self": "https://carlsource.server.com/api/entities/v1/unit?_locale=en_GB"
},
"meta": {
"requestLocale": "en_GB"
}
}
On remarque que :
-
la langue de la requête diffère entre les deux,
-
les attributs traduisibles sont exprimés en fonction de cette langue,
-
le
codeReferenceest bien le code avec lequel l’entité a été initialement créée, et que c’est celui qui sera donc à utiliser pour faire référence à cette entité via un filtrefilter[code]=.
Si l’entité a été créée par l’utilisateur français, et que l’on souhaite créer ou modifier des traductions anglaises, une requête PATCH suffit.
Si c’est un utilisateur français qui réalise cette opération, alors il faudra spécifier le paramètre d’URI _locale=en_GB.
curl -X PATCH /api/entities/v1/unit/100?_locale=en_GB
{
"data": {
"id": "CH",
"type": "unit",
"links": {
"self": "https://carlsource.server.com/api/entities/v1/unit/100"
},
"meta": {
"translatableAttributesLanguageMap": {
"symbol": "en",
"description": "en"
},
"entityLanguage": "fr",
"codeReference": "CH"
},
"attributes": {
"symbol": "hp",
"UOwner": "DEMO",
"code": "CH",
"modifyDate": "2026-01-16T13:55:43.722+01:00",
"description": "Horsepower",
"persoId": null,
"decimal": 0
},
"relationships": {
"translations": {
"links": {
"self": "https://carlsource.server.com/api/entities/v1/unit/100/relationships/translations",
"related": "https://carlsource.server.com/api/entities/v1/unit/100/translations"
}
},
"secuPolicy": {
"links": {
"self": "https://carlsource.server.com/api/entities/v1/unit/100/relationships/secuPolicy",
"related": "https://carlsource.server.com/api/entities/v1/unit/100/secuPolicy"
}
}
}
},
"links": {
"self": "https://carlsource.server.com/api/entities/v1/unit/100?_locale=en_GB"
},
"meta": {
"requestLocale": "en_GB"
}
}
6.4.4. Le filtrage multilingue
Le filtrage a évolué en plusieurs étapes dont voici le détail.
Jusqu’en CARL Source 7.2, pour une requête comprenant un filtre tel que filter[code][EQ]=SOME_CODE :
-
La locale n’était jamais prise en compte, et la recherche se faisait uniquement sur la table principale (i.e. toujours en langue principale et jamais dans les tables de traductions).
-
La section
attributescontenait les valeurs non traduites telles que stockées dans la table principale.
À partir de CARL Source 7.4, pour une requête comprenant un filtre tel que filter[code][EQ]=SOME_CODE :
-
La recherche se fait uniquement sur la table principale.
-
Si le paramètre de configuration système
enableI18nEntitiesApiest coché, la sectionattributescontient les valeurs traduites. -
Si le paramètre de configuration système
enableI18nEntitiesApiest coché, mais si la requête inclut le paramètre_ignoreTranslations=true, alors la sectionattributescontient les valeurs non traduites telles que stockées dans la table principale (mode de compatibilité à la requête près). -
Si le paramètre de configuration système
enableI18nEntitiesApiest décoché, la sectionattributescontient les valeurs non traduites telles que stockées dans la table principale (mode de compatibilité global).
À partir de CARL Source 7.5, pour une requête comprenant un filtre tel que i18nFilter[code][EQ]=SOME_CODE :
-
La recherche se fait sur les valeurs traduites.
-
La section attributes contient les valeurs traduites.
|
|
Pour rester dans le comportement historique (avant CARL Source 7.3) sans support multilingue, on peut intervenir à deux niveaux :
|
6.4.5. Le tri multilingue
Contrairement au filtrage, et conformément à la spécification JSON:API, le tri ne peut pas s’appuyer sur un nouveau paramètre : c’est toujours le paramètre sort qui s’en charge.
De ce fait, en l’état son comportement est conforme à l’historique : il ne tient pas compte des traductions.
En revanche, un nouveau paramètre permet de faire en sorte que sort gère le multilingue : ajouter le paramètre _i18nSort=true active le tri sur l’attribut traduisible.
-
Le paramètre
filterdevienti18nFiltersi l’on souhaite qu’il s’applique à des valeurs traduites -
En revanche, le paramètre
sortrestesortet il faut ajouter_i18nSort=truesi l’on souhaite qu’il s’applique à des valeurs traduites
Exemples
Soient les données de la fonctionnalité animal, exécutées par un utilisateur français.
-
Code : A
-
Description : abeille
-
Traduction de description : bee
-
Code : B
-
Description : baleine
-
Traduction de description : whale
-
Code : C
-
Description : chien
-
Traduction de description : dog
curl -X GET /api/entities/v1/animal
-
A, abeille
-
B, baleine
-
C, chien
curl -X GET /api/entities/v1/animal?_locale=en_GB
-
A, bee
-
B, whale
-
C, dog
curl -X GET /api/entities/v1/animal?filter[description][LIKE]=h&_locale=en_GB
*
curl -X GET /api/entities/v1/animal?i18nFilter[description][LIKE]=h&_locale=en_GB
-
B, whale
-
C, chien
curl -X GET /api/entities/v1/animal?_ignoreI18n=true&_locale=enGB
-
A, abeille
-
B, baleine
-
C, chien
curl -X GET /api/entities/v1/animal?sort=description&_locale=enGB
-
A, bee
-
B, whale
-
C, dog
curl -X GET /api/entities/v1/animal?sort=description&_i18nSort=true&_locale=enGB
-
A, bee
-
C, dog
-
B, whale
6.5. Les API sortant du cas standard
6.5.1. L’API des relevés de mesure /entities/v1/measurereading
L’ajout des relevés de mesure ne peut être pris en charge par l’API standard car il comporte une particularité.
En effet, le calcul de la variation en fonction de la mesure (et inversement) est un traitement particulier qui n’entre pas dans un cas standard d’ajout d’une entité.
Une API a été réalisée spécifiquement pour l’ajout d’un relevé de mesure : se reporter au chapitre Scénario d’ajout des relevés de mesure : l’API /measure-readings pour une explication détaillée.
6.6. Interagir avec le cycle de vie
Au-delà des interactions CRUD (créer, lire, modifier, supprimer), l’API /entities permet de faire évoluer l’état des objets métier le long de leur cycle de vie.
Dans CARL Source, les objets métier les plus centraux disposent d’un cycle de vie : il s’agit d’une succession d’états reliés entre eux par des transitions.
Exemple : par défaut, à sa création, une demande d’intervention est positionnée à l’état Attente prise en compte.
À partir de cet état, différentes transitions sont disponibles, menant chacune vers un nouvel état :
-
La transition Accepter la demande d’intervention mène vers l’état Attente réalisation.
-
La transition Transférer la demande d’intervention boucle sur l’état courant Attente prise en compte.
-
La transition Refuser la demande d’intervention mène vers l’état Refusé.
-
La transition Demander un complément d’information mène vers l’état Attente information.
-
La transition Clôturer la demande mène vers l’état Soldé.
Reprenons la demande d’intervention créée précédemment.
Son identifiant est 166ee780a94-1486 et elle se trouve à l’état Attente prise en compte (correspondant à un attribut "statusCode" positionné à la valeur "REQUEST").
Si l’on cherche à consulter les données relatives à cette demande d’intervention (via la commande suivante) :
curl -X GET -H "X-CS-Access-Token: votre_access_token" https://carlsource.server.com/gmaoCS02/api/entities/v1/mr/166ee780a94-1486
On obtient en retour les informations suivantes :
{
"data" : {
"id" : "166ee780a94-1486",
"type" : "mr",
"attributes" : {
"code" : "000005",
"description" : "Nouvelle demande",
"workPriority" : "HIGH",
"statusCode" : "REQUEST"
...
},
"relationships" : {
...
},
"links" : {
"self" : "https://carlsource.server.com/gmaoCS02/api/entities/v1/mr/166ee780a94-1486",
"workflow-transitions" : "https://carlsource.server.com/gmaoCS02/api/entities/v1/mr/166ee780a94-1486/workflow-transitions"
}
}
}
La rubrique links nous fournit un lien (URL) via la propriété «workflow-transitions».
L’appel de cette URL permet d’obtenir la liste de toutes les transitions pouvant être jouées à partir de l’état courant de la demande d’intervention :
curl -X GET -H "X-CS-Access-Token: votre_access_token" https://carlsource.server.com/gmaoCS02/api/entities/v1/mr/166ee780a94-1486/workflow-transitions
La liste des transitions pouvant être conséquente, il est possible d’utiliser les capacités de filtrage évoquées plus tôt afin de restreindre la liste aux transitions qui nous intéressent.
Dans cet exemple, on souhaite jouer la transition Accepter la demande d’intervention pour que l’état de la demande d’intervention bascule à Attente réalisation : nous avons donc besoin du code correspondant à cet état "cible".
Ce code peut être obtenu par le biais de la sous-fonctionnalité Workflows d’états de CARL Source (cf. Codes des transitions et des états) : en l’occurrence, le code correspondant à l’état Attente réalisation est AWAITINGREAL.
Nous pouvons maintenant restreindre la liste des transitions à celles dont le nextStepCode vaut AWAITINGREAL :
curl -X GET -H "X-CS-Access-Token: votre_access_token" https://carlsource.server.com/gmaoCS02/api/entities/v1/mr/166ee780a94-1486/workflow-transitions?filter[nextStepCode]=AWAITINGREAL
HTTP/1.1 200
{
"data" : [ {
"id" : "M1B:com.carl.xnet.system.status.TransitionParameters",
"type" : "workflow-transitions",
"attributes" : {
"nextStepCode" : "AWAITINGREAL",
"transitionParameters" : null
},
"relationships" : {
"transition" : {
"links" : {
"self" : "https://carlsource.server.com/gmaoCS02/api/entities/v1/workflow-transitions/M1B:com.carl.xnet.system.status.TransitionParameters/relationships/transition",
"related" : "https://carlsource.server.com/gmaoCS02/api/entities/v1/workflow-transitions/M1B:com.carl.xnet.system.status.TransitionParameters/transition"
}
}
},
"links" : {
"self" : "https://carlsource.server.com/gmaoCS02/api/entities/v1/workflow-transitions/M1B:com.carl.xnet.system.status.TransitionParameters"
}
},
{
"id" : "M1:com.carl.xnet.system.status.TransitionParameters",
"type" : "workflow-transitions",
"attributes" : {
"nextStepCode" : "AWAITINGREAL",
"transitionParameters" : null
},
"relationships" : {
"transition" : {
"links" : {
"self" : "https://carlsource.server.com/gmaoCS02/api/entities/v1/workflow-transitions/M1:com.carl.xnet.system.status.TransitionParameters/relationships/transition",
"related" : "https://carlsource.server.com/gmaoCS02/api/entities/v1/workflow-transitions/M1:com.carl.xnet.system.status.TransitionParameters/transition"
}
}
},
"links" : {
"self" : "https://carlsource.server.com/gmaoCS02/api/entities/v1/workflow-transitions/M1:com.carl.xnet.system.status.TransitionParameters"
}
} ]
}
On constate dans la réponse ci-dessus que deux transitions permettent de faire passer la demande d’intervention à l’état Attente réalisation.
L’API nous donne les moyens de connaitre le détail de chaque transition via relationships.transition.links.related :
-
/api/entities/v1/workflow-transitions/M1B:com.carl.xnet.system.status.TransitionParameters/transition
-
/api/entities/v1/workflow-transitions/M1:com.carl.xnet.system.status.TransitionParameters/transition
Appel du détail de la première transition (M1B:com.carl.xnet.system.status.TransitionParameters) :
curl -X GET -H "X-CS-Access-Token: votre_access_token" https://carlsource.server.com/gmaoCS02/api/entities/v1/api/entities/v1/workflow-transitions/M1B:com.carl.xnet.system.status.TransitionParameters/transition
HTTP/1.1 200
{
"data" : {
"id" : "M1B",
"type" : "mrreqawaintingrealtransition",
"attributes" : {
"ordering" : 1,
"description" : "Accepter la DI",
"automatic" : true,
"pageId" : null,
"transitionFamily" : null
},
"relationships" : {
"msgTemplate" : {
"links" : {
"self" : "https://carlsource.server.com/gmaoCS02/api/entities/v1/mrreqawaintingrealtransition/M1B/relationships/msgTemplate",
"related" : "https://carlsource.server.com/gmaoCS02/api/entities/v1/mrreqawaintingrealtransition/M1B/msgTemplate"
}
},
"nextStep" : {
"links" : {
"self" : "https://carlsource.server.com/gmaoCS02/api/entities/v1/mrreqawaintingrealtransition/M1B/relationships/nextStep",
"related" : "https://carlsource.server.com/gmaoCS02/api/entities/v1/mrreqawaintingrealtransition/M1B/nextStep"
}
},
"step" : {
"links" : {
"self" : "https://carlsource.server.com/gmaoCS02/api/entities/v1/mrreqawaintingrealtransition/M1B/relationships/step",
"related" : "https://carlsource.server.com/gmaoCS02/api/entities/v1/mrreqawaintingrealtransition/M1B/step"
}
}
},
"links" : {
"self" : "https://carlsource.server.com/gmaoCS02/api/entities/v1/mrreqawaintingrealtransition/M1B"
}
}
}
Le détail de la transition nous indique que celle-ci est automatique ("automatic" : true) : elle peut donc être appelée sans paramètre.
=> Appliquons cette transition à notre demande d’intervention.
Pour réaliser cette transition d’état, il est nécessaire d’effectuer un POST de la transition sur l’URL de workflow-transitions de notre demande d’intervention :
curl -X POST -H "X-CS-Access-Token: votre_access_token" -H "Content-Type: application/vnd.api+json, Accept: application/vnd.api+json" \ -d '{ "data" : { "id" : "M1B:com.carl.xnet.system.status.TransitionParameters", "type" : "workflow-transitions", "attributes" : { "nextStepCode" : "AWAITINGREAL", "transitionParameters" : null }, "relationships" : { "transition" : { "links" : { "self" : "https://carlsource.server.com/gmaoCS02/api/entities/v1/workflow-transitions/M1B:com.carl.xnet.system.status.TransitionParameters/relationships/transition", "related" : "https://carlsource.server.com/gmaoCS02/api/entities/v1/workflow-transitions/M1B:com.carl.xnet.system.status.TransitionParameters/transition" } } }, "links" : { "self" : "https://carlsource.server.com/gmaoCS02/api/entities/v1/workflow-transitions/M1B:com.carl.xnet.system.status.TransitionParameters" } } }' \ https://carlsource.server.com/gmaoCS02/api/entities/v1/mr/166ee780a94-1486/workflow-transitions
Nous ne nous intéresserons pas au JSON retourné (il s’agit uniquement du détail de la transition jouée).
En revanche, si l’on demande à nouveau le détail de la demande d’intervention, on peut constater que son attribut statusCode est passé de REQUEST à AWAITINGREAL :
curl -X GET -H "X-CS-Access-Token: votre_access_token" https://carlsource.server.com/gmaoCS02/api/entities/v1/mr/166ee780a94-1486?fields[mr]=code,description,statusCode
HTTP/1.1 200
{
"data" : {
"id" : "166ee780a94-1486",
"type" : "mr",
"attributes" : {
"code" : "000001",
"description" : "Nouvelle demande urgente",
"statusCode" : "AWAITINGREAL"
},
"links" : {
"self" : "https://carlsource.server.com/gmaoCS02/api/entities/v1/mr/166ee780a94-1486",
"workflow-transitions" : "https://carlsource.server.com/gmaoCS02/api/entities/v1/mr/166ee780a94-1486/workflow-transitions"
}
}
}
6.7. Le dictionnaire CARL Source
L’API /entities de CARL Source est autodescriptive : les objets JSON retournés dans la réponse HTTP incluent des URL directement invocables afin de pouvoir "naviguer" dans un graphe d’objet tout en le découvrant.
Il y a toutefois des limites : il est nécessaire de connaitre le code du type d’objet que l’on souhaite manipuler (mr dans nos exemples).
De même, s’il est possible de découvrir les transitions disponibles à partir de l’état courant d’un objet, les codes des états dans lesquels un objet peut se trouver ne sont pas fournis par l’API.
Ces codes sont disponibles depuis la fonctionnalité Dictionnaire de CARL Source, et sa sous-fonctionnalité Workflows d’états (menu Système).
6.7.1. Codes des types d’objets
Les objets du dictionnaire décrivent tous les objets de CARL Source, quels que soient leur type, mais tous ne sont pas manipulables par l’API /entities : seuls sont manipulables les objets de catégorie Entité (objectType = BEAN) - cela représente plus de 500 objets.
|
|
Quelques rares exceptions sont à noter - certains objets particulièrement techniques (propres au fonctionnement interne de CARL Source) sont :
|
À partir de ces objets, retrouver le code du type d’objet à utiliser avec l’API s’avère très simple : il s’agit de la valeur du code de l’objet, en minuscule.
Quelques exemples :
-
Pour l’objet du dictionnaire Intervention, le code vaut WO : le code à utiliser dans l’API est donc wo.
=> Exemple : https://carlsource.server.com/gmaoCS02/api/entities/v1/wo liste les interventions définies dans CARL Source. -
Pour l’objet du dictionnaire Client, le code vaut CUSTOMER : le code à utiliser dans l’API est donc customer.
=> Exemple : https://carlsource.server.com/gmaoCS02/api/entities/v1/customer liste les clients définis dans CARL Source. -
Pour l’objet du dictionnaire Centre de coût, le code vaut COSTCENTER : le code à utiliser dans l’API est donc costcenter.
=> Exemple : https://carlsource.server.com/gmaoCS02/api/entities/v1/costcenter liste les centres de coût définis dans CARL Source. -
Pour l’objet du dictionnaire Intervenant, le code vaut TECHNICIAN : le code à utiliser dans l’API est donc technician.
=> Exemple : https://carlsource.server.com/gmaoCS02/api/entities/v1/technician liste les intervenants définis dans CARL Source. -
etc.
6.7.2. Codes des transitions et des états
Nous avons vu que les transitions d’un objet entre deux états (via la propriété workflow-transitions) pouvaient facilement être découvertes via les URL retournées par l’API.
En revanche, les différents états possibles pour un objet CARL Source ne peuvent pas être découverts de la même manière.
Afin d’avoir une vue de ces différents états, il est nécessaire de consulter la sous-fonctionnalité du Workflows d’états depuis le dictionnaire CARL Source.
Cela permet par exemple de saisir qu’une demande d’intervention dont l’attribut statusCode vaut REQUEST :
-
est en Attente de prise en compte,
-
que l’état suivant le plus probable est AWAITINGREAL (Attente réalisation),
-
et que l’on peut parvenir à ce nouvel état en appliquant la transition Accepter la DI.
7. Scénario IIOT : Faire interagir les objets connectés avec CARL Source
Ce chapitre explique comment faire interagir les objets connectés avec CARL Source.
|
|
Dans les requêtes qui suivent, les valeurs en rouge sont à modifier en fonction de votre configuration ou de vos besoins. |
7.1. Contexte
7.1.1. L’appairage entre un capteur et un point de mesure
Un capteur peut être associé à un ou plusieurs points de mesure CARL Source. Pour cela, une entité a été créée sous le nom de SensorPairing.
Cette entité représente l’appairage entre un capteur et un point de mesure. Cela signifie donc qu’un appairage doit avoir 1 point de mesure, et un point de mesure peut avoir 0 ou 1 appairage.
L’ensemble des appairages représente ainsi les différentes associations d’un capteur aux points de mesure de CARL Source.
L’entité SensorPairing contient les attributs suivants :
| Attribut | Type | Obligatoire ? | Description |
|---|---|---|---|
description |
Alphanumérique |
Non |
Description |
databaseName |
Alphanumérique |
Oui |
Nom de la base de données dans laquelle le capteur est géré |
measurement |
Alphanumérique |
Oui |
Nom de la mesure dans laquelle le capteur est géré |
sensorTags |
Liste de SensorTag |
Oui |
Liste des tags |
field |
Alphanumérique |
Oui |
Mesure |
dateOfPairing |
Date |
Oui |
Date d’appairage |
measurePoint |
MeasurePoint |
Oui |
Point de mesure associé |
7.1.2. Les tags associés à un appairage
Un appairage doit avoir 1 ou plusieurs tags. Une entité SensorTag a donc été créée pour remplir ce rôle.
Cette entité est constituée d’une combinaison clé/valeur et est associée à un appairage. Elle contient les attributs suivants :
| Attribut | Type | Obligatoire ? | Description |
|---|---|---|---|
tagKey |
Alphanumérique |
Oui |
Clé |
tagValue |
Alphanumérique |
Oui |
Valeur |
sensorPairing |
SensorPairing |
Oui |
Appairage associé |
Par défaut, lors de la création d’un appairage, deux tags sont créés automatiquement. Ceux-ci représentent le point de mesure et l’équipement associés :
| Clé | Valeur |
|---|---|
MEASURE_POINT |
id CARL Source du point de mesure |
EQUIPMENT |
id CARL Source de l’équipement |
7.2. Créer, lire, modifier et supprimer un appairage de capteur
7.2.1. Création
curl -X POST -H "X-CS-Access-Token: votre_access_token" -H "Content-Type: application/vnd.api+json" \ -d '{ "data": { "type": "sensorpairing", "attributes": { "description": "mon premier appairage", "databaseName": "nom de la base", "measurement": "nom de la mesure", "field": "mesure", "dateOfPairing": "2019-12-10T19:10:00.000+02:00" }, "relationships": { "measurePoint": { "data": { "type": "measurepoint", "id": "measurepoint_id" } } } } }' \ https://carlsource.server.com/gmaoCS02/api/entities/v1/sensorpairing
Le JSON décrivant l’appairage venant d’être créé est reçu en réponse à cette requête, avec un code HTTP 201.
|
|
Les deux tags MEASURE_POINT et EQUIPMENT ont également été créés. |
7.2.2. Lecture
7.2.2.1. Lister tous les appairages
curl -X GET -H "X-CS-Access-Token: votre_access_token" https://carlsource.server.com/gmaoCS02/api/entities/v1/sensorpairing/
7.2.2.2. Lister tous les appairages entre un capteur et ses points de mesure
curl -X GET -H "X-CS-Access-Token: votre_access_token" https://carlsource.server.com/gmaoCS02/api/entities/v1/sensortag?fields=sensorPairing&filter[tagKey]=SENSOR&filter[tagValue]=sensor_name
curl -X GET -H "X-CS-Access-Token: votre_access_token" https://carlsource.server.com/gmaoCS02/api/entities/v1/sensortag?include=sensorPairing&filter[tagKey]=SENSOR&filter[tagValue]=sensor_name
7.2.2.3. Lister tous les points de mesure d’un capteur
Ici, le point de mesure n’est pas directement lié au tag : il faut l’inclure à la requête en passant par l’appairage.
Dans le résultat obtenu la liste des points de mesure du capteur se situera donc dans la balise "included": [...].
curl -X GET -H "X-CS-Access-Token: votre_access_token" https://carlsource.server.com/gmaoCS02/api/entities/v1/sensortag?include=sensorPairing.measurePoint&filter[tagKey]=SENSOR&filter[tagValue]=intensity
7.2.3. Modification
La syntaxe est proche de celle de la création, il suffit de faire pointer l’url sur l’id de l’appairage et d’utiliser uniquement les attributs/relations à modifier.
Exemple :
curl -X PATCH -H "X-CS-Access-Token: votre_access_token" -H "Content-Type: application/vnd.api+json" \ -d '{ "data": { "type": "sensorpairing", "attributes": { "description": "mon premier appairage modifié", "field": "mesure2", "dateOfPairing": "2019-12-10T20:10:00.000+02:00" } } }' \ https://carlsource.server.com/gmaoCS02/api/entities/v1/sensorpairing/pairing_id
7.3. Créer, lire, modifier et supprimer un tag associé à un appairage de capteur
7.3.1. Création
curl -X POST -H "X-CS-Access-Token: votre_access_token" -H "Content-Type: application/vnd.api+json" \ -d '{ "data": { "type": "sensortag", "attributes": { "tagKey": "SENSOR", "tagValue": "engine_temp" }, "relationships": { "sensorPairing": { "data": { "type": "sensorpairing", "id": "pairing_id" } } } } }' \ https://carlsource.server.com/gmaoCS02/api/entities/v1/sensortag
Le JSON décrivant le tag venant d’être créé est reçu en réponse à cette requête, avec un code HTTP 201.
7.3.2. Lecture
7.3.2.1. Lister tous les tags
curl -X GET -H "X-CS-Access-Token: votre_access_token" https://carlsource.server.com/gmaoCS02/api/entities/v1/sensortag/
7.3.2.2. Lister tous les tags filtrés par clé
curl -X GET -H "X-CS-Access-Token: votre_access_token" https://carlsource.server.com/gmaoCS02/api/entities/v1/sensortag?fields=tagKey,tagValue,sensorPairing&filter[tagKey]=MEASURE_POINT
7.3.3. Modification
La syntaxe est proche de celle de la création, il suffit de faire pointer l’url sur l’id du tag et d’utiliser uniquement les attributs/relations à modifier.
Exemple :
curl -X PATCH -H "X-CS-Access-Token: votre_access_token" -H "Content-Type: application/vnd.api+json" \ -d '{ "data": { "type": "sensortag", "attributes": { "tagValue": "intensity" } } }' \ https://carlsource.server.com/gmaoCS02/api/entities/v1/sensortag/tag_id
7.4. Créer et lire un relevé de mesure via un appairage de capteur
7.4.1. Création
curl -X POST -H "X-CS-Access-Token: votre_access_token" -H "Content-Type: application/vnd.api+json" \ -d '{ "data": { "measure": 3, OU "variation": 3, "measuredAt": "2023-04-17T15:07:06", "sensorPairing": { "id": "pairing_id" } } }' \ https://carlsource.server.com/gmaoCS02/api/measure-readings/v1/add
Le JSON décrivant l’appairage venant d’être créé est reçu en réponse à cette requête, avec un code HTTP 201.
|
|
La valeur de l’attribut "Origine" est fixée à 3 (IOT). Les deux tags MEASURE_POINT et EQUIPMENT ont également été créés. |
|
|
Il est également possible d’ajouter une liste de relevés de mesure. |
7.4.2. Lecture
7.4.2.1. Lister tous les relevés de mesure d’un capteur
Dans l’exemple ci-dessous, nous listons tous les relevés de mesure du capteur "intensity".
La variable "fields" affiche uniquement les champs demandés pour optimiser le résultat aux attributs utiles, mais elle peut être retirée de la requête.
curl -X GET -H "X-CS-Access-Token: votre_access_token" https://carlsource.server.com/gmaoCS02/api/entities/v1/measurereading?fields=measure,variation,dateMeasure,description,measurePoint,sensorPairing&filter[measurereading][description][LIKE]=SENSOR=intensity
|
|
Cette requête peut être adaptée afin de filtrer les relevés de mesure en fonction des tags d’appairage concaténés dans la description des relevés. |
7.4.2.2. Lister tous les relevés de mesure d’un appairage
curl -X GET -H "X-CS-Access-Token: votre_access_token" https://carlsource.server.com/gmaoCS02/api/entities/v1/measurereading?filter[sensorPairing.id]=pairing_id
7.4.2.3. Lister tous les relevés de mesure d’un point de mesure
curl -X GET -H "X-CS-Access-Token: votre_access_token" https://carlsource.server.com/gmaoCS02/api/entities/v1/measurereading?filter[measurePoint.id]=measurepoint_id
8. Scénario d’utilisation des documents liés : l’API /ui/v1/documents
L’API /ui/v1/documents a été créée en premier lieu pour être utilisée par les IHM de l’application, d’où son emplacement dans /ui/v1.
Elle peut néanmoins être utilisée dans un contexte hors IHM par une application externe.
8.1. Modèle de données
8.1.1. Nom de classe Java™ des entités
Contrairement aux APIs génériques de type JSON:API qui permettent de manipuler les entités, cette API nécessite que l’on précise directement le nom de la classe Java™ du type d’entité sur laquelle on veut manipuler les documents.
Pour obtenir ce nom de classe de façon simple vous pouvez interroger l’application via un appel JSON-API.
WOcurl -X GET -H "X-CS-Access-Token: votre_access_token" \ https://carlsource.server.com/gmaoCS02/api/entities/v1/objectinfo?"filter[code]=WO&fields=typeName"
{
"data": [
{
"id": "WO",
"type": "objectinfo",
"links": {
"self": "https://carlsource.server.com/gmaoCS02/api/entities/v1/objectinfo/WO"
},
"attributes": {
"typeName": "com.carl.xnet.works.backend.bean.WOBean"
}
}
],
"links": {
"self": "code=WO&fields=typeName"
}
}
8.1.2. Types de documents liés
Dans l’application CARL Source, les documents liés à une entité sont classés par type de document : un contrat, un schéma technique, une icône, un fond de plan de bâtiment. Le type n’est pas un type de format de fichier (PNG, JPEG, PDF, Word, etc.) mais une catégorie liée à leur usage.
Ces types de documents sont accessibles depuis la fonctionnalité "Type de documents" du module "Système". C’est le code du type de document qui est utilisé dans l’API des documents liés.
8.2. Upload (téléversement) d’un document lié
L’API /ui/v1/documents/entity/upload/<entity-class-name>/<entity-id> permet de téléverser un nouveau document et de le lier à l’entité dont on donne le type (nom de classe Java™) et l’identifiant. Le contenu de la requête est au format multipart/form-data, identique à ce qui est utilisé par un navigateur pour envoyer un fichier.
17c30872770-7c :curl -X POST -H "X-CS-Access-Token: votre_access_token" \ -F "type=DOC" \ -F "description=Nouveau document" \ -F "file=@NouveauDoc.pdf" \ https://carlsource.server.com/gmaoCS02/api/ui/v1/documents/entity/upload/com.carl.xnet.works.backend.bean.WOBean/17c30872770-7c
{
"data": [
{
"type": "documents",
"id": "17c30872770-3336",
"attributes": {
"fileName": "NouveauDoc.pdf",
"code": "DOC-00005",
"description": "Nouveau document",
"type": "DOC"
},
"links": {
"download": "https://carlsource.server.com/gmaoCS02/download/servlet/NouveauDoc.pdf?docid\u003d17c30872770-3337\u0026version\u003d0"
}
}
]
}
Paramètres supplémentaires :
-
code (facultatif) : le code du document lié qui sera créé. Par défaut c’est la codification automatique qui est utilisée, mais il est possible de le définir. Exemple :
code=CONTRAT-0001.
|
|
Le lien |
8.3. Download (téléchargement) d’un document lié
Pour télécharger un document lié, il est nécessaire d’utiliser l’API /ui/v1/documents/download/<document-id>.
17c30872770-3336curl -X GET -H "X-CS-Access-Token: votre_access_token" --output "doc.pdf" \ https://carlsource.server.com/gmaoCS02/api/ui/v1/documents/download/17c30872770-3336
8.4. Lister les documents liés à une entité
Pour récupérer la liste des documents liés à une entité, on utilise l’API /ui/v1/documents/entity/<entity-class-name>/<entity-id>.
17c30872770-7ccurl -X GET -H "X-CS-Access-Token: votre_access_token" \ https://carlsource.server.com/gmaoCS02/api/ui/v1/documents/entity/com.carl.xnet.works.backend.bean.WOBean/17c30872770-7c
{
"data": [
{
"type": "documents",
"id": "17c30872770-3ca5",
"attributes": {
"fileName": "Photo.jpg",
"code": "DOC-00008",
"description": "Photo.jpg",
"type": "IMG"
},
"links": {
"download": "https://carlsource.server.com/gmaoCS02/download/servlet/Photo.jpg?..."
}
},
{
"type": "documents",
"id": "17c30872770-3ca4",
"attributes": {
"fileName": "Manuel technique.pdf",
"code": "DOC-00007",
"description": "Manuel technique.pdf",
"type": "PLAN"
},
"links": {
"download": "https://carlsource.server.com/gmaoCS02/download/servlet/Manuel+technique.pdf?..."
}
},
{
"type": "documents",
"id": "17c30872770-3ca6",
"attributes": {
"fileName": "Contrat.pdf",
"code": "DOC-00009",
"description": "Contrat.pdf",
"type": "DOC"
},
"links": {
"download": "https://carlsource.server.com/gmaoCS02/download/servlet/Contrat.pdf?..."
}
}
],
"meta": {
"isEntityDocumentable": true,
"numberOfDocumentsInWidget": 3,
"hasMoreResults": false,
"canUploadDocuments": true,
"canReadDocuments": true
},
"included": [
{
"type": "document-type",
"id": "DOC",
"attributes": {
"code": "DOC",
"description": "Textes, contrats"
}
},
...
]
}
La réponse fournit également (via les rubriques meta et included) un certain nombre d’informations supplémentaires utiles pour une IHM :
-
l’entité supporte les documents liés,
-
l’utilisateur peut téléverser ou télécharger des documents liés pour cette entité,
-
ainsi que la liste des types de documents avec leurs libellés.
|
|
Comme précisé plus haut pour l’API d’upload (téléversement) d’un document lié, il ne faut pas tenir compte du lien |
Paramètres de filtre supplémentaires :
-
type (facultatif) : une liste de types de documents séparés par des virgules. Exemple :
type=IMG,ICON. -
pictureType (facultatif) : un booléen permettant de filtrer les résultats en fonction de la caractérisation des types de documents comme étant (ou non) des images (cf. la fonctionnalité "Type de documents" du module "Système"). Exemple :
pictureType=true.
9. Scénario d’import d’équipements : l’API /import-equipment
L’API /import-equipment permet d’importer en masse des équipements dans CARL Source, puis de les mettre à jour après un import initial.
Cette API ayant un lien avec les fonctions d’import d’équipements pour les cartes, plans de bâtiments, puis pour le BIM, elle est située avec les APIs REST dédiées au SIG : /gis/v1/import-equipment.
L’import se réalise en deux temps :
-
Utilisation des APIs REST pour importer les descriptions des équipements dans la table de référence : CSGI_IMP_EQUIPMENT;
-
Utilisation du traitement d’import d’équipements GISIMPORTJOB, dans la fonctionnalité CARL Source des traitements automatiques.
9.1. Droit d’utilisation de l’API
L’utilisation de cette API nécessite que l’utilisateur avec lequel est invoquée l’API dispose des droits de profil requis. L’API est contrôlée par le droit de profil : Equipements / Import d’équipements.
9.2. Insérer, modifier, ou supprimer des descriptions d’équipements dans la table d’import
L’API /gis/v1/import-equipment/apply-batch-operations permet de modifier en lot la table d’import.
Cette API permet d’envoyer, dans une requête POST au format JSON (Media-Type: application/json), une liste d’opérations à réaliser sur la table d’import.
[
{
"action": "CREATE",
"equipment": {"id":"1", "structureId":"MATERIAL", "projectGuid":"18"}
},
{
"action": "DELETE",
"equipment": {"id":"2"}
}
]
Les actions disponibles pour la description d’équipement sont les suivantes :
| Action | Description |
|---|---|
CREATE |
La ligne d’import est créée ( |
UPDATE |
La ligne d’import est mise à jour ( |
SYNC |
La ligne d’import est marquée comme étant mise à jour ( |
DELETE |
La ligne d’import est marquée pour suppression ( |
Les champs correspondants pour la description d’équipement sont les suivants :
| Champs | Type (Format ou Longueur) | Opération | Description |
|---|---|---|---|
|
Alphanumérique (33) |
CREATE, UPDATE, SYNC, DELETE |
Identifiant de l’équipement dans la table d’import |
|
Alphanumérique (20) |
CREATE |
Code de l’équipement à importer (identifiant métier) |
|
Alphanumérique (40) |
CREATE |
Identifiant (GUID) du projet BIM |
|
Alphanumérique (60) |
CREATE, UPDATE |
Description de l’équipement à importer (libellé) |
|
Alphanumérique (40) |
CREATE, UPDATE |
Identifiant du type de structure |
|
Alphanumérique (33) |
CREATE, UPDATE |
Identifiant de l’équipement parent dans la table d’import |
|
Alphanumérique (255) |
CREATE, UPDATE |
Classe IFC |
|
Alphanumérique (JSON) |
CREATE, UPDATE |
Attributs d’objet génériques (par exemple issus de l’IFC) |
|
Alphanumérique (20) |
CREATE, UPDATE |
Code d’un article ou d’un modèle pour l’équipement |
|
Numérique (nombre entier) |
CREATE, UPDATE |
Capacité d’accueil, Numéro d’étage |
|
Numérique |
CREATE, UPDATE |
Surface utile, Surface de plancher, Surface de terrain |
|
Alphanumérique (255) |
CREATE, UPDATE |
Usage, Classification ERP, Catégorie ERP |
|
Alphanumérique (255) |
CREATE, UPDATE |
Chemin relatif du DWF dans la bibliothèque, Nom du DWG d’origine |
|
Alphanumérique (EWKT) |
CREATE, UPDATE |
Géométrie (point, ligne, ou polygone) |
|
Booléen |
CREATE, UPDATE |
Champs booléens libres |
|
Alphanumérique (date-heure ISO8601) |
CREATE, UPDATE |
Champs dates-heures libres |
|
Numérique |
CREATE, UPDATE |
Champs numériques libres |
|
Alphanumérique (255) |
CREATE, UPDATE |
Champs textes libres |
|
|
L’usage de cette API nécessite que l’utilisateur dispose de tous les droits de Création, Modification, Suppression dans le droit de profil : Equipements / Import d’équipements. |
curl -X POST -H "X-CS-Access-Token: votre_access_token" -H "Content-Type: application/json" --data-binary "@path/to/file" https://carlsource.server.com/gmaoCS02/api/gis/v1/import-equipment/apply-batch-operations
[
{
"action": "CREATE",
"equipment": {
"id":"1254",
"code":"B2",
"description":"Bat 2",
"structureId":"BUILDING",
"ifcClass":"IFCBUILDING",
"projectGuid":"GUID2",
"area":1200,
"attributes":"{attr1:0}"
}
},
{
"action": "UPDATE",
"equipment": {
"id":"125",
"description":"Bat 1 - new description",
"structureId":"BUILDING",
"area":1750
}
},
{
"action": "SYNC",
"equipment": {
"id":"12"
}
},
{
"action": "DELETE",
"equipment": {
"id":"123"
}
}
]
|
|
Une fois la requête exécutée avec succès, il est nécessaire de lancer dans CARL Source le traitement d’import d’équipements GISIMPORTJOB à partir de la fonctionnalité "Traitements automatiques". |
9.3. Récupérer les descriptions des équipements déjà présents dans la table d’import
L’API /gis/v1/import-equipment/stream-equipments/{bimprojectguid} permet de récupérer toutes les lignes de la table d’import associées à un projet référencé par son bimprojectguid.
Le résultat est retourné au format ndjson (Media-Type: application/x-ndjson) : chaque enregistrement est converti au format JSON sur une seule ligne, et chaque ligne est séparée par le caractère : \n.
curl -X GET -H "X-CS-Access-Token: votre_access_token" https://carlsource.server.com/gmaoCS02/api/gis/v1/import-equipment/stream-equipments/GUID1
HTTP/1.1 200
{"id": "1","code": "B1","description": "New building","area": 1200.0,"structureId": "BUILDING","attributes": "{attr1:0}","ifcClass": "IFCBUILDING"}
{"id": "2","code": "B2","description": "Building 2","area": 900.0,"structureId": "BUILDING","attributes": "{attr1:0}","ifcClass": "IFCBUILDING"}
|
|
L’usage de cette API nécessite que l’utilisateur dispose du droit de Lecture dans le droit de profil : Equipements / Import d’équipements. |
10. Scénario d’utilisation des indicateurs : l’API /ui/v1/indicators
L’API /ui/v1/indicators permet de récupérer la valeur d’un indicateur tout en permettant de faire varier les valeurs des critères de cet indicateur.
10.1. Création d’un indicateur
Pour être utilisable, cette API nécessite la création d’un indicateur. Il est possible de créer aussi bien un indicateur de type filtre que de type requête. A noter qu’il sera possible de faire varier la valeur des critères sur un indicateur de type filtre.
Le filtre peut être créé depuis un écran de recherche de CARL Source (éventuellement complété d’un filtre avancé) en utilisant l’action Transformer en indicateur.
Dans la suite de ce scénario, on crée un indicateur qui s’appuie sur le bean de recherche MRSELBean. Cet indicateur comporte un critère de filtre sur le statut (qui fait partie du bean de recherche) ainsi que deux critères personnalisés : un premier sur le champ xtraTxt01 et un autre sur le champ externalEntityId.
A noter qu’il est possible de modifier la description du filtre (qui correspondra à la valeur utilisée pour identifier le filtre dans les requêtes API) dans l’écran d’édition des filtres avancés. Mais il n’est pas possible ensuite de modifier cette description dans l’écran d’édition de l’indicateur.
10.2. Récupération des informations sur l’indicateur
Cette partie s’appuie sur les API des entités au format JSON:API en utilisant le type indicator.
Ici, on récupère les informations sur l’indicateur en partant de son code et en incluant également ses critères :
curl -X GET -H "X-CS-Access-Token: votre_access_token" \
https://carlsource.server.com/gmaoCS02/api/entities/v1/indicator?include=criteria&filter[code]=IND_MR_CUSTOM
{
"data": [
{
"id": "17c57530346-f01",
"type": "indicator",
"attributes": {
"code": "IND_MR_CUSTOM",
"description": "Texte pour IND_MR_CUSTOM",
"type": "FILTER",
"targetForm": "MR_SELId",
"dataBean": "com.carl.xnet.works.backend.bean.MRBean",
"searchBean": "com.carl.xnet.works.backend.search.MRSELBean"
}
}
],
"included": [
{
"id": "17c57530346-dee",
"type": "indicatorcriterion",
"attributes": {
"criterion": "status",
"description": "status",
"criterionValue": "[REQUEST,WAITINFO,AWAITINGREAL]",
}
},
{
"id": "17c57530346-def",
"type": "indicatorcriterion",
"attributes": {
"description": "xtraTxt01",
"criterionValue": "123456",
"operator": 6,
"property": "xtraTxt01"
}
},
{
"id": "17c57530346-df1",
"type": "indicatorcriterion",
"attributes": {
"description": "externalEntityId",
"criterionValue": "12",
"operator": 6,
"property": "eqpt.externalEntityId",
}
}
]
}
10.3. Récupération de la valeur de cet indicateur avec les critères par défaut
L’appel suivant permet de récupérer la valeur courante de l’indicateur sans modifier les valeurs des critères de l’indicateur.
A noter qu’un recalcul est forcé à chaque appel (même si l’indicateur a une information de rafraîchissement différente de 0).
curl -X POST -i -H "X-CS-Access-Token: votre_access_token" -H "Content-Type: application/vnd.api+json" \
-d '{
"code": "IND_MR_CUSTOM"
}' \
https://carlsource.server.com/gmaoCS02/api/ui/v1/indicators/values
{
"data": [
{
"type": "com.carl.xnet.analyse.backend.bean.indicator",
// l’identifiant est retourné, que l’on passe le code ou l’identifiant en paramètre
"id": "17c57530346-f01",
"attributes": {
"values": [
{
"value": 42.0
}
]
}
}
]
}
|
|
Il est possible de passer l’identifiant de l’indicateur au lieu de son code en remplaçant le paramètre |
10.4. Récupération de la valeur de cet indicateur avec un critère modifié
On peut ensuite modifier la valeur d’un critère de filtre (ici : externalEntityId).
Dans l’exemple suivant, on passe deux valeurs différentes dans le même appel :
curl -X POST -i -H "X-CS-Access-Token: votre_access_token" -H "Content-Type: application/vnd.api+json" \
-d '{
"code": "IND_MR_CUSTOM",
"filters":[
{
"filterId": "1",
"criteria": [
{
"name": "externalEntityId",
"value":"first entity"
}
]
},
{
"filterId": "2",
"criteria": [
{
"name": "externalEntityId",
"value":"other entity"
}
]
}
]
}' \
https://carlsource.server.com/gmaoCS02/api/ui/v1/indicators/values
{
"data": [
{
"type": "com.carl.xnet.analyse.backend.bean.indicator",
"id": "17c57530346-f01",
"attributes": {
"values": [
{
"filterId": "1",
"value": 10.0
},
{
"filterId": "2",
"value": 21.0
}
]
}
}
]
}
Dans ce cas, la réponse obtenue indique l’identifiant du filtre passé en paramètre ainsi que la valeur associée.
|
|
Si la requête de l’indicateur est complexe (ex : table chargée, critère de filtre non indexé), il faut éviter de demander trop de valeurs en une seule fois : cela entraînerait un temps de réponse important. |
10.5. Récupération de la valeur de cet indicateur avec plusieurs critères modifiés
Il est également possible de faire varier plusieurs critères de filtre.
Par exemple :
curl -X POST -i -H "X-CS-Access-Token: votre_access_token" -H "Content-Type: application/vnd.api+json" \
-d '{
"code": "IND_MR_CUSTOM",
"filters":[
{
"filterId": "1",
"criteria": [
{
"name": "externalEntityId",
"value":"first entity"
},
{
"name": "xtraTxt01",
"value":"a value for xtraTxt01"
}
]
}
]
}' \
https://carlsource.server.com/gmaoCS02/api/ui/v1/indicators/values
{
"data": [
{
"type": "com.carl.xnet.analyse.backend.bean.indicator",
"id": "17c57530346-f01",
"attributes": {
"values": [
{
"filterId": "1",
"value": 13.0
}
]
}
}
]
}
11. Scénario d’ajout des relevés de mesure : l’API /measure-readings
L’API /measure-readings permet d’ajouter un ou plusieurs relevés de mesure.
11.1. Droits d’utilisation de l’API
L’utilisation de cette API nécessite que l’utilisateur avec lequel est invoquée l’API dispose des droits de profil requis.
L’API est contrôlée par le droit de profil : Equipements / Relevé de mesure.
11.2. Insérer / Lire des relevés de mesure
11.2.1. Insérer un relevé de mesure
L’API /measure-readings/v1/add permet d’envoyer, dans une requête POST au format JSON (Media-Type: application/json), un relevé de mesure à un point de mesure.
curl -X POST -H "X-CS-Access-Token: votre_access_token" -H "Content-Type: application/vnd.api+json" \ -d '{ "data": { "origin": "AUTO", "measure": 10000, OU "variation": 10, "measuredAt": "2023-04-17T15:07:06", "measurePoint": { "id": "6" OU "code": "CPT-KM-02" } } }' \ https://carlsource.server.com/gmaoCS02/api/measure-readings/v1/add
Les champs correspondants pour la description du relevé de mesure sont les suivants :
| Champs | Type (Format ou Longueur) | Description | Obligatoire / Facultatif |
|---|---|---|---|
|
Alphanumérique |
Code de l’origine du relevé de mesure (MANUAL, AUTO, IOT) |
Obligatoire si |
|
Numérique |
Valeur de la mesure |
Obligatoire si |
|
Numérique |
Variation du relevé de mesure |
Obligatoire si |
|
Date |
Date de la mesure |
Obligatoire |
|
Booléen |
S’il s’agit d’une correction |
Facultatif |
|
Booléen |
S’il s’agit d’une répercussion |
Facultatif |
|
Alphanumérique (60) |
Description du relevé de mesure |
Facultatif |
|
Point de mesure de référence |
Obligatoire si |
|
|
Appairage de capteur de référence |
Obligatoire si |
|
|
L’utilisation de L’utilisation de |
Les champs correspondants pour la description du point de mesure de référence sont les suivants :
| Champs | Type (Format ou Longueur) | Description |
|---|---|---|
|
Alphanumérique (20) |
Code du point de mesure (ne pas renseigner si |
|
Alphanumérique (33) |
Id du point de mesure (ne pas renseigner si |
|
|
L’utilisation de |
Les champs correspondants pour la description de l’appairage de capteur de référence sont les suivants :
| Champs | Type (Format ou Longueur) | Description |
|---|---|---|
|
Alphanumérique (33) |
Id de l’appairage de capteur |
HTTP/1.1 201 Created
{
"data": {
"id": "18ad0a4654d-8",
"variation": 0.0,
"measure": 10000.0,
"measuredAt": "2023-04-17T15:07:06.000",
"correction": false,
"repercussion": false,
"origin": "AUTO",
"measurePoint": {
"id": "6"
},
"modifyDate": "2023-09-26T10:41:53.996",
"noChrono": false
}
}
11.2.2. Insérer une liste de relevés de mesure
L’API /measure-readings/v1/add-all permet d’envoyer, dans une requête POST au format JSON (Media-Type: application/json), une liste de relevés de mesure à un ou plusieurs points de mesure.
|
|
Cette liste permet d’ajouter des relevés de mesure sur différents points de mesure. |
curl -X POST -H "X-CS-Access-Token: votre_access_token" -H "Content-Type: application/vnd.api+json" \ -d '{ "data":[ { "origin": "AUTO", "variation": 5, "measuredAt": "2023-05-18T15:59:06", "measurePoint": { "code": "CPT-KM-02" } }, { "origin": "MANUAL", "measure": 10, "measuredAt": "2023-05-18T16:57:06", "measurePoint": { "id": "12" } }, { "origin": "AUTO", "measure": 11000, "measuredAt": "2023-05-18T15:57:06", "measurePoint": { "code": "CPT-KM-02" } } ] }' \ https://carlsource.server.com/gmaoCS02/api/measure-readings/v1/add-all
|
|
Les champs à renseigner sont identiques à ceux de l’API /measure-readings/v1/add. |
HTTP/1.1 201 Created
{
"data": [
{
"id": "18ad0e3e436-4e4",
"variation": 0.0,
"measure": 10.0,
"measuredAt": "2023-05-18T16:57:06.000",
"correction": false,
"repercussion": false,
"origin": "MANUAL",
"measurePoint": {
"id": "12"
},
"modifyDate": "2023-09-26T15:11:51.219",
"noChrono": false
},
{
"id": "18ad0e3e436-4e6",
"variation": 1000.0,
"measure": 11000.0,
"measuredAt": "2023-05-18T15:57:06.000",
"correction": false,
"repercussion": false,
"origin": "AUTO",
"measurePoint": {
"id": "6"
},
"modifyDate": "2023-09-26T15:11:51.317",
"noChrono": false
},
{
"id": "18ad0e3e436-4e7",
"variation": 5.0,
"measure": 11005.0,
"measuredAt": "2023-05-18T15:59:06.000",
"correction": false,
"repercussion": false,
"origin": "AUTO",
"measurePoint": {
"id": "6"
},
"modifyDate": "2023-09-26T15:11:51.342",
"noChrono": false
}
]
}
11.2.3. Lire des relevés de mesure
L’API /entities/v1/measurereading permet de retourner, dans une requête GET, les relevés de mesure.
Comme décrit dans le chapitre Lister, filtrer et sélectionner, il est possible d’affiner cette recherche en filtrant, en triant et sélectionnant les attributs à afficher.
Voici un exemple :
https://carlsource.server.com/gmaoCS02/api/entities/v1/measurereading?filter[measurePoint.id]=6&sort=dateMeasure&fields=dateMeasure,measure,variation,description,origin
| Clé | Valeur | Description |
|---|---|---|
|
6 |
Recherche les relevés de mesure du point de mesure ayant pour id : 6 |
|
dateMeasure |
Trie les relevés de mesure par date de mesure croissant |
|
dateMeasure,measure,variation,description,origin |
Affiche uniquement les champs définis |
{
"data": [
{
"id": "4",
"type": "measurereading",
"links": {
"self": "http://localhost:8380/xnet/api/entities/v1/measurereading/4"
},
"attributes": {
"origin": 1,
"description": null,
"variation": 10000.0,
"measure": 10000.0,
"dateMeasure": "2007-12-10T00:00:00.000+01:00"
}
},
{
"id": "18ad0e3e436-442",
"type": "measurereading",
"links": {
"self": "http://localhost:8380/xnet/api/entities/v1/measurereading/18ad0e3e436-442"
},
"attributes": {
"origin": 2,
"description": null,
"variation": 0.0,
"measure": 10000.0,
"dateMeasure": "2023-04-17T15:07:06.000+02:00"
}
},
{
"id": "18ad0e3e436-4e6",
"type": "measurereading",
"links": {
"self": "http://localhost:8380/xnet/api/entities/v1/measurereading/18ad0e3e436-4e6"
},
"attributes": {
"origin": 2,
"description": null,
"variation": 1000.0,
"measure": 11000.0,
"dateMeasure": "2023-05-18T15:57:06.000+02:00"
}
},
{
"id": "18ad0e3e436-4e7",
"type": "measurereading",
"links": {
"self": "http://localhost:8380/xnet/api/entities/v1/measurereading/18ad0e3e436-4e7"
},
"attributes": {
"origin": 2,
"description": null,
"variation": 5.0,
"measure": 11005.0,
"dateMeasure": "2023-05-18T15:59:06.000+02:00"
}
}
],
"links": {
"self": "measurePoint.id=6&sort=dateMeasure&fields=dateMeasure%2Cmeasure%2Cvariation%2Cdescription%2Corigin"
}
}
12. Manipulation des réservations avec l’API /reserves
L’API /reserves permet de manipuler une ou plusieurs réservations (création, mise à jour, recherche, suppression).
12.1. Droits d’utilisation de l’API
L’utilisation de cette API nécessite que l’utilisateur avec lequel est invoquée l’API dispose des droits de profil requis.
L’API est contrôlée par les droits de profil : Travaux / Intervention et Stock / Réservations.
12.2. Créer une ou plusieurs réservations
12.2.1. Créer une réservation
L’API /reserves/v1/add permet d’envoyer, dans une requête POST au format JSON (Media-Type: application/json), une réservation.
|
|
La création d’une réservation est possible uniquement si l’intervention est à l’état "Validée". La création d’une réservation est impossible si la date spécifiée est antérieure à la date de début de l’intervention. Si la date de réservation spécifiée est située après la date de fin de l’intervention, la date de fin de l’intervention sera automatiquement mise à jour avec la date de la réservation. |
curl -X POST -H "X-CS-Access-Token: votre_access_token" -H "Content-Type: application/vnd.api+json" \ -d '{ "data": { "quantity": 1, "reserveDate" : "2024-01-05T09:12:55.835+01:00", "description" : "Test de création de réservation avec l’API REST", "item": { "code": "FILTRE-AIR-D20" } , "wo": { "code": "DEV-WO-017-2006" }, "actor": { "code": "DEMO" }, "warehouse": { "code": "MAG2" } }’\ https://carlsource.server.com/gmaoCS02/api/reserves/v1/add
Les champs correspondants pour la description d’une réservation sont les suivants :
| Champs | Type (Format ou Longueur) | Description | Obligatoire / Facultatif |
|---|---|---|---|
|
Alphanumérique |
Code ou id de l’article |
Obligatoire |
|
Numérique |
Nombre d’articles à réserver |
Obligatoire |
|
Alphanumérique |
Code ou id du magasin de la réservation |
Obligatoire |
|
Alphanumérique |
Intervention porteuse de la réservation |
Obligatoire |
|
Date |
Date de la réservation |
Facultatif. Date du jour par défaut. |
|
Alphanumérique |
Code ou id de l’acteur |
Facultatif. Acteur connecté par défaut. |
|
Alphanumérique (60) |
Description de la réservation |
Facultatif |
HTTP/1.1 201 Created
{
"data": {
"id": "1917e380cdc-ac",
"item": {
"id": "FILTRE-AIR-D20",
"code": "FILTRE-AIR-D20"
},
"quantity": 1.0,
"reserveDate": "2024-01-05T09:12:55.835+01:00",
"wo": {
"id": "DEV17",
"code": "DEV-WO-017-2006"
},
"actor": {
"id": "14",
"code": "DEMO"
},
"description": "Test de création de réservation avec l’API REST"
}
}
12.2.2. Créer une liste de réservations
L’API /reserves/v1/add-all permet d’envoyer, dans une requête POST au format JSON (Media-Type: application/json), une liste de réservations.
|
|
Cette liste permet d’ajouter des réservations sur une ou plusieurs interventions, magasins ou articles. Il n’est pas obligatoire de créer la liste avec le même magasin, article ou intervention. Chaque réservation peut donc contenir des données indépendantes des autres réservations. Si l’API rencontre une erreur fonctionnelle (ex : donnée obligatoire non renseignée ou tentative de création sur une intervention non valide), c’est l’intégralité de la liste qui est rejetée. |
curl -X POST -H "X-CS-Access-Token: votre_access_token" -H "Content-Type: application/vnd.api+json" \ -d '{ "data":[ { "quantity": 1, "reserveDate": "2023-12-11T10:50:46.841+01:00", "description": "Test création de réservation 1", "item": { "code": "FILTRE-AIR-D20" }, "wo": { "code": "DEV-WO-017-2006" }, "actor": { "code": "DEMO" }, "warehouse": { "code": "MAG2" } }, { "quantity": 2, "reserveDate": "2023-12-11T10:50:46.841+01:00", "description": "Test création de réservation 2", "item": { "code": "FILTRE-AIR-D20" }, "wo": { "code": "DEV-WO-017-2006" }, "actor": { "code": "DEMO" }, "warehouse": { "code": "MAG2" } }, { "quantity": 3, "reserveDate": "2023-12-11T10:50:46.841+01:00", "description": "Test création de réservation 3", "item": { "code": "ITEM1" }, "wo": { "code": "DEV-WO-017-2006" }, "actor": { "code": "DEMO" }, "warehouse": { "code": "MAG1" } } ] }’\
|
|
Les champs à renseigner sont identiques à ceux de l’API /reserves/v1/add.
|
HTTP/1.1 201 Created
{
"data": [
{
"id": "1917e380cdc-1eb",
"item": {
"id": "FILTRE-AIR-D20",
"code": "FILTRE-AIR-D20"
},
"quantity": 1.0,
"reserveDate": "2023-12-11T10:50:46.841+01:00",
"wo": {
"id": "DEV17",
"code": "DEV-WO-017-2006"
},
"actor": {
"id": "14",
"code": "DEMO"
},
"description": "Test création de réservation 1"
},
{
"id": "1917e380cdc-1ed",
"item": {
"id": "FILTRE-AIR-D20",
"code": "FILTRE-AIR-D20"
},
"quantity": 2.0,
"reserveDate": "2023-12-11T10:50:46.841+01:00",
"wo": {
"id": "DEV17",
"code": "DEV-WO-017-2006"
},
"actor": {
"id": "14",
"code": "DEMO"
},
"description": "Test création de réservation 2"
},
{
"id": "1917e380cdc-1ef",
"item": {
"id": "ITEM1",
"code": "ITEM1"
},
"warehouse": {
"id": "WAREHOUSE1",
"code": "MAG1"
},
"quantity": 3.0,
"reserveDate": "2023-12-11T10:50:46.841+01:00",
"wo": {
"id": "DEV17",
"code": "DEV-WO-017-2006"
},
"actor": {
"id": "14",
"code": "DEMO"
},
"description": "Test création de réservation 3"
}
]
}
12.3. Mettre à jour une réservation
L’API /reserves/v1/update/<reserve-id> permet de mettre à jour une réservation.
curl -X POST -H "X-CS-Access-Token: votre_access_token" -H "Content-Type: application/vnd.api+json" \ -d '{ "data": { "quantity": 1, "reserveDate" : "2024-01-05T09:12:55.835+01:00", "description" : "Réservation mise à jour par DEMO vers MAG1", "item": { "code": "FILTRE-AIR-D20" } , "wo": { "code": "DEV-WO-017-2006" }, "actor": { "code": "DEMO" }, "warehouse": { "code": "MAG1" } } } ‘ \ https://carlsource.server.com/gmaoCS02/api/reserves/v1/update/1917e380cdc-ac
HTTP/1.1 200 OK
{
"data": {
"id": "1917e380cdc-ac",
"item": {
"id": "FILTRE-AIR-D20",
"code": "FILTRE-AIR-D20"
},
"warehouse": {
"id": "WAREHOUSE1",
"code": "MAG1"
},
"quantity": 1.0,
"reserveDate": "2024-01-05T09:12:55.835+01:00",
"wo": {
"id": "DEV17",
"code": "DEV-WO-017-2006"
},
"actor": {
"id": "14",
"code": "DEMO"
},
"description": "Réservation mise à jour par DEMO vers MAG1"
}
}
12.4. Mettre à jour une liste de réservations
L’API /reserves/v1/update-all permet de mettre à jour une liste de réservations.
|
|
En plus des attributs obligatoires, il est nécessaire de fournir l’id de la réservation que l’on souhaite mettre à jour dans la liste. |
{
"data": [
{
"id": "1917e380cdc-1eb",
"item": {
"code": "ITEM1"
},
"quantity": 2.0,
"reserveDate": "2023-12-11T10:50:46.841+01:00",
"wo": {
"code": "DEV-WO-017-2006"
},
"actor": {
"code": "DEMO"
},
"description": "Mise à jour de la réservation 1"
},
{
"id": "1917e380cdc-1ed",
"item": {
"code": "FILTRE-AIR-D20"
},
"quantity": 2.0,
"reserveDate": "2023-12-11T10:50:46.841+01:00",
"wo": {
"code": "DEV-WO-018-2006"
},
"actor": {
"code": "DEMO"
},
"description": "Mise à jour de la réservation 2"
},
{
"id": "1917e380cdc-1ef",
"item": {
"code": "ITEM1"
},
"warehouse": {
"code": "MAG1"
},
"quantity": 2.0,
"reserveDate": "2023-12-11T10:50:46.841+01:00",
"wo": {
"code": "DEV-WO-017-2006"
},
"actor": {
"code": "DEMO"
},
"description": "Mise à jour de la réservation 3"
}
]
}
{
"data": [
{
"id": "1917e380cdc-1eb",
"item": {
"id": "FILTRE-AIR-D20",
"code": "FILTRE-AIR-D20"
},
"quantity": 2.0,
"reserveDate": "2023-12-11T10:50:46.841+01:00",
"wo": {
"id": "DEV17",
"code": "DEV-WO-017-2006"
},
"actor": {
"id": "14",
"code": "DEMO"
},
"description": "Mise à jour de la réservation 1"
},
{
"id": "1917e380cdc-1ed",
"item": {
"id": "FILTRE-AIR-D20",
"code": "FILTRE-AIR-D20"
},
"quantity": 2.0,
"reserveDate": "2023-12-11T10:50:46.841+01:00",
"wo": {
"id": "DEV18",
"code": "DEV-WO-018-2006"
},
"actor": {
"id": "14",
"code": "DEMO"
},
"description": "Mise à jour de la réservation 2"
},
{
"id": "1917e380cdc-1ef",
"item": {
"id": "ITEM1",
"code": "ITEM1"
},
"warehouse": {
"id": "WAREHOUSE1",
"code": "MAG1"
},
"quantity": 2.0,
"reserveDate": "2023-12-11T10:50:46.841+01:00",
"wo": {
"id": "DEV17",
"code": "DEV-WO-017-2006"
},
"actor": {
"id": "14",
"code": "DEMO"
},
"description": "Mise à jour de la réservation 3"
}
]
}
12.5. Retrouver les réservations liées à une entité (article, intervention ou magasin)
L’API /reserves/v1/<entityType>/<entityId> permet de rechercher des réservations liées aux entités wo, item et warehouse.
https://carlsource.server.com/gmaoCS02/api/reserves/v1/wo/DEV18
{
"data": [
{
"id": "1917e380cdc-1ed",
"item": {
"id": "FILTRE-AIR-D20",
"code": "FILTRE-AIR-D20"
},
"quantity": 2.0,
"reserveDate": "2023-12-11T10:50:46.841+01:00",
"wo": {
"id": "DEV18",
"code": "DEV-WO-018-2006"
},
"actor": {
"id": "14",
"code": "DEMO"
},
"description": "Mise à jour de la réservation 2"
}
]
}
| Entité de recherche | Description |
|---|---|
|
Article lié à la réservation |
|
Intervention liée à la réservation |
|
Magasin lié à la réservation |
13. Scénario de mise à jour des états des factures : l’API /energy-meter-invoices
13.1. Droits d’utilisation de l’API
L’utilisation de cette API nécessite que l’utilisateur avec lequel est invoquée l’API dispose des droits de profil requis.
L’API est contrôlée par le droit de profil : Equipements / Suivi facturation énergie.
13.2. Mise à jour des états des factures
L’API /energy-meter-invoices/v1/update-status permet d’envoyer, dans une requête POST au format JSON (Media-Type: application/json), une liste de factures à mettre à jour.
curl -X POST -H "X-CS-Access-Token: votre_access_token" -H "Content-Type: application/vnd.api+json" \ -d ' { "data":[ { "invoiceNumber" : "110", "status" : "PAID", "energyMeter" : { "id" : "nrj1" OU "code" : "ENERGY_01" } }, { "invoiceNumber" : "111", "status" : "TOPAY", "energyMeter" : { "id" : "nrj1" OU "code" : "ENERGY_01" } } ] }' \ https://carlsource.server.com/gmaoCS02/api/energy-meter-invoice/v1/update-status
Les champs correspondants pour la description de la facture sont les suivants :
| Champs | Type (Format ou Longueur) | Description | Obligatoire / Facultatif |
|---|---|---|---|
|
Alphanumérique |
Numéro de la facture |
Obligatoire |
|
Alphanumérique |
Etat |
Obligatoire |
Les champs correspondants pour la description d’un point énergie sont les suivants :
| Champs | Type (Format ou Longueur) | Description |
|---|---|---|
|
Alphanumérique |
Code du point énergie (ne pas renseigner si |
|
Alphanumérique |
Identifiant du point énergie (ne pas renseigner si |
L’utilisation de code ou id est obligatoire pour que la facture puisse avoir un point énergie de référence, mais les deux attributs ne peuvent pas être renseignés simultanément.
HTTP/1.1 201 Created
{
"data":[
{
"invoiceNumber" : "110",
"status" : "PAID",
"energyMeter" : {
"id" : "nrj1"
}
},
{
"invoiceNumber" : "111",
"status" : "TOPAY",
"energyMeter" : {
"id" : "nrj1"
}
}
]
}
14. Scénario d’utilisation des liens dans l’arborescence : l’API /link-equipments
L’API /link-equipments permet d’ajouter, de déplacer, de modifier ou de clôturer un ou plusieurs liens dans l’arborescence.
14.1. Droits d’utilisation de l’API
L’utilisation de cette API nécessite que l’utilisateur avec lequel est invoquée l’API dispose des droits de profil requis.
L’API est contrôlée par le droit de profil : Equipements / Arborescence du parc équipements.
-
Lorsque le lien existe déjà, si la date de fin est renseignée : droit "Supprimer le lien courant".
-
Lorsque le lien existe entre les deux équipements : droit "Modifier les informations sur liens".
-
Lorsque le lien existe pour cette jonction : droit "Modifier les informations sur liens".
14.2. Ajouter, modifier, déplacer ou clôturer un lien sur l’arborescence
|
|
Toutes ces différentes actions sur les liens sont régies par deux appels uniquement :
|
C’est l’utilisation des attributs qui composent le corps de cette API qui permet de définir s’il s’agit de la création, du déplacement, de la modification ou de la clôture du lien.
Exemples d’utilisation :
-
Création : Si aucun lien n’existe, l’ajout d’un père, d’un fils, et d’une date de début crée le lien dans l’arborescence.
-
Déplacement : L’appel à la même API que précédemment en modifiant le père ou le fils déplace le lien dans l’arborescence.
-
Clôture : L’ajout d’une date de fin clôture le lien dans l’arborescence.
14.2.1. Gérer un seul lien
L’API /link-equipments/v1/add permet d’envoyer, dans une requête POST au format JSON (Media-Type: application/json), un lien sur l’arborescence.
curl -X POST -H "X-CS-Access-Token: votre_access_token" -H "Content-Type: application/vnd.api+json" \ -d '{ "data": { "linkBegin":"2024-09-11T12:00:00", "description":"Lien API Rest", "ordering":1, "junction": { "id":"LOCATIONMATERIAL" }, "parent": { "id":"ALLEMAGNE" }, "child": { "code":"CEAU" } } }' \ https://carlsource.server.com/gmaoCS02/api/link-equipments/v1/add
Les champs correspondants pour la description du lien sur l’arborescence sont les suivants :
| Champs | Type (Format ou Longueur) | Description | Obligatoire / Facultatif |
|---|---|---|---|
|
Date |
Date de début de validité du lien |
Obligatoire, uniquement dans le cas des liens datés. |
|
Date |
Date de fin de validité du lien |
Facultatif |
|
Numérique |
Ordre des nœuds d’une branche d’arborescence |
Facultatif |
|
Alphanumérique |
Description du lien |
Facultatif |
-
linkBegin: ce champ est requis uniquement si la structure enfant est de type "liens datés".
Par exemple, un lien entre un point de structure et un matériel nécessite une date, tandis qu’un lien entre deux points de structure n’en requiert aucune.
Un lien nécessite l’utilisation des entités de référence suivantes :
| Champs | Description | Obligatoire / Facultatif |
|---|---|---|
|
Description des liens entre structures |
Obligatoire |
|
Equipement parent du lien |
Facultatif |
|
Equipement enfant du lien |
Obligatoire |
Les champs correspondants pour la description des entités de référence du lien sont les suivants :
| Champs | Type (Format ou Longueur) | Description |
|---|---|---|
|
Alphanumérique (20) |
Code de l’entité de référence |
|
Alphanumérique (33) |
Id de l’entité de référence |
|
|
L’utilisation de |
HTTP/1.1 201 Created
{
"data": [
{
"id": "19368f7c674-3",
"junction": {
"id": "LOCATIONMATERIAL"
},
"parent": {
"id": "ALLEMAGNE",
"code": "ALLEMAGNE"
},
"child": {
"id": "9",
"code": "CEAU"
},
"linkBegin": "2024-09-11T12:00:00.000",
"linkEnd": "2200-12-31T01:00:00.000",
"description": "lien API Rest",
"ordering": 1
}
]
}
14.2.2. Gérer une liste de liens
L’API /link-equipments/v1/add-all permet d’envoyer, dans une requête POST au format JSON (Media-Type: application/json), une liste de liens sur l’arborescence.
|
|
Cette liste permet de gérer des liens sur différents équipements. |
curl -X POST -H "X-CS-Access-Token: votre_access_token" -H "Content-Type: application/vnd.api+json" \ -d '{ "data": [ { "junction": { "id":"LOCATIONMATERIAL" }, "parent": { "id":"ALLEMAGNE" }, "child": { "code":"BALL" }, "linkBegin":"2024-09-11T12:00:00", "description":"Création du lien", "ordering":1 }, { "junction": { "id":"LOCATIONMATERIAL" }, "parent": { "id":"FRANCE" }, "child": { "code":"BALL" }, "linkBegin":"2024-09-11T13:00:00", "description":"Déplacement du lien", "ordering":1 }, { "junction": { "id":"LOCATIONMATERIAL" }, "parent": { "id":"FRANCE" }, "child": { "code":"BALL" }, "linkBegin":"2024-09-11T14:00:00", "description":"Modification de la date du lien existant", "ordering":1 }, { "junction": { "id":"LOCATIONMATERIAL" }, "parent": { "id":"FRANCE" }, "child": { "code":"BALL" }, "linkBegin":"2024-09-11T15:00:00", "linkEnd":"2024-09-12T15:00:00", "description":"Clôture du lien", "ordering":1 } ] }' \ https://carlsource.server.com/gmaoCS02/api/link-equipments/v1/add-all
L’exemple ci-dessus illustre les cas de figure suivants :
-
Déplacement du lien du père "ALLEMAGNE" vers le père "FRANCE" (cf. "Déplacement du lien" dans le code)
|
|
Le déplacement d’un lien entraîne la clôture du lien existant et la création du nouveau lien dans l’arborescence - cf. "Réponse obtenue" plus bas. |
-
Modification de la date du lien en cours (cf. les deux premières occurrences d’utilisation de l’attribut
linkBegin) -
Clôture du lien en cours (cf. occurrence d’utilisation de l’attribut
linkEnd)
|
|
Les champs à renseigner sont identiques à ceux de l’API /link-equipments/v1/add. |
HTTP/1.1 201 Created
{
"data": [
{
"id": "19368f7c674-18",
"junction": {
"id": "LOCATIONMATERIAL"
},
"parent": {
"id": "ALLEMAGNE",
"code": "ALLEMAGNE"
},
"child": {
"id": "2",
"code": "BALL"
},
"linkBegin": "2024-09-11T12:00:00.000",
"linkEnd": "2200-12-31T01:00:00.000",
"description": "Création du lien",
"ordering": 1
},
{
"id": "19368f7c674-18",
"junction": {
"id": "LOCATIONMATERIAL"
},
"parent": {
"id": "ALLEMAGNE",
"code": "ALLEMAGNE"
},
"child": {
"id": "2",
"code": "BALL"
},
"linkBegin": "2024-09-11T12:00:00.000",
"linkEnd": "2024-09-11T12:59:59.999",
"description": "Création du lien",
"ordering": 1
},
{
"id": "19368f7c674-19",
"junction": {
"id": "LOCATIONMATERIAL"
},
"parent": {
"id": "FRANCE",
"code": "FRANCE"
},
"child": {
"id": "2",
"code": "BALL"
},
"linkBegin": "2024-09-11T13:00:00.000",
"linkEnd": "2200-12-31T01:00:00.000",
"description": "Déplacement du lien",
"ordering": 1
},
{
"id": "19368f7c674-19",
"junction": {
"id": "LOCATIONMATERIAL"
},
"parent": {
"id": "FRANCE",
"code": "FRANCE"
},
"child": {
"id": "2",
"code": "BALL"
},
"linkBegin": "2024-09-11T14:00:00.000",
"linkEnd": "2200-12-31T01:00:00.000",
"description": "Modification de la date du lien existant",
"ordering": 1
},
{
"id": "19368f7c674-19",
"junction": {
"id": "LOCATIONMATERIAL"
},
"parent": {
"id": "FRANCE",
"code": "FRANCE"
},
"child": {
"id": "2",
"code": "BALL"
},
"linkBegin": "2024-09-11T15:00:00.000",
"linkEnd": "2024-09-12T15:00:00.000",
"description": "Clôture du lien",
"ordering": 1
}
]
}
Analyse de la réponse obtenue :
-
Création : La réponse n°1 correspond à la création du lien.
-
Déplacement :
-
La réponse n°2 correspond à la clôture de ce lien (même
id) car le déplacement d’un lien clôture le lien actuel pour en créer un nouveau. -
La réponse n°3 correspond à la création du nouveau lien suite à la demande de déplacement.
-
-
Modification : La réponse n°4 correspond à la modification du lien en cours.
-
Clôture : La réponse n°5 correspond à la clôture du lien dans l’arborescence.
|
|
Si une erreur survient lors du traitement de l’API, aucune modification n’est prise en compte. |
14.2.3. Lire des liens équipement
L’API /entities/v1/linkequipment permet de retourner, dans une requête GET, les liens équipement.
Comme décrit dans le chapitre Lister, filtrer et sélectionner, il est possible d’affiner cette recherche en filtrant, en triant et sélectionnant les attributs à afficher.
https://carlsource.server.com/gmaoCS02/api/entities/v1/linkequipment?filter[child.code]=BALL&sort=linkBegin
15. Scénario de manipulation des inventaires : l’API /inventories
L’API /inventories permet de créer un ou plusieurs inventaires.
15.1. Droits d’utilisation de l’API
L’utilisation de l’API nécessite que l’utilisateur dispose des droits de profils requis. L’API est contrôlée par le droit de création d’inventaire : Stock/Inventaire.
15.2. Créer un ou plusieurs inventaires
15.2.1. Créer un inventaire
L’API /inventories/v1/add permet d’envoyer dans une requête POST au format JSON (Media-Type: application/json), un mouvement d’inventaire.
curl -X POST -H "X-CS-Access-Token: votre_access_token" -H "Content-Type: application/vnd.api+json" \
-d '{
"data": {
"movementQuantity": 11.0,
"description": "Test de création d’inventaire avec l’API REST",
"item": {
"code": "ITEM1"
},
"location": {
"code": "A1C10"
},
"actor": {
"code": "DEMO"
},
"warehouse": {
"code": "MAG1"}
}
}'https://carlsource.server.com/gmaoCS02/api/inventories/v1/add
Les champs correspondants pour la description d’un inventaire sont les suivants :
| Champs | Type (Format ou Longueur) | Description | Obligatoire / Facultatif |
|---|---|---|---|
|
Alphanumérique |
Code ou id de l’article |
Obligatoire |
|
Numérique |
Quantité inventoriée |
Obligatoire |
|
Alphanumérique |
Code ou id du magasin de la réservation |
Obligatoire. Peut-être facultatif si l’article a déjà été inventorié dans un seul magasin. |
|
Alphanumérique |
Intervention porteuse de la réservation |
Facultatif |
|
Date Date de l’inventaire |
Facultatif. Date du jour par défaut. |
|
Alphanumérique |
Code ou id de l’acteur |
Facultatif. Acteur connecté par défaut. |
|
Alphanumérique |
Description de l’inventaire |
Facultatif |
|
Alphanumérique |
Code ou id du matériel |
Obligatoire pour l’inventaire d’un article sérialisé |
|
Alphanumérique |
Numéro de lot associé |
Facultatif |
|
Alphanumérique |
Code ou id du type de mouvement |
Facultatif. Mouvement de type Inventaire par défaut. |
|
HTTP/1.1 201 Created
{
"data":{
"id":"19759fe5d1c-1",
"actor":{
"id":"14",
"code":"DEMO"
},
"item":{
"id":"ITEM1",
"code":"ITEM1"
},
"movementQuantity":11.0,
"movementDate":"2025-06-10T15:21:58.311+02:00",
"location":{
"id":"LOCATION1",
"code":"A1C10"
},
"warehouse":{
"id":"WAREHOUSE1",
"code":"MAG1"
},
"description":"Test de création d’inventaire avec l’API REST",
"movementType":{
"id":"INVENTORY",
"code":"INVENTAIRE"}
}
}
15.2.2. Créer une liste d’inventaire
L’ API/inventories/v1/add-all permet d’envoyer dans une requête POST au format JSON (Media-Type :application/json), une liste d’inventaire.
|
|
Si l’API rencontre une erreur fonctionnelle, comme une donnée obligatoire non renseignée c’est toute la liste qui est rejetée. |
curl -X POST -H "X-CS-Access-Token: votre_access_token" -H "Content-Type: application/vnd.api+json" \
-d '{
"data": [
{
"movementQuantity": 4.0,
"description": "Test de création de plusieurs inventaires avec l’API REST. Inventaire 1",
"item": {
"code": "ITEM1"
},
"location": {
"code": "A1C10"
},
"actor": {
"code": "DEMO"
},
"warehouse": {
"code": "MAG1"
}
},
{
"movementQuantity": 3.0,
"description": "Test de création de plusieurs inventaires avec l’API REST. Inventaire 2",
"item": {
"code": "ITEM1"
},
"location": {
"code": "A2C03"
},
"actor": {
"code": "DEMO"
},
"warehouse": {
"code": "MAG2"
}
}
]
}’\https://carlsource.server.com/gmaoCS02/api/inventories/v1/add-all
|
|
Les champs à renseigner sont identiques à l’API inventories/v1/add. |
HTTP/1.1 201 Created
{
"data": [
{
"id": "19759fe5d1c-57",
"actor": {
"id": "14",
"code": "DEMO"
},
"item": {
"id": "ITEM1",
"code": "ITEM1"
},
"movementQuantity": 4.0,
"movementDate": "2025-06-10T15:42:02.225+02:00",
"location": {
"id": "LOCATION1",
"code": "A1C10"
},
"warehouse": {
"id": "WAREHOUSE1",
"code": "MAG1"
},
"description": "Test de création de plusieurs inventaires avec l’API REST. Inventaire 1",
"movementType": {
"id": "INVENTORY",
"code": "INVENTAIRE"
}
},
{
"id": "19759fe5d1c-5a",
"actor": {
"id": "14",
"code": "DEMO"
},
"item": {
"id": "ITEM1",
"code": "ITEM1"
},
"movementQuantity": 3.0,
"movementDate": "2025-06-10T15:42:02.292+02:00",
"location": {
"id": "LOCATION4",
"code": "A2C03"
},
"warehouse": {
"id": "WAREHOUSE2",
"code": "MAG2"
},
"description": "Test de création de plusieurs inventaires avec l’API REST. Inventaire 2",
"movementType": {
"id": "INVENTORY",
"code": "INVENTAIRE"
}
}
]
}
16. Import de factures externes : l’API /invoices
16.1. Présentation générale
Cette API REST permet d’importer des factures externes dans CARL Source, conformément à la norme EN16931 et aux besoins spécifiques du SI. Elle s’adresse aux clients souhaitant automatiser l’intégration de leurs factures électroniques (e-factures) dans CARL Source.
16.1.1. Import des données de facturation
-
Endpoint : /api/invoices/v1/add
-
Méthode HTTP :
POST -
Type de contenu attendu (
Content-type) :application/json -
Authentification : Requise
16.1.2. Import des données de facturation et du fichier représentant la facture
-
Endpoint : /api/invoices/v1/add
-
Méthode HTTP :
POST -
Type de contenu attendu (
Content-type) :multipart/form-data -
Authentification : Requise
16.1.3. Droits d’utilisation
Les droits d’accès aux APIs sont conditionnés par les paramètres de module suivants (Menu Système, fonctionnalité Paramètres des modules) :
-
Achats / INVOICE_IMPORT_ENABLED | Activer l’import de e-factures : doit être coché
-
Achats / INVOICE_IMPORT_FORMAT | Format de l’import de e-factures : doit valoir "CARL Source"
Ainsi que par le droit de profil suivant :
-
Achats / Factures / Autoriser la création de factures par API d’import d’e-factures : doit être coché
16.2. Fonctionnement de l’API
16.2.1. Étapes de traitement
-
Validation des données :
-
Les champs obligatoires sont renseignés (voir ci-dessous).
-
Le type de facture est contrôlé (certains types comme
384/CORRECTEDou389/SELF_BILLEDne sont pas supportés pour l’instant). -
Les règles métier garantissant la cohérence des données fournies (commande, devise, etc.) sont contrôlées.
-
-
Réalisation de l’import :
-
Si la facture n’existe pas, elle est créée.
-
Si elle existe et est toujours à l’état "En préparation", elle est mise à jour.
-
Si la commande associée n’est pas trouvée, le mode "pré-facture" doit être autorisé afin que la facture soit tout de même créée en tant que "pré-facture" (brouillon).
-
Si la facture de référence n’est pas trouvée, le mode "pré-facture" doit être autorisé afin que l’avoir soit tout de même créée en tant que "pré-avoir" (brouillon).
-
16.3. Structure des données attendues
16.3.1. Exemple de payload JSON
{
"data": {
"invoiceNumber": "FAC-2026-001",
"invoiceIssueDate": "2026-04-17T10:00:00+02:00",
"invoiceTypeCode": "380",
"invoiceStatus": "EN_ATTENTE",
"buyerReference": "ACH-12345",
"purchaseOrderReference": "PO-2026-001",
"deliveryCode": "BL-2026-001",
"precedingInvoiceReference": null,
"sellerReference": "VEND-98765",
"supplierReference": "FOUR-54321",
"invoiceReference": "REF-2026-001",
"invoiceCurrencyCode": "EUR",
"invoiceTotalAmountWithVAT": 1200.50,
"invoiceTotalVATAmount": 200.08,
"invoiceTotalAmountWithoutVAT": 1000.42
}
}
16.3.2. Description des champs principaux
| Champ | Obligatoire | Description |
|---|---|---|
invoiceNumber |
Oui (1) |
Numéro unique de la facture externe |
invoiceIssueDate |
Oui |
Date d’émission de la facture (format |
invoiceTypeCode |
Non (2) |
Code type de facture ( |
invoiceStatus |
Oui |
Statut interne de la facture dans le SI appelant |
buyerReference |
Non |
Références sur l’acheteur |
purchaseOrderReference |
Non (3) |
Référence de la commande associée |
deliveryCode |
Non (3) |
Numéro de BL client (obligatoire si mode BL activé) |
precedingInvoiceReference |
Non |
Référence de facture d’origine (obligatoire pour 381) |
sellerReference |
Non |
Référence du vendeur |
supplierReference |
Non |
Référence du fournisseur |
invoiceReference |
Non |
Référence de la facture d’origine pour les avoirs |
invoiceCurrencyCode |
Oui |
Code de la devise (format |
invoiceTotalAmountWithVAT |
Oui |
Montant total TTC |
invoiceTotalVATAmount |
Oui |
Montant total TVA |
invoiceTotalAmountWithoutVAT |
Oui |
Montant total HT |
(1) Obligatoire ou non selon le cas métier (pré-facture possible)
(2) Obligatoire pour certaines règles métier (ex : 381 avec precedingInvoiceReference)
(3) Le caractère obligatoire dépend du mode de facturation (commande ou BL - uniquement commande pour l’instant)
16.4. Points d’attention
-
Type de facture :
-
Les factures de type
384(Rectificative) ne sont pas prises en compte. -
Les factures de type
389(Auto-facturation) sont pour l’instant refusées par l’API.
-
-
Pré-facture :
-
Si aucune commande n’est trouvée, le mode "pré-facture" doit être activé côté configuration pour que la facture soit importée. Dans le cas contraire la facture n’est pas importée.
-
16.5. Bonnes pratiques
-
Toujours renseigner les champs obligatoires.
-
Vérifier la configuration du module Achat et du profil de l’utilisateur invoquant l’API côté CARL Source.
-
Utiliser les bons codes de types de facture selon la norme
EN16931. Si le type n’est pas renseigné, le traitement utilise le type380- facture commerciale - par défaut. -
En cas d’erreur, consulter le message retourné dans le corps de la réponse http, mais aussi côté serveur dans les logs applicatifs de CARL Source.
-
Lors de la phase de mise en place, il peut être pratique d’utiliser une authentification BASIC pour mener les tests.
Nous encourageons toutefois fortement l’utilisation de tokens OAuth2 pour un passage en exploitation.
16.6. Exemple d’appel avec curl
Voici un exemple d’appel à l’API d’import de factures externes en utilisant curl.
À noter : les environnements CARL Source en SaaS sont protégés et - pour des raisons de sécurité - rejettent les requêtes ne spécifiant aucun user-agent ou spécifiant un user-agent contenant "curl".
curl -X POST \ https://carlsource.server.com/gmaoCS02/api/invoices/v1/add \ -H "Content-Type: application/json" \ -H "Authorization: Bearer votre_access_token" \ --user-agent "Mozilla/5.0" \ --data-binary @- <<'EOF' { "data": { "invoiceNumber": "FAC-2026-001", "invoiceIssueDate": "2026-04-17T10:00:00+02:00", "invoiceTypeCode": "380", "invoiceStatus": "EN_ATTENTE", "buyerReference": "ACH-12345", "purchaseOrderReference": "PO-2026-001", "deliveryCode": "BL-2026-001", "precedingInvoiceReference": null, "sellerReference": "VEND-98765", "supplierReference": "FOUR-54321", "invoiceReference": "REF-2026-001", "invoiceCurrencyCode": "EUR", "invoiceTotalAmountWithVAT": 1200.50, "invoiceTotalVATAmount": 200.08, "invoiceTotalAmountWithoutVAT": 1000.42 } } EOF
-
Remplacez la valeur en rouge
carlsource.server.com/gmaoCS02par l’URL et le contexte de votre instance CARL Source. -
Remplacez
votre_access_tokenpar un token d’authentification valide. -
Note : pour simplifier les tests, il est possible de remplacer
-H "Authorization: Bearer votre_access_token" \par-u identifiant:mot_de_passeen utilisant un couple login / mot de passe valide.
16.6.1. Exemple avec upload de fichier PDF (multipart/form-data)
Voici un exemple d’appel à l’API d’import de factures externes avec un fichier PDF joint, en utilisant curl :
DTO=$(cat <<'EOF'
{
"data": {
"invoiceNumber": "FAC-2026-001",
"invoiceIssueDate": "2026-04-17T10:00:00+02:00",
"invoiceTypeCode": "380",
"invoiceStatus": "EN_ATTENTE",
"buyerReference": "ACH-12345",
"purchaseOrderReference": "PO-2026-001",
"deliveryCode": "BL-2026-001",
"precedingInvoiceReference": null,
"sellerReference": "VEND-98765",
"supplierReference": "FOUR-54321",
"invoiceReference": "REF-2026-001",
"invoiceCurrencyCode": "EUR",
"invoiceTotalAmountWithVAT": 1200.50,
"invoiceTotalVATAmount": 200.08,
"invoiceTotalAmountWithoutVAT": 1000.42
}
}
EOF
)
curl -X POST \
https://carlsource.server.com/gmaoCS02/api/invoices/v1/add \
-H "Authorization: Bearer votre_access_token" \
--user-agent "Mozilla/5.0" \
-F "dto=$DTO;type=application/json" \
-F 'pdf=@/chemin/vers/facture.pdf;type=application/pdf'
-
La partie
dtodoit être envoyée avec le type de contenuapplication/json. -
La partie
pdfcorrespond au fichier PDF à joindre (paramètrerequired = false: l’envoi du PDF est optionnel). -
Remplacez la valeur en rouge
carlsource.server.com/gmaoCS02par l’URL et le contexte de votre instance CARL Source. -
Remplacez
votre_access_tokenpar un token d’authentification valide. -
Remplacez
/chemin/vers/facture.pdfpar le chemin local vers votre fichier PDF.
17. Echange de données
17.1. Droits d’utilisation
Les droits d’accès aux APIs sont conditionnés par les droits de profil suivants :
-
Echange de données / Interface d’échange / Import : pour les APIs commençant par "api/exchange/v1/import/"
-
Echange de données / Interface d’échange / Export : pour les APIs commençant par "api/exchange/v1/export/"
-
Echange de données / Historique des échanges / Lecture : pour l’API "api/exchange/v1/executions/"
17.2. Export synchrone
Cette API permet d’effectuer un export de données via une interface en mode synchrone. Son résultat correspond au contenu du fichier généré.
-
Signature : api/exchange/v1/export/synchronous/interface/<code de l’interface>
-
Méthode HTTP : POST
-
Corps de message (optionnel) au format JSON avec les propriétés suivantes :
| Propriété | Obligatoire | Définition |
|---|---|---|
|
Non |
Code du filtre personnalisé |
|
Non |
Objet JSON contenant la liste des codes d’attributs sur lesquels appliquer un filtrage, ainsi que l’expression du filtre. |
Exemple de corps de message :
{
"customFilterCode": "WO_02",
"evalParameters": {
"code": "CTRL*"
}
}
Exemple d’utilisation de l’API via cURL :
curl -X POST https://carlsource.server.com/gmaoCS02/api/exchange/v1/export/synchronous/interface/USER_OUT \ -u identifiant:mot_de_passe \ -o user_out.xml
curl -X POST https://carlsource.server.com/gmaoCS02/api/exchange/v1/export/synchronous/interface/USER_OUT \ -u identifiant:mot_de_passe \ -H 'Content-Type: application/json' \ -d '{"evalParameters": {"code": "*MO"}}' \ -o user_out_filtered.xml
17.3. Export asynchrone
Cette API permet d’effectuer un export de données via une interface et/ou un système externe en mode asynchrone.
-
Signatures :
-
Export via une interface : api/exchange/v1/export/asynchronous/interface/<code de l’interface>
-
Export via un système externe : api/exchange/v1/export/asynchronous/external-system/<code du système externe>
-
Export via une interface dans un système externe : api/exchange/v1/export/asynchronous/external-system/<code du système externe>/interface/<code de l’interface>
-
-
Méthode HTTP : POST
-
Corps de message (optionnel) au format JSON : voir le corps de message du chapitre Export synchrone
-
Réponse au format JSON encapsulée dans la propriété
data:
| Propriété | Obligatoire | Définition |
|---|---|---|
|
Oui |
Identification de l’historique d’échange (voir Suivi des échanges asynchrones) |
Exemple d’utilisation de l’API via cURL :
curl -s -X POST https://carlsource.server.com/gmaoCS02/api/exchange/v1/export/asynchronous/interface/USER_OUT \ -H "X-CS-Access-Token: votre_access_token"
{"data":{"messageId":"0217d44f-c142-46a8-ae17-dd07b04289cf"}}
curl -s -X POST https://carlsource.server.com/gmaoCS02/api/exchange/v1/export/asynchronous/external-system/EXT_SYST_XML/interface/USER_OUT \ -u identifiant:mot_de_passe \ -H 'Content-Type: application/json' \ -d '{"evalParameters": {"code": "*MO"}}'
{"data":{"messageId":"aa72e3dd-00eb-4559-b183-81afead5056e"}}
17.4. Import synchrone
Cette API permet d’effectuer un import de données via une interface et/ou un système externe en mode synchrone.
-
Signatures :
-
Import via une interface : api/exchange/v1/import/synchronous/interface/<code de l’interface>
-
Import via un système externe : api/exchange/v1/import/synchronous/external-system/<code du système externe>
-
Import via une interface dans un système externe : api/exchange/v1/import/synchronous/external-system/<code du système externe>/interface/<code de l’interface>
-
-
Méthode HTTP : POST
-
Corps de message (optionnel dans le cas d’une utilisation d’un système externe) : contenu de l’échange à importer
-
Réponse au format JSON encapsulée dans la propriété
data:
| Propriété | Obligatoire | Définition |
|---|---|---|
|
Oui |
Valeur |
|
Oui |
Liste des erreurs remontées durant l’import |
Exemples de réponses :
{
"data": {
"status": true,
"errors": []
}
}
{
"data": {
"status": false,
"errors": [
"Erreur lors de la validation (costCenter):org.postgresql.util.PSQLException: ERREUR: valeur trop longue pour le type character varying(60) Sur l’élément principal numéro 2 de tag 'costCenter' [srcPos='2' code='SUIVI-PLOMB']\n"
]
}
}
Exemple d’utilisation de l’API via cURL :
curl -s -X POST https://carlsource.server.com/gmaoCS02/api/exchange/v1/import/synchronous/interface/COSTCENTER_IN_CSV \ -u identifiant:mot_de_passe \ -d @costcenter_in.csv
{"data":{"status":true,"errors":[]}}
curl -s -X POST https://carlsource.server.com/gmaoCS02/api/exchange/v1/import/synchronous/external-system/EXT_SYS_XML/interface/COSTCENTER_IN_CSV \ -H "X-CS-Access-Token: votre_access_token" \
{"data":{"status":true,"errors":[]}}
17.5. Import asynchrone
Cette API permet d’effectuer un import de données via une interface et/ou un système externe en mode asynchrone.
-
Signatures :
-
Import via une interface : api/exchange/v1/import/asynchronous/interface/<code de l’interface>
-
Import via un système externe : api/exchange/v1/import/asynchronous/external-system/<code du système externe>
-
Import via une interface dans un système externe : api/exchange/v1/export/asynchronous/external-system/<code du système externe>/interface/<code de l’interface>
-
-
Méthode HTTP : POST
-
Corps de message (optionnel dans le cas d’une utilisation d’un système externe) : contenu de l’échange à importer
-
Réponse au format JSON encapsulée dans la propriété
data:
| Propriété | Obligatoire | Définition |
|---|---|---|
|
Oui |
Identification de l’historique d’échange (voir Suivi des échanges asynchrones) |
Exemple d’utilisation de l’API via cURL :
curl -s -X POST https://carlsource.server.com/gmaoCS02/api/exchange/v1/import/asynchronous/interface/COSTCENTER_IN_CSV \ -H "X-CS-Access-Token: votre_access_token" \ -d @costcenter_in.csv
{"data":{"messageId":"f2a666e0-70b4-4d26-bf4d-9d950c3cb27b"}}
curl -s -X POST https://carlsource.server.com/gmaoCS02/api/exchange/v1/import/asynchronous/external-system/EXT_SYS_XML/interface/COSTCENTER_IN_CSV \ -H "X-CS-Access-Token: votre_access_token" \
{"data":{"messageId":"ed122f53-85b0-4303-9f27-2a9b0741ea17"}}
17.6. Suivi des échanges asynchrones
Cette API permet de connaître l’état d’un échange asynchrone.
-
Signature : api/exchange/v1/executions/<messageId>
-
Méthode HTTP : GET
-
Réponse au format JSON encapsulée dans la propriété
data:
| Propriété | Définition |
|---|---|
|
Identifiant correspondant à l’échange déclenché (contenu dans la réponse des APIs asynchrones) |
|
Code du résultat de l’exécution (voir liste de valeurs 'EXCHANGESTATUS') |
|
Etape de l’échange |
|
Nombre d’éléments traités |
|
Code d’erreur pour les échanges de données (voir liste de valeurs 'EXCHANGEERROR') |
|
Nombre d’éléments rejetés |
|
Identifiant de l’historique d’échange |
|
Objet JSON contenant un lien (propriété |
{
"data": {
"messageId": "ed122f53-85b0-4303-9f27-2a9b0741ea17",
"processStep": "IMPORTATION",
"execStatus": "OK",
"processedElements": 1,
"rejectedElements": 0,
"id": "19324b43129-53a",
"links": {
"self": "https://carlsource.server.com/gmaoCS02/api/entities/v1/interfaceexecution/19324b43129-53a"
}
}
}
Exemple d’utilisation de l’API via cURL :
curl -s -X POST https://carlsource.server.com/gmaoCS02/api/exchange/v1/executions/4ddd58d5-8a24-4541-ba15-facddefcb07b \ -H "X-CS-Access-Token: votre_access_token" \
{
"data":{
"messageId":"4ddd58d5-8a24-4541-ba15-facddefcb07b",
"processStep":"UPLOAD",
"execStatus":"WARNING",
"processedElements":0,
"rejectedElements":0,
"errorCode":"TECH001",
"id":"19324b43129-66a",
"links":{
"self":"https://carlsource.server.com/gmaoCS02/api/entities/v1/interfaceexecution/19324b43129-66a"
}
}
}
18. Conclusion
Vous disposez à présent des informations nécessaires pour prendre en main cette API et interagir avec les objets de CARL Source :
-
s’authentifier,
-
lister, créer, lire, modifier, et supprimer des objets métier,
-
faire évoluer ces objets le long de leur cycle de vie avec les workflow-transitions.
Avis de marques déposées
Nous avons apporté tous nos efforts pour garantir l’exactitude des informations au moment de la publication de ce document.
CARL Source étant en constante évolution, CARL Berger-Levrault ne peut être tenu responsable des éventuels manques ou erreurs de ce document.
Si vous relevez une incohérence ou une erreur, merci de contacter le service support de CARL Berger-Levrault.
Toute reproduction, en tout ou en partie, sous quelque forme que ce soit, est formellement interdite sans l’autorisation préalable de CARL Berger-Levrault.
Toutes les marques et noms de produits mentionnés dans ce document sont les propriétés de leurs détenteurs respectifs telles que répertoriées ci-dessous :
-
Android™ et Google Chrome® sont des marques déposées de Google LLC
-
ArcGIS® est une marque déposée d’Environmental Systems Research Institute.
-
Elasticsearch® est une marque déposée d’Elasticsearch B.V. aux États-Unis et dans d’autres pays.
-
Firefox® est une marque déposée de Mozilla Foundation.
-
Java™ et Oracle® sont des marques déposées d’Oracle Corporation.
-
PostgreSQL® est une marque déposée de The PostgreSQL Community Association of Canada.
-
Safari® est une marque d’Apple Inc., déposée aux États-Unis et dans d’autres pays.
-
Azure®, SQL Server®, Microsoft Edge® et Windows® sont des marques déposées de Microsoft Corporation.
-
Tomcat® est une marque déposée de l’Apache Software Foundation aux États-Unis et dans d’autres pays.
