Demandes dans Codenica API
Pour travailler avec les demandes via Codenica API, commencez par créer une clé API dans les paramètres de Codenica. Si aucune clé n'a encore été créée, ouvrez dans un nouvel onglet Codenica API - introduction. Vous y trouverez les règles communes pour créer une clé, conserver le secret et authentifier les requêtes.
Le nom technique de la collection dans l'API est requesteditems et le type d'un objet individuel est requesteditem. Une demande sert à enregistrer un besoin d'achat, de livraison, de préparation ou d'exécution d'un élément précis. En plus de la description, elle peut contenir une échéance, une quantité, un prix, un coût, une valeur, une taxe, un budget, une priorité et un statut.
Les exemples utilisent le préfixe PUBLIC-API-REQUESTEDITEM-20260906053922. Dans votre intégration, remplacez-le par votre propre identifiant et adaptez les adresses, les UUID et les valeurs de champs aux données de votre base.
Demandes - adresse de l'API et choix de l'installation
Toutes les routes relatives aux demandes commencent par :
{BASE_URL}/api/v1/requesteditemsBASE_URL désigne l'adresse du serveur Codenica sans le suffixe /api/v1. Dans la version Cloud, utilisez le domaine public attribué à l'entreprise concernée :
export BASE_URL="https://votre-entreprise.codenica.com"Dans une installation On-Premise par défaut, l'adresse enregistrée localement par Codenica Discovery est :
export BASE_URL="http://codenica.local:5150"Si l'administrateur a publié l'installation sous un domaine d'entreprise, derrière un proxy inverse, avec HTTPS ou sur un autre port, utilisez l'adresse exacte fournie pour cette installation :
export BASE_URL="https://api.votre-entreprise.example"N'utilisez pas localhost si l'application d'intégration fonctionne sur un autre ordinateur que l'API. La base de données appropriée est sélectionnée en fonction de l'adresse à laquelle l'intégration se connecte. Ne transmettez pas tenantId dans le body, la chaîne de requête ou un en-tête supplémentaire.
Demandes - périmètres de la clé API
La clé API utilisée pour travailler avec les demandes ne devrait contenir que les périmètres nécessaires à l'intégration concernée. L'ensemble complet des périmètres du module est le suivant :
requesteditems:read
requesteditems:write
requesteditems:delete
requesteditems:schema
requesteditems:stats
requesteditems:relationships:read
requesteditems:relationships:write
requesteditems:users:read
requesteditems:files:read
requesteditems:files:write
requesteditems:technical:read
requesteditems:technical:write
requesteditems:pin:writePour lire les listes et les enregistrements, sélectionnez requesteditems:read ; pour consulter le catalogue des champs, ajoutez également requesteditems:schema. La création et la modification exigent requesteditems:write, tandis que la suppression exige requesteditems:delete. Ajoutez les périmètres des relations, des fichiers, des statistiques, du demandeur et de l'épinglage seulement si l'intégration utilise ces opérations.
Si l'intégration recherche des cibles de relation, la clé doit également disposer des périmètres de lecture correspondants, par exemple assets:read, clients:read, vendors:read, documents:read, tickets:read, changes:read, problems:read, releases:read, notes:read, approvals:read ou worktasks:read. Le périmètre de la clé ne remplace pas les autorisations de l'utilisateur.
Demandes - authentification
Authentifiez chaque requête Codenica API avec deux en-têtes :
export CLIENT_ID="cna_votre_client_id"
export CLIENT_SECRET="cns_votre_client_secret"
curl --request GET --url "$BASE_URL/api/v1/requesteditems?page=1&pageSize=25" \
--header "Accept: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"Une intégration externe n'a pas besoin du JWT de l'administrateur ni des cookies du panneau Codenica. Conservez le secret dans un gestionnaire de secrets côté serveur. Ne le placez pas dans du code livré au navigateur, un dépôt, une URL, l'historique des commandes ou les journaux. En dehors des tests locaux, utilisez HTTPS.
Enregistrez meta.requestId dans les réponses. Cet identifiant aide à retrouver une requête précise dans les journaux, mais il ne remplace pas l'UUID de la demande et ne constitue pas un secret.
Demandes - vérification du contexte de connexion
Avant le premier enregistrement, récupérez le contexte. Vous vérifierez ainsi que l'adresse mène à la bonne base de données et que la clé possède les périmètres et les limites nécessaires :
curl --request GET --url "$BASE_URL/api/v1/context" \
--header "Accept: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"Dans la réponse, vérifiez data.apiVersion, data.contractVersion, les données de data.tenant, la valeur de data.caller.authentication égale à api_key, la présence de requesteditems dans data.capabilities.resources, les périmètres de la clé et les limites de requêtes.
Si le contexte indique une autre entreprise ou ne contient pas le périmètre requis, corrigez l'adresse ou créez une clé avec les autorisations appropriées. N'essayez pas d'acheminer la requête vers une autre base en envoyant un tenantId externe.
Demandes - schéma et cibles des relations
Le schéma est la source d'information sur les champs actuels, leurs types, leur possibilité d'écriture et les cibles de relation autorisées :
curl --request GET --url "$BASE_URL/api/v1/requesteditems/schema" \
--header "Accept: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"La réponse contient notamment data.itemType, data.fields et data.relationshipTargets. Pour ce module, itemType vaut requesteditem. Pour chaque champ, vérifiez readable, writable, required, technical, unique et maxLength.
Extrait de schéma :
{
"data": {
"itemType": "requesteditem",
"fields": [
{ "name": "title", "type": "string", "writable": true },
{ "name": "dateDue", "type": "dateTime", "writable": true },
{ "name": "quantity", "type": "integer", "writable": true },
{ "name": "value", "type": "number", "writable": true },
{ "name": "pin", "type": "integer", "writable": false }
],
"relationshipTargets": [
{ "targetDataSet": "assets", "targetItemType": "asset" },
{ "targetDataSet": "documents", "targetItemType": "document" },
{ "targetDataSet": "worktasks", "targetItemType": "worktask" }
]
}
}Ne construisez pas votre mapping uniquement à partir de cet exemple. Avant de lancer l'intégration, récupérez le schéma de la bonne base et utilisez uniquement les champs et les cibles retournés.
Demandes - champs métier et système
Les champs les plus importants d'une demande sont les suivants :
customIddateDue, dateEndlocation, departmenttag, linktitlestatus, priority, category, budget, currencytax, quantitycost, price, valuedescriptionid, itemType, creator, updater, dateCreated, dateUpdated, importId, importSource et dateImported sont définis par le système ou réservés à la lecture technique. Ne les envoyez pas dans attributes.
appUserRequesterId
clientRequesterId
catalogId
catalogItemId
creator
updater
dateCreated
dateUpdated
importId
importSource
dateImportedDemandes - endpoints disponibles
Les principales routes du module requesteditems sont les suivantes :
GET /api/v1/requesteditems
POST /api/v1/requesteditems
GET /api/v1/requesteditems/{REQUESTED_ITEM_ID}
PATCH /api/v1/requesteditems/{REQUESTED_ITEM_ID}
DELETE /api/v1/requesteditems/{REQUESTED_ITEM_ID}
GET /api/v1/requesteditems/schema
GET /api/v1/requesteditems/stats
GET /api/v1/requesteditems/values
POST /api/v1/requesteditems:batch
GET /api/v1/requesteditems/{REQUESTED_ITEM_ID}/relationships
POST /api/v1/requesteditems/{REQUESTED_ITEM_ID}/relationships
POST /api/v1/requesteditems/{REQUESTED_ITEM_ID}/relationships:batch
DELETE /api/v1/requesteditems/{REQUESTED_ITEM_ID}/relationships/{DATASET}/{TARGET_ID}
GET /api/v1/requesteditems/{REQUESTED_ITEM_ID}/user-relationships
GET /api/v1/requesteditems/{REQUESTED_ITEM_ID}/files
POST /api/v1/requesteditems/{REQUESTED_ITEM_ID}/files
POST /api/v1/requesteditems/{REQUESTED_ITEM_ID}/files/{FILE_ID}
DELETE /api/v1/requesteditems/{REQUESTED_ITEM_ID}/files/{FILE_ID}
GET /api/v1/requesteditems/{REQUESTED_ITEM_ID}/files/{FILE_ID}/content
POST /api/v1/requesteditems/{REQUESTED_ITEM_ID}/pinLes lectures exigent les périmètres read, tandis que chaque mutation exige les périmètres supplémentaires prévus par le tableau des autorisations. Toute requête qui modifie les données exige également un Idempotency-Key.
Demandes - listes et pagination
Récupérez la liste des demandes page par page. Exemple :
curl --request GET --url "$BASE_URL/api/v1/requesteditems?itemType=requesteditem&page=1&pageSize=25" \
--header "Accept: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"La réponse contient la collection data.items ainsi que les informations sur la page :
{
"data": {
"items": [
{
"id": "requested-item-uuid",
"itemType": "requesteditem",
"attributes": {
"customId": "ERP-REQ-2026-0042",
"title": "Trois moniteurs pour un nouveau poste",
"status": "Open",
"quantity": 3,
"value": 3136.5
},
"meta": {
"etag": "\"etag-value\""
}
}
],
"page": 1,
"pageSize": 25,
"totalItems": 1,
"totalPages": 1,
"hasNextPage": false
},
"meta": {
"requestId": "request-id"
}
}Passez à la page suivante en fonction de hasNextPage. Ne supposez pas que la dernière page contient toujours moins d'éléments que le pageSize choisi. Vérifiez la taille maximale dans data.capabilities.limits ou dans le contrat actuel.
Demandes - recherche et filtres
Utilisez le paramètre search pour la recherche textuelle. Pour la synchronisation, il est préférable d'utiliser un customId stable, un UUID ou un filtre explicite :
curl --silent --show-error -G \
--data-urlencode "search=moniteurs" \
--data-urlencode "page=1" \
--data-urlencode "pageSize=20" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
"$BASE_URL/api/v1/requesteditems"Les filtres simples peuvent utiliser les noms de champs :
curl --silent --show-error -G \
--data-urlencode "status=Open" \
--data-urlencode "priority=High" \
--data-urlencode "customId=ERP-REQ-2026-0042" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
"$BASE_URL/api/v1/requesteditems"Un filtre structurel suit la forme field:operator:value :
status:eq:Open
priority:ne:Low
quantity:gte:2
price:lt:1000
title:contains:laptop
customId:startswith:ERP-
link:notempty:Les opérateurs pris en charge sont eq, ne, gt, gte, lt, lte, contains, startswith, endswith et notempty. Encodez la valeur du filtre dans l'URL, surtout si elle contient un espace, deux-points ou un caractère spécial.
Demandes - sélection des champs et inclusion des données
Si vous n'avez besoin que d'une partie de la réponse, utilisez fields. Ajoutez les fichiers, les relations et les utilisateurs avec include :
curl --silent --show-error -G \
--data-urlencode "fields=id,itemType,customId,title,status,priority,dateDue,quantity,value" \
--data-urlencode "include=files,relationships,users" \
--data-urlencode "ids=7512ef99-0010-4962-9453-99383a377e4b" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
"$BASE_URL/api/v1/requesteditems"Les valeurs include disponibles sont files, relationships et users. Chacune exige le périmètre correspondant. fields=* ne contourne pas les autorisations sur les champs techniques et ne renvoie pas les champs système réservés à l'enveloppe de réponse.
Vous pouvez aussi utiliser createdAfter, createdBefore, updatedAfter, updatedBefore, sort et direction pour filtrer. Vérifiez les noms de champs de fields, sort et filter par rapport au schéma actuel.
Demandes - statistiques et valeurs des champs
L'endpoint stats aide à examiner la répartition des données, tandis que values renvoie les valeurs utiles pour construire des filtres :
curl --silent --show-error -G \
--data-urlencode "field=status" \
--data-urlencode "limit=20" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
"$BASE_URL/api/v1/requesteditems/stats"
curl --silent --show-error -G \
--data-urlencode "field=category" \
--data-urlencode "search=hard" \
--data-urlencode "limit=20" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
"$BASE_URL/api/v1/requesteditems/values"Exemple de réponse values :
{
"data": {
"field": "category",
"values": ["Hardware", "Office"]
},
"meta": {
"requestId": "request-id"
}
}Les statistiques et les valeurs sont des lectures et ne modifient pas les demandes. Ne les interrogez pas en boucle serrée sans nécessité - le schéma et les valeurs de champs peuvent être mis en cache pendant une durée adaptée à l'intégration.
Demandes - création minimale
Créez un enregistrement avec POST /api/v1/requesteditems. Indiquez itemType dans le body et les champs dans attributes :
curl --request POST --url "$BASE_URL/api/v1/requesteditems" \
--header "Content-Type: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "Idempotency-Key: requesteditem-create-unique-001" \
--data-raw '{
"itemType": "requesteditem",
"attributes": {
"customId": "ERP-REQ-2026-0042",
"title": "Achat de fournitures de bureau",
"category": "Office",
"quantity": 10,
"currency": "PLN",
"status": "Open",
"description": "Élément créé par l'intégration."
}
}'La valeur de itemType doit être requesteditem. Adaptez les noms et les types de champs à la réponse du schéma. Envoyez les dates au format ISO 8601 et les nombres comme des nombres JSON, sans les formater en chaînes de caractères.
Une réponse correcte possède le statut 201 Created. Enregistrez data.id, l'ETag de l'en-tête HTTP et l'ETag de data.meta.etag.
Demandes - création complète avec champs financiers
L'exemple suivant correspond à un enregistrement du parcours de démonstration complet. Il montre une échéance, un lieu, un statut, une priorité et des données de règlement :
curl --request POST --url "$BASE_URL/api/v1/requesteditems" \
--header "Content-Type: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "Idempotency-Key: requesteditem-create-20260906053922-source" \
--data-raw '{
"itemType": "requesteditem",
"attributes": {
"customId": "PUBLIC-API-REQUESTEDITEM-20260906053922-SOURCE",
"dateDue": "2026-12-31T17:00:00Z",
"dateEnd": "2027-01-15T17:00:00Z",
"location": "Warsaw",
"department": "IT",
"tag": "public-api,requesteditems,demo",
"link": "https://codenica.com",
"title": "Parcours complet de l'API des demandes",
"status": "Open",
"priority": "High",
"category": "Hardware",
"budget": "IT-2026",
"currency": "PLN",
"tax": 23,
"quantity": 3,
"cost": 300,
"price": 100,
"value": 369,
"description": "Demande de démonstration créée via l'API publique."
},
"customValues": [
{
"name": "description",
"valuePattern": "[requested-item-demo] Public API"
}
]
}'customValues est facultatif. Supprimez cette propriété si l'intégration n'utilise pas de règles de valeurs supplémentaires. N'envoyez pas de champs techniques simplement parce qu'ils apparaissent dans une réponse.
Demandes - nouvelle tentative sûre de la création
Si un délai d'attente survient après l'envoi d'une requête et que vous ne savez pas si l'enregistrement a été sauvegardé, répétez exactement la même opération avec le même Idempotency-Key et un body identique :
curl --request POST --url "$BASE_URL/api/v1/requesteditems" \
--header "Content-Type: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "Idempotency-Key: requesteditem-create-20260906053922-source" \
--data-binary @requesteditem-create.jsonLe fichier requesteditem-create.json doit contenir exactement le body de la première requête. La nouvelle tentative renvoie le même enregistrement au lieu de créer un doublon. Une nouvelle intention métier, un body modifié ou une autre route exigent une nouvelle clé. Une nouvelle tentative avec un body différent renvoie 422 idempotency_key_reused.
Conservez la clé d'idempotence côté intégration avec le statut de l'opération. N'utilisez pas le secret client à cette fin.
Demandes - lecture d'un enregistrement et ETag
Après avoir créé ou trouvé une demande, récupérez-la par UUID :
export REQUESTED_ITEM_ID="7512ef99-0010-4962-9453-99383a377e4b"
curl --request GET --url "$BASE_URL/api/v1/requesteditems/$REQUESTED_ITEM_ID?include=files,relationships,users" \
--header "Accept: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"Vous trouverez l'ETag actuel dans l'en-tête HTTP et généralement dans data.meta.etag ainsi que dans l'enveloppe principale meta.etag :
ETag: "etag-value"L'ETag est une version opaque d'un enregistrement précis. Ne retirez pas les guillemets renvoyés dans l'en-tête et ne calculez pas cette valeur vous-même. Avant toute modification de l'enregistrement, d'une relation ou d'un fichier, récupérez un ETag récent si une autre personne ou intégration a pu modifier l'enregistrement.
Demandes - mise à jour partielle avec If-Match
PATCH ne modifie que les champs envoyés dans le body. Il exige l'ETag actuel et une nouvelle clé d'idempotence :
export REQUESTED_ITEM_ETAG='"etag-value-from-get"'
curl --request PATCH --url "$BASE_URL/api/v1/requesteditems/$REQUESTED_ITEM_ID" \
--header "Accept: application/json" \
--header "Content-Type: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "If-Match: $REQUESTED_ITEM_ETAG" \
--header "Idempotency-Key: requesteditem-update-20260906-0001" \
--data-raw '{
"attributes": {
"dateDue": "2027-01-31T17:00:00Z",
"title": "Demand API - parcours complet - mise à jour",
"status": "In progress",
"priority": "Normal",
"quantity": 4,
"price": 125,
"value": 615
}
}'Il n'est pas nécessaire d'envoyer l'objet complet. Les champs absents du body restent inchangés. Après une réponse 200 OK, remplacez l'ETag enregistré par la valeur renvoyée par l'API. Toute mutation suivante doit utiliser la version la plus récente.
Demandes - ETag obsolète et If-Match manquant
L'absence de l'en-tête If-Match est rejetée afin qu'une intégration ne puisse pas écraser les modifications effectuées par une autre personne :
curl --request PATCH --url "$BASE_URL/api/v1/requesteditems/$REQUESTED_ITEM_ID" \
--header "Content-Type: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "Idempotency-Key: requesteditem-update-without-etag-0001" \
--data-raw '{"attributes":{"status":"Approved"}}'Le résultat attendu est 428 Precondition Required avec le code if_match_required. Si vous envoyez un ETag ancien, vous recevez 412 Precondition Failed avec le code if_match_failed :
HTTP 412 Precondition Failed
code: if_match_failedAprès une erreur 412, récupérez à nouveau l'enregistrement, comparez votre modification aux données actuelles, puis envoyez seulement un nouveau PATCH. Ne lancez pas une boucle aveugle qui écraserait les modifications d'un utilisateur.
Demandes - épinglage et désépinglage
pin est un champ en lecture seule dans attributes. Définissez-le avec un endpoint distinct et l'ETag actuel :
curl --request POST --url "$BASE_URL/api/v1/requesteditems/$REQUESTED_ITEM_ID/pin" \
--header "Content-Type: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "If-Match: $REQUESTED_ITEM_ETAG" \
--header "Idempotency-Key: requesteditem-pin-0001" \
--data '{"pin":3}'Les valeurs de 0 à 3 sont autorisées. Pour supprimer l'épinglage, utilisez null :
curl --request POST --url "$BASE_URL/api/v1/requesteditems/$REQUESTED_ITEM_ID/pin" \
--header "Content-Type: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "If-Match: $REQUESTED_ITEM_ETAG" \
--header "Idempotency-Key: requesteditem-unpin-0001" \
--data '{"pin":null}'Enregistrez le nouvel ETag après chaque opération. N'essayez pas de modifier pin avec un PATCH ordinaire.
Demandes - relation du demandeur
Chaque demande peut avoir une relation système requester. Lisez-la avec :
curl --request GET --url "$BASE_URL/api/v1/requesteditems/$REQUESTED_ITEM_ID/user-relationships" \
--header "Accept: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"Le demandeur est défini par un flux système existant et peut désigner appUserRequesterId ou clientRequesterId. L'API publique permet la lecture, mais ne propose pas de POST ni de DELETE séparé pour modifier cette relation. N'essayez pas de définir le demandeur dans un champ non documenté de attributes. La lecture exige requesteditems:users:read ainsi que les autorisations appropriées sur les données.
Demandes - relations d'objets autorisées
Le catalogue actuel des cibles de relation des demandes comprend :
assetsassetclients, vendorsclient, vendordocuments, ticketsdocument, ticketchanges, problems, releaseschange, problem, releasenotes, approvalsnote, approvalworktasksworktaskIl n'existe pas de relation avec la collection requesteditems elle-même ni avec confirmations. La cible doit être visible pour l'utilisateur associé à la clé et correspondre à la liste relationshipTargets renvoyée par le schéma.
Demandes - ajout, lecture et suppression des relations
Une relation entre objets ne stocke pas relationshipType. Dans le payload, indiquez targetId, targetDataSet et un targetItemType compatible :
{
"targetId": "5ddc5b5a-5bdc-46f9-ab7e-5ad8f6775b3a",
"targetDataSet": "assets",
"targetItemType": "asset"
}L'ajout d'une relation exige l'ETag actuel de la source, le périmètre requesteditems:relationships:write et une clé d'idempotence distincte :
curl --request POST --url "$BASE_URL/api/v1/requesteditems/$REQUESTED_ITEM_ID/relationships" \
--header "Content-Type: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "If-Match: $REQUESTED_ITEM_ETAG" \
--header "Idempotency-Key: requesteditem-relationship-asset-0001" \
--data '{
"targetId": "5ddc5b5a-5bdc-46f9-ab7e-5ad8f6775b3a",
"targetDataSet": "assets",
"targetItemType": "asset"
}'Lisez la liste des relations avec :
curl --request GET --url "$BASE_URL/api/v1/requesteditems/$REQUESTED_ITEM_ID/relationships?page=1&pageSize=50" \
--header "Accept: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"Supprimez une relation par collection et UUID de la cible :
curl --request DELETE --url "$BASE_URL/api/v1/requesteditems/$REQUESTED_ITEM_ID/relationships/assets/5ddc5b5a-5bdc-46f9-ab7e-5ad8f6775b3a" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "If-Match: $REQUESTED_ITEM_ETAG" \
--header "Idempotency-Key: requesteditem-relationship-asset-delete-0001"Après l'ajout ou la suppression d'une relation, relisez les données de la source et enregistrez le nouvel ETag. Si le schéma ne renvoie pas une cible, ne l'utilisez pas dans l'intégration.
Demandes - modifications groupées des relations
Pour plusieurs modifications dans une seule requête, utilisez relationships:batch. Pour les relations des demandes, n'envoyez toujours pas relationshipType :
curl --request POST --url "$BASE_URL/api/v1/requesteditems/$REQUESTED_ITEM_ID/relationships:batch" \
--header "Content-Type: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "If-Match: $REQUESTED_ITEM_ETAG" \
--header "Idempotency-Key: requesteditem-relationship-batch-0001" \
--data-raw '{
"add": [
{
"targetId": "5ddc5b5a-5bdc-46f9-ab7e-5ad8f6775b3a",
"targetDataSet": "assets",
"targetItemType": "asset"
},
{
"targetId": "88b93fb8-8848-4669-9d87-ed4795e13bcc",
"targetDataSet": "documents",
"targetItemType": "document"
}
],
"remove": [
{
"targetId": "8f42dc16-167b-4e4a-983f-862ae85f3c7a",
"targetDataSet": "worktasks",
"targetItemType": "worktask"
}
]
}'La réponse contient des compteurs :
{
"data": {
"added": 2,
"removed": 1,
"skipped": 0
},
"meta": {
"requestId": "request-id"
}
}Ne considérez pas automatiquement skipped comme une réussite métier. Après le batch, lisez la collection des relations et vérifiez le résultat de chaque modification.
Demandes - liste et envoi de fichiers
Les fichiers sont traités séparément des champs de la demande. Lisez d'abord la liste actuelle :
curl --request GET --url "$BASE_URL/api/v1/requesteditems/$REQUESTED_ITEM_ID/files?page=1&pageSize=50" \
--header "Accept: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"Envoyez le fichier en multipart/form-data. Le rôle du fichier est transmis dans la chaîne de requête :
curl --request POST --url "$BASE_URL/api/v1/requesteditems/$REQUESTED_ITEM_ID/files?relationshipType=request-form" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "If-Match: $REQUESTED_ITEM_ETAG" \
--header "Idempotency-Key: requesteditem-file-upload-0001" \
--form "[email protected];type=application/pdf"Un élément de fichier contient notamment id, fileName, contentType, size, relationshipType, isMain et downloadUrl. Vérifiez la taille avant l'envoi et définissez consciemment le type MIME.
Demandes - téléchargement, rattachement et suppression de fichiers
Téléchargez le contenu du fichier avec l'endpoint content et enregistrez-le en mode binaire :
curl --request GET --url "$BASE_URL/api/v1/requesteditems/$REQUESTED_ITEM_ID/files/$FILE_ID/content" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--output demande-telechargee.pdfSi le fichier existe déjà dans le système, vous pouvez le rattacher sans envoyer une nouvelle copie :
curl --request POST --url "$BASE_URL/api/v1/requesteditems/$REQUESTED_ITEM_ID/files/$FILE_ID?relationshipType=quotation" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "If-Match: $REQUESTED_ITEM_ETAG" \
--header "Idempotency-Key: requesteditem-file-attach-0001"Suppression d'un fichier d'une demande :
curl --request DELETE --url "$BASE_URL/api/v1/requesteditems/$REQUESTED_ITEM_ID/files/$FILE_ID" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "If-Match: $REQUESTED_ITEM_ETAG" \
--header "Idempotency-Key: requesteditem-file-delete-0001"Attach crée une relation avec un fichier existant, mais n'envoie pas une nouvelle copie. Le modèle actuel des demandes n'a pas d'endpoint pour le fichier principal : chaque élément possède isMain=false. N'utilisez pas /files/{FILE_ID}/main ni makeMain pour cet objet.
Demandes - opérations batch
L'endpoint /api/v1/requesteditems:batch permet de créer, modifier et supprimer plusieurs enregistrements. Il ne remplace pas les opérations sur les fichiers, l'épinglage ou le batch des relations :
curl --request POST --url "$BASE_URL/api/v1/requesteditems:batch" \
--header "Content-Type: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "Idempotency-Key: requesteditems-batch-20260906-0001" \
--data-raw '{
"items": [
{
"operation": "create",
"create": {
"itemType": "requesteditem",
"attributes": {
"customId": "ERP-REQ-BATCH-001",
"title": "Souris et clavier pour l'équipe",
"category": "Hardware",
"quantity": 5,
"price": 150,
"currency": "PLN",
"status": "Open"
}
}
},
{
"operation": "update",
"id": "7dc877ec-4766-42cc-a34a-900e55ab3f46",
"ifMatch": "\"etag-from-get\"",
"update": {
"attributes": {
"status": "Approved",
"quantity": 6
}
}
},
{
"operation": "delete",
"id": "476b8c2e-6da9-409d-bb35-98039619ccfe",
"ifMatch": "\"etag-after-update\""
}
]
}'Chaque élément update et delete possède son propre ETag. Un batch n'est pas une transaction tout ou rien. Parcourez les items de la réponse et enregistrez le statut, l'UUID et l'erreur de chaque élément. Un résultat partiel peut renvoyer 207 Multi-Status.
Demandes - suppression d'un enregistrement
Avant la suppression, récupérez à nouveau l'enregistrement, vérifiez son UUID et son ETag actuel, puis assurez-vous que le processus métier autorise cette suppression :
curl --request DELETE --url "$BASE_URL/api/v1/requesteditems/$REQUESTED_ITEM_ID" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "If-Match: $REQUESTED_ITEM_ETAG" \
--header "Idempotency-Key: requesteditem-delete-20260906-0001"Une réponse correcte renvoie 200 OK et data=true. Après la suppression, une nouvelle lecture de l'UUID devrait renvoyer 404 Not Found avec le code requestedItem_not_found. Vous pouvez aussi effectuer un contrôle final avec une liste filtrée par customId et attendre totalItems=0.
Supprimer un enregistrement ne permet pas de conserver l'historique du processus. Si les données ont une valeur d'audit, enregistrez les informations nécessaires dans le système source avant d'exécuter DELETE.
Demandes - erreurs, limites et ordre de travail sûr
Les erreurs utilisent le format Problem Details. Enregistrez status, code et requestId dans les journaux, mais n'enregistrez jamais le secret client ni les en-têtes complets :
authentication_failedscope_or_access_deniedrequestedItem_not_foundif_match_failedif_match_required ou idempotency_key_requiredvalidation_failedrate_limit_exceededRetry-After.Lisez X-RateLimit-Limit et X-RateLimit-Remaining. Limitez la concurrence, mettez en cache le schéma et les valeurs et appliquez un backoff après 429. Une séquence sûre est : context, schema, liste ou lecture par UUID, création avec Idempotency-Key, enregistrement de l'UUID et de l'ETag, fichiers ou relations, modification avec If-Match, lecture de vérification et suppression seulement à la fin. Le même modèle peut être utilisé dans n8n si les identifiants sont enregistrés comme credential et que les UUID, les ETag et les clés d'idempotence sont transmis entre les nœuds.
