Confirmations dans Codenica API

Pour commencer à travailler avec les Confirmations via Codenica API, créez une clé API dans les paramètres de Codenica. Si vous n'en avez pas encore, ouvrez Codenica API - introduction dans un nouvel onglet. Cet article présente les règles communes de création des clés, de conservation des secrets et d'authentification.

Une Confirmation est un enregistrement de processus pour lequel un Client précis doit prendre une décision. Une intégration peut préparer les données, affecter le Client, joindre des documents, des actifs, des notes et des fichiers, puis rendre la décision disponible dans le contexte du Client concerné.

Le nom technique d'un enregistrement est confirmation et celui de la collection API est confirmations. Une modification classique concerne la partie descriptive de l'enregistrement. N'écrivez pas le résultat de la décision directement dans status - utilisez l'endpoint dédié /decision pour confirmer ou refuser une Confirmation.

Les exemples utilisent PUBLIC-API-CONFIRMATION-20260908-0001. Remplacez cette référence par celle de votre application d'intégration et les valeurs entre accolades par les données de votre base.


Confirmations - adresse de l'API et choix de l'installation

Toutes les routes des Confirmations commencent par :

{BASE_URL}/api/v1/confirmations

BASE_URL désigne l'adresse du serveur Codenica sans le suffixe /api/v1. Avec Codenica Cloud, utilisez le domaine ou le sous-domaine attribué à l'entreprise concernée :

export BASE_URL="https://{domaine-de-l-entreprise}"

Dans l'installation On-Premise par défaut, Codenica Discovery enregistre l'adresse locale suivante :

export BASE_URL="http://codenica.local:5150"

Si l'administrateur a publié l'installation sur un domaine d'entreprise, en HTTPS, derrière un reverse proxy ou sur un autre port, utilisez l'adresse exacte communiquée pour cette installation :

export BASE_URL="https://{adresse-reelle-de-l-installation}"

N'utilisez localhost que si l'intégration et l'API fonctionnent sur le même ordinateur. L'exemple http://localhost:5050 concerne un environnement de développement local, et non l'adresse On-Premise standard. N'envoyez pas tenantId dans le body ni dans la chaîne de requête. La base de données cible est sélectionnée à partir de l'hôte de la requête.


Confirmations - périmètres de la clé API

La clé utilisée pour les Confirmations doit contenir uniquement les périmètres nécessaires à l'intégration. L'ensemble complet des périmètres du module est le suivant :

confirmations:read
confirmations:write
confirmations:delete
confirmations:schema
confirmations:stats
confirmations:relationships:read
confirmations:relationships:write
confirmations:users:read
confirmations:files:read
confirmations:files:write
confirmations:technical:read
confirmations:technical:write
confirmations:pin:write
confirmations:decision:write
users:read

Utilisez confirmations:read pour les listes et les enregistrements. La création et la modification classique exigent confirmations:write, tandis que la suppression exige confirmations:delete. Ajoutez les périmètres des relations, des fichiers, des statistiques, des champs techniques, de l'épinglage et des décisions uniquement si l'intégration réalise ces opérations.

Si l'intégration sélectionne des cibles de relation dans une autre collection, elle doit aussi disposer du périmètre de lecture correspondant, par exemple assets:read, documents:read, clients:read ou notes:read. Les périmètres de la clé ne remplacent pas les droits de l'utilisateur auquel la clé est associée.


Confirmations - authentification des requêtes

Authentifiez chaque requête Codenica API avec deux en-têtes :

X-Codenica-Client-Id: {CLIENT_ID}
X-Codenica-Client-Secret: {CLIENT_SECRET}
Accept: application/json

Exemple de première requête :

export PUBLIC_API_CLIENT_ID="cna_example"
export PUBLIC_API_CLIENT_SECRET="cns_example"

curl --request GET --url "$BASE_URL/api/v1/context" \
  --header "Accept: application/json" \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET"

Une intégration externe n'a pas besoin du Bearer JWT de l'administrateur ni des cookies du panneau Codenica. Conservez le Client Secret côté serveur, dans un coffre-fort de secrets. Ne le placez pas dans le code du navigateur, un dépôt, une URL, l'historique des commandes ou les journaux. En dehors du développement local, utilisez HTTPS.

Conservez meta.requestId dans les réponses. Cet identifiant facilite la recherche de la requête dans les journaux, mais ne remplace pas l'UUID de la Confirmation et ne constitue pas un secret.


Confirmations - vérifier le contexte de connexion

Lisez le contexte avant la première écriture. 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 --fail-with-body --silent --show-error \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  "$BASE_URL/api/v1/context"

Vérifiez notamment data.apiVersion, data.contractVersion, les données de data.tenant, la valeur api_key dans data.caller.authentication, le rôle et le clientId de l'appelant, la présence de confirmations dans data.capabilities.resources, ainsi que les périmètres et les limites.

{
  "data": {
    "caller": {
      "role": "Administrator",
      "authentication": "api_key",
      "scopes": [
        "confirmations:read",
        "confirmations:write",
        "confirmations:decision:write"
      ]
    },
    "capabilities": {
      "supportsETag": true,
      "supportsIdempotency": true,
      "supportsRelationships": true,
      "supportsFiles": true
    }
  },
  "meta": { "requestId": "{REQUEST_ID}" }
}

Si le contexte identifie la mauvaise entreprise ou ne contient pas un périmètre requis, corrigez l'adresse ou la clé. N'essayez pas de sélectionner une autre base en envoyant un identifiant provenant d'une autre installation.


Confirmations - schéma et cibles de relations

Le schéma est la référence pour connaître les champs actuels, leurs types, leur caractère modifiable et les cibles de relations autorisées :

curl --fail-with-body --silent --show-error \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  "$BASE_URL/api/v1/confirmations/schema"

La réponse contient notamment data.itemType, data.fields et data.relationshipTargets. Pour ce module, itemType vaut toujours confirmation. Pour chaque champ, vérifiez readable, writable, required, technical, unique et maxLength.

{
  "data": {
    "itemType": "confirmation",
    "fields": [
      { "name": "customId", "type": "string", "writable": true },
      { "name": "status", "type": "string", "writable": false },
      { "name": "pin", "type": "integer", "writable": false }
    ],
    "relationshipTargets": [
      { "targetDataSet": "assets" },
      { "targetDataSet": "clients", "targetItemType": "client" },
      { "targetDataSet": "documents", "targetItemType": "document" },
      { "targetDataSet": "notes", "targetItemType": "note" }
    ]
  }
}

Pour assets, le schéma n'impose pas un type unique. Si une cible possède itemType=computer, envoyez computer dans la requête de relation au lieu de supposer asset. Ne construisez pas le mapping à partir d'un seul exemple - lisez le schéma actuel avant d'exécuter l'intégration.


Confirmations - champs métier et champs du processus

Les principaux champs que vous pouvez envoyer dans attributes sont les suivants :

Champ
Type
Utilisation
customId
string
Identifiant de l'application d'intégration
location, department
string
Lieu et service associés à la demande
tag, link
string
Étiquettes et lien vers la source de la demande
info, description
string
Informations complémentaires et description de ce qui doit être confirmé
type, category
string
Type et catégorie du processus
status, dateConfirmed, dateDeclined, dateEnd, remark, pin
lecture seule
Résultat de la décision, commentaire et épinglage

Les principales longueurs maximales sont notamment : customId 500, location 300, department 300, tag 2000, link 2000, info 10000, type 300, category 300 et description 10000 caractères. Le schéma actuel de la base reste prioritaire.

N'écrivez pas status, dateConfirmed, dateDeclined, dateEnd, remark ou pin dans un PATCH classique. N'envoyez pas non plus les champs d'audit :

creator
updater
dateCreated
dateUpdated
importId
importSource
dateImported

Confirmations - endpoints disponibles

Les principales routes du module confirmations sont les suivantes :

GET    /api/v1/confirmations
POST   /api/v1/confirmations
GET    /api/v1/confirmations/{CONFIRMATION_ID}
PATCH  /api/v1/confirmations/{CONFIRMATION_ID}
DELETE /api/v1/confirmations/{CONFIRMATION_ID}
GET    /api/v1/confirmations/schema
GET    /api/v1/confirmations/stats
GET    /api/v1/confirmations/values
POST   /api/v1/confirmations:batch
GET    /api/v1/confirmations/{CONFIRMATION_ID}/relationships
POST   /api/v1/confirmations/{CONFIRMATION_ID}/relationships
POST   /api/v1/confirmations/{CONFIRMATION_ID}/relationships:batch
DELETE /api/v1/confirmations/{CONFIRMATION_ID}/relationships/{DATASET}/{TARGET_ID}
GET    /api/v1/confirmations/{CONFIRMATION_ID}/user-relationships
GET    /api/v1/confirmations/{CONFIRMATION_ID}/files
POST   /api/v1/confirmations/{CONFIRMATION_ID}/files
POST   /api/v1/confirmations/{CONFIRMATION_ID}/files/{FILE_ID}
DELETE /api/v1/confirmations/{CONFIRMATION_ID}/files/{FILE_ID}
GET    /api/v1/confirmations/{CONFIRMATION_ID}/files/{FILE_ID}/content
POST   /api/v1/confirmations/{CONFIRMATION_ID}/pin
POST   /api/v1/confirmations/{CONFIRMATION_ID}/decision

Les lectures exigent les périmètres de lecture, tandis que chaque mutation exige le périmètre supplémentaire correspondant à l'opération. Toute requête qui modifie les données exige Idempotency-Key ; une opération sur un enregistrement existant exige également le If-Match actuel.


Confirmations - listes et pagination

Lisez les Confirmations par pages. Vous pouvez envoyer la valeur fixe itemType=confirmation, même si l'API utilise déjà ce type pour tout le module :

curl --fail-with-body --silent --show-error \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  "$BASE_URL/api/v1/confirmations?itemType=confirmation&page=1&pageSize=25"

La réponse contient la collection data.items et les informations de pagination :

{
  "data": {
    "items": [
      {
        "id": "{CONFIRMATION_ID}",
        "itemType": "confirmation",
        "attributes": {
          "customId": "ERP-CONFIRMATION-2026-0042",
          "category": "Achats",
          "status": "Pending"
        },
        "meta": { "etag": "{ETAG}" }
      }
    ],
    "page": 1,
    "pageSize": 25,
    "totalItems": 1,
    "totalPages": 1,
    "hasNextPage": false
  },
  "meta": { "requestId": "{REQUEST_ID}" }
}

Passez à la page suivante selon hasNextPage. Lisez la taille maximale d'une page dans data.capabilities.limits.maxPageSize au lieu de la coder en dur.


Confirmations - recherche et filtres

Le paramètre search recherche du texte dans les champs descriptifs. Pour une synchronisation, un customId stable ou un UUID est généralement préférable :

curl --silent --show-error -G \
  --data-urlencode "search=achats" \
  --data-urlencode "page=1" \
  --data-urlencode "pageSize=20" \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  "$BASE_URL/api/v1/confirmations"

Vous pouvez combiner plusieurs filtres de champs dans une seule requête :

curl --silent --show-error -G \
  --data-urlencode "status=Pending" \
  --data-urlencode "category=Achats" \
  --data-urlencode "customId=ERP-CONFIRMATION-2026-0042" \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  "$BASE_URL/api/v1/confirmations"

Pour un filtrage plus précis, utilisez la forme structurée field:operator:value :

category:eq:Achats
status:ne:Declined
description:contains:moniteur
customId:startswith:ERP-CONFIRMATION-
link:notempty:

Les opérateurs utiles comprennent notamment eq, ne, contains, startswith, endswith et notempty. Encodez dans l'URL les valeurs qui contiennent des espaces, des deux-points ou des caractères spéciaux.


Confirmations - sélection des champs et données incluses

Le paramètre fields limite les attributs renvoyés dans la réponse. Lors d'une synchronisation de liste, ne demandez que les données nécessaires à l'intégration :

curl --fail-with-body --silent --show-error \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  "$BASE_URL/api/v1/confirmations?fields=id,customId,status,category&page=1&pageSize=20"

Pour recevoir dans la même réponse les fichiers, les relations et l'utilisateur créateur, utilisez include :

curl --fail-with-body --silent --show-error \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  "$BASE_URL/api/v1/confirmations/{CONFIRMATION_ID}?fields=%2A&include=files%2Crelationships%2Cusers"

L'inclusion des fichiers exige confirmations:files:read, celle des relations confirmations:relationships:read et celle des utilisateurs confirmations:users:read. Gardez fields et include ciblés lorsque l'intégration n'a pas besoin de l'enregistrement complet.


Confirmations - statistiques et valeurs de champs

L'endpoint stats aide à construire un récapitulatif des Confirmations visibles, tandis que values fournit les valeurs destinées aux filtres :

curl --fail-with-body --silent --show-error \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  "$BASE_URL/api/v1/confirmations/stats?field=category&limit=20"
curl --fail-with-body --silent --show-error \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  "$BASE_URL/api/v1/confirmations/values?field=category&search=ach&limit=20"

Ces deux endpoints sont en lecture seule et exigent confirmations:stats. Les résultats ne comprennent que les enregistrements visibles pour l'utilisateur associé à la clé et ne nécessitent pas d'ETag. Vérifiez la valeur maximale de limit dans le contrat API actuel.


Confirmations - création d'un enregistrement et affectation d'un Client

Une Confirmation qui nécessite une décision doit pointer vers un Client métier. Il s'agit de l'objet Client de la base, et non de l'identité technique AppUser utilisée pour se connecter :

{
  "targetId": "{CLIENT_ID}",
  "targetDataSet": "clients",
  "targetItemType": "client"
}

Le payload minimal contient le itemType fixe, les attributes descriptifs et la relation vers le Client :

{
  "itemType": "confirmation",
  "attributes": {
    "customId": "ERP-CONFIRMATION-2026-0042",
    "category": "Achats",
    "description": "Confirmation de l'achat d'une station de travail."
  },
  "relationships": [
    {
      "targetId": "{CLIENT_ID}",
      "targetDataSet": "clients",
      "targetItemType": "client"
    }
  ]
}

L'affectation peut être envoyée dès la création. N'ajoutez pas le champ relationshipType à cette relation.


Confirmations - exemple complet de création

Dans une intégration plus importante, enregistrez le body dans un fichier afin de pouvoir relancer sans risque la requête identique après une interruption momentanée de la connexion :

{
  "itemType": "confirmation",
  "attributes": {
    "customId": "PUBLIC-API-CONFIRMATION-20260908-0001",
    "location": "Paris",
    "department": "Informatique",
    "tag": "integration,achats,confirmation",
    "link": "https://erp.example.com/requests/0001",
    "info": "Demande reçue du système d'achats.",
    "type": "Achat de matériel",
    "category": "Achats",
    "description": "Confirmation de l'achat d'une nouvelle station de travail pour le service informatique."
  },
  "relationships": [
    {
      "targetId": "{CLIENT_ID}",
      "targetDataSet": "clients",
      "targetItemType": "client"
    }
  ]
}
curl --fail-with-body --silent --show-error \
  --request POST \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  --header "Content-Type: application/json" \
  --header "Accept: application/json" \
  --header "Idempotency-Key: erp-confirmation-create-0001" \
  --data-binary @confirmation-create.json \
  "$BASE_URL/api/v1/confirmations"

Une création réussie renvoie 201 Created. La réponse contient l'UUID, le itemType, les attributs, les métadonnées de dates, l'ETag et le requestId. Conservez l'UUID et l'ETag, car les étapes suivantes en ont besoin.


Confirmations - Idempotency-Key et relances sûres

Toute requête qui modifie les données avec une clé API doit avoir son propre Idempotency-Key. Si la connexion est interrompue après l'envoi, répétez exactement la même requête avec la même clé :

curl --fail-with-body --silent --show-error \
  --request POST \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: erp-confirmation-create-0001" \
  --data-binary @confirmation-create.json \
  "$BASE_URL/api/v1/confirmations"

La répétition d'une requête identique avec la même clé ne doit pas créer une deuxième Confirmation. Ne réutilisez pas une clé pour des bodies ou des opérations différents. Une clé d'idempotence représente une seule opération métier.

Création :   Idempotency-Key = erp-confirmation-create-0001
Relance :    Idempotency-Key = erp-confirmation-create-0001
Nouvelle modification : Idempotency-Key = erp-confirmation-update-0001

Utilisez des clés distinctes pour PATCH, l'épinglage, les décisions, les relations, les fichiers et la suppression. Après chaque modification réussie, enregistrez l'ETag renvoyé par l'opération.


Confirmations - lecture d'un enregistrement

Après la création ou dès que vous avez reçu son UUID, récupérez l'enregistrement complet :

curl --fail-with-body --silent --show-error \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  "$BASE_URL/api/v1/confirmations/{CONFIRMATION_ID}?fields=%2A"

Conservez l'ETag de l'en-tête HTTP ETag ou de data.meta.etag. Conservez également meta.requestId pour le diagnostic.

curl --fail-with-body --silent --show-error \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  "$BASE_URL/api/v1/confirmations/{CONFIRMATION_ID}?fields=%2A&include=files%2Crelationships%2Cusers"

La version avec include permet de voir en une lecture le Client affecté, les relations d'objets, le requester et les fichiers. Si vous ne récupérez que les données de synchronisation, limitez la réponse avec fields.


Confirmations - modification avec l'ETag actuel

Une modification sûre suit toujours la même séquence : lisez l'enregistrement, récupérez son ETag actuel, préparez un petit PATCH, envoyez If-Match et un nouvel Idempotency-Key, puis enregistrez le nouvel ETag :

{
  "attributes": {
    "info": "Informations ajoutées après vérification dans le système d'achats.",
    "category": "Achats informatiques",
    "description": "Confirmation mise à jour par l'intégration."
  }
}
curl --fail-with-body --silent --show-error \
  --request PATCH \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  --header "Content-Type: application/json" \
  --header "If-Match: {CURRENT_ETAG}" \
  --header "Idempotency-Key: erp-confirmation-update-0001" \
  --data-binary @confirmation-update.json \
  "$BASE_URL/api/v1/confirmations/{CONFIRMATION_ID}"

Une réussite renvoie 200 OK et un nouvel ETag. Un PATCH classique peut modifier les champs descriptifs, mais ne doit pas servir à écrire status, les dates de décision, dateEnd, remark ou pin.


Confirmations - protection contre les modifications concurrentes

Si vous omettez If-Match, l'API rejette la modification :

HTTP 428 Precondition Required
code: if_match_required

Si vous envoyez un ETag plus ancien que la version actuelle de l'enregistrement, vous recevez :

HTTP 412 Precondition Failed
code: if_match_failed

Après un 412, relisez l'enregistrement, comparez ses valeurs avec la modification prévue, puis envoyez un nouveau PATCH. Ne relancez pas en boucle la même requête avec un ETag obsolète.

N'essayez pas de contourner le contrôle de version en plaçant des champs du processus dans le body :

{
  "attributes": {
    "status": "Confirmed",
    "dateConfirmed": "2026-09-08T10:30:00Z"
  }
}

Utilisez l'endpoint dédié /decision. Le système peut ainsi vérifier le Client concerné, l'état actuel du processus et la concurrence.


Confirmations - épinglage et désépinglage

L'épinglage est une opération distincte, qui ne fait pas partie d'un PATCH classique. Les valeurs autorisées sont null ou un nombre compris entre 0 et 3 :

curl --fail-with-body --silent --show-error \
  --request POST \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  --header "Content-Type: application/json" \
  --header "If-Match: {CURRENT_ETAG}" \
  --header "Idempotency-Key: erp-confirmation-pin-0001" \
  --data '{"pin":3}' \
  "$BASE_URL/api/v1/confirmations/{CONFIRMATION_ID}/pin"

Pour désépingler l'enregistrement, envoyez null :

curl --fail-with-body --silent --show-error \
  --request POST \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  --header "Content-Type: application/json" \
  --header "If-Match: {PINNED_ETAG}" \
  --header "Idempotency-Key: erp-confirmation-unpin-0001" \
  --data '{"pin":null}' \
  "$BASE_URL/api/v1/confirmations/{CONFIRMATION_ID}/pin"

Les deux opérations exigent confirmations:pin:write. Après chaque action, lisez le nouvel ETag et vérifiez la valeur de pin.


Confirmations - décision du Client

La décision est une action métier, et non une modification classique de l'enregistrement. Avant de la prendre, la Confirmation doit être affectée à un Client. La requête doit provenir d'une clé représentant ce Client et contenir confirmations:decision:write. L'API vérifie également l'ETag actuel.

Pour confirmer une demande, utilisez ce payload :

{
  "confirmed": true,
  "remark": "Je confirme que la demande peut être réalisée."
}
curl --fail-with-body --silent --show-error \
  --request POST \
  --header "X-Codenica-Client-Id: $PUBLIC_API_DECISION_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_DECISION_CLIENT_SECRET" \
  --header "Content-Type: application/json" \
  --header "If-Match: {DECISION_ETAG}" \
  --header "Idempotency-Key: erp-confirmation-decision-0001" \
  --data '{"confirmed":true,"remark":"Je confirme que la demande peut être réalisée."}' \
  "$BASE_URL/api/v1/confirmations/{CONFIRMATION_ID}/decision"

Pour refuser, utilisez la même route avec false :

curl --fail-with-body --silent --show-error \
  --request POST \
  --header "X-Codenica-Client-Id: $PUBLIC_API_DECISION_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_DECISION_CLIENT_SECRET" \
  --header "Content-Type: application/json" \
  --header "If-Match: {DECISION_ETAG}" \
  --header "Idempotency-Key: erp-confirmation-decision-0002" \
  --data '{"confirmed":false,"remark":"Je refuse cette demande."}' \
  "$BASE_URL/api/v1/confirmations/{CONFIRMATION_ID}/decision"

Après une décision positive, le statut devient Confirmed et le système renseigne dateConfirmed, dateEnd et le commentaire. Après une décision négative, le statut devient Declined et le système renseigne dateDeclined, dateEnd et le commentaire. Ne renseignez pas ces champs manuellement.


Confirmations - Client et requester

La relation Client identifie le Client métier qui doit prendre la décision. Elle ne correspond pas à l'identifiant technique AppUser. Lisez cette affectation avec les relations d'objets ou depuis un enregistrement unique avec include=relationships.

L'API expose également une collection d'utilisateurs distincte, en lecture seule. Elle contient le requester automatique, c'est-à-dire l'utilisateur qui a créé la Confirmation :

curl --fail-with-body --silent --show-error \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  "$BASE_URL/api/v1/confirmations/{CONFIRMATION_ID}/user-relationships?relationshipType=requester&page=1&pageSize=20"
{
  "targetId": "{REQUESTER_USER_ID}",
  "targetDataSet": "users",
  "relationshipType": "requester",
  "displayName": "{REQUESTER_NAME}",
  "email": "{REQUESTER_EMAIL}",
  "role": "{REQUESTER_ROLE}"
}

Le requester est défini par le système. Ne définissez pas cette relation dans attributes et n'essayez pas de la modifier par les endpoints de relations d'objets. Sa lecture exige confirmations:users:read.


Confirmations - relations d'objets autorisées

Le catalogue actuel des cibles de relations des Confirmations comprend quatre collections :

Collection
itemType
Signification
assets
dynamique, par exemple computer
actif associé
clients
client
Client qui prend la décision
documents
document ou le type renvoyé par la cible
document lié à la demande
notes
note
note liée à la décision

Chaque cible doit exister, être visible pour l'utilisateur associé à la clé et correspondre à la liste relationshipTargets renvoyée par le schéma. Le catalogue des Confirmations ne permet pas de relations avec des collections arbitraires.


Confirmations - format des relations classiques et affectation du Client

Une relation vers un actif, un document ou une note possède un relationshipType. Exemple avec un document :

{
  "targetId": "{DOCUMENT_ID}",
  "targetDataSet": "documents",
  "targetItemType": "invoice",
  "relationshipType": "related"
}

L'affectation d'un Client est l'exception. Elle contient targetDataSet=clients et targetItemType=client, mais pas de relationshipType :

{
  "targetId": "{CLIENT_ID}",
  "targetDataSet": "clients",
  "targetItemType": "client"
}

Pour les actifs, lisez le type réel de l'objet et envoyez-le exactement dans targetItemType :

assets     - targetItemType: computer
documents  - targetItemType: invoice
notes      - targetItemType: note

Les valeurs ci-dessus sont des exemples. Le type correct peut être différent dans votre base.


Confirmations - ajouter, lire et supprimer une relation

Ajoutez une relation avec un POST contenant directement l'objet relation, sans enveloppe supplémentaire :

curl --fail-with-body --silent --show-error \
  --request POST \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  --header "Content-Type: application/json" \
  --header "If-Match: {CURRENT_ETAG}" \
  --header "Idempotency-Key: erp-confirmation-relation-add-0001" \
  --data '{"targetId":"{DOCUMENT_ID}","targetDataSet":"documents","targetItemType":"invoice","relationshipType":"related"}' \
  "$BASE_URL/api/v1/confirmations/{CONFIRMATION_ID}/relationships"

Lisez les relations sous forme de collection :

curl --fail-with-body --silent --show-error \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  "$BASE_URL/api/v1/confirmations/{CONFIRMATION_ID}/relationships?targetDataSet=documents&relationshipType=related&page=1&pageSize=50"

La suppression d'une relation exige l'ETag actuel de la Confirmation. Placez la collection et l'UUID de la cible dans le chemin, et transmettez le type de relation dans la requête :

curl --fail-with-body --silent --show-error \
  --request DELETE \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  --header "If-Match: {CURRENT_ETAG}" \
  --header "Idempotency-Key: erp-confirmation-relation-delete-0001" \
  "$BASE_URL/api/v1/confirmations/{CONFIRMATION_ID}/relationships/documents/{DOCUMENT_ID}?relationshipType=related"

L'ajout et la suppression renvoient une nouvelle version de l'enregistrement ou data=true. Après chaque modification réussie, lisez le nouvel ETag.


Confirmations - modifier plusieurs relations

Pour ajouter ou supprimer plusieurs relations dans une même requête, utilisez relationships:batch. Le body contient les tableaux add et remove :

{
  "add": [
    {
      "targetId": "{ASSET_ID}",
      "targetDataSet": "assets",
      "targetItemType": "computer",
      "relationshipType": "related"
    }
  ],
  "remove": [
    {
      "targetId": "{NOTE_ID}",
      "targetDataSet": "notes",
      "targetItemType": "note",
      "relationshipType": "related"
    }
  ]
}
curl --fail-with-body --silent --show-error \
  --request POST \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  --header "Content-Type: application/json" \
  --header "If-Match: {CURRENT_ETAG}" \
  --header "Idempotency-Key: erp-confirmation-relationships-batch-0001" \
  --data-binary @confirmation-relationships-batch.json \
  "$BASE_URL/api/v1/confirmations/{CONFIRMATION_ID}/relationships:batch"

La réponse contient les compteurs added, removed et skipped. La limite du batch de relations est fournie par le contexte, l'ETag actuel est obligatoire et la version de la Confirmation change. Pour affecter un Client, utilisez le format sans relationshipType.


Confirmations - liste et téléversement de fichiers

Commencez par lire les fichiers actuellement associés à la Confirmation :

curl --fail-with-body --silent --show-error \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  "$BASE_URL/api/v1/confirmations/{CONFIRMATION_ID}/files?page=1&pageSize=50"

Un élément de la liste contient notamment id, fileName, contentType, size, relationshipType, isMain et downloadUrl. Ajoutez un fichier avec multipart/form-data :

curl --fail-with-body --silent --show-error \
  --request POST \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  --header "If-Match: {CURRENT_ETAG}" \
  --header "Idempotency-Key: erp-confirmation-file-upload-0001" \
  --form "[email protected];type=application/pdf" \
  "$BASE_URL/api/v1/confirmations/{CONFIRMATION_ID}/files?relationshipType=decision-form"
{
  "data": {
    "id": "{FILE_ID}",
    "fileName": "formulaire-decision.pdf",
    "contentType": "application/pdf",
    "size": 48231,
    "relationshipType": "decision-form",
    "isMain": false,
    "downloadUrl": "/api/v1/confirmations/{CONFIRMATION_ID}/files/{FILE_ID}/content"
  }
}

Le téléversement exige confirmations:files:write, l'ETag actuel et une nouvelle clé d'idempotence. Lisez la limite de taille dans data.capabilities.limits.maxUploadBytes. L'API des Confirmations ne propose pas d'opération pour choisir un fichier principal - ne construisez pas une intégration qui attendrait un endpoint /main.


Confirmations - télécharger, rattacher et supprimer des fichiers

Téléchargez le contenu du fichier avec l'endpoint content et enregistrez-le en mode binaire :

curl --fail-with-body --silent --show-error \
  --output formulaire-decision-telecharge.pdf \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  "$BASE_URL/api/v1/confirmations/{CONFIRMATION_ID}/files/{FILE_ID}/content"

Si le fichier est déjà enregistré dans Codenica, rattachez-le à une deuxième Confirmation sans téléverser à nouveau son contenu :

curl --fail-with-body --silent --show-error \
  --request POST \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  --header "If-Match: {SECOND_CONFIRMATION_ETAG}" \
  --header "Idempotency-Key: erp-confirmation-file-attach-0001" \
  "$BASE_URL/api/v1/confirmations/{SECOND_CONFIRMATION_ID}/files/{FILE_ID}?relationshipType=reference"

Pour détacher un fichier d'une Confirmation ou supprimer sa dernière relation, utilisez la même route DELETE :

curl --fail-with-body --silent --show-error \
  --request DELETE \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  --header "If-Match: {CONFIRMATION_ETAG}" \
  --header "Idempotency-Key: erp-confirmation-file-delete-0001" \
  "$BASE_URL/api/v1/confirmations/{CONFIRMATION_ID}/files/{FILE_ID}"

Attach crée une relation vers un fichier existant. Si le fichier est toujours associé à la Confirmation source, le détacher d'un second enregistrement ne doit pas supprimer la relation source. Avant de supprimer la dernière relation, lisez la liste des fichiers et vérifiez l'élément sélectionné.


Confirmations - opérations batch

L'endpoint /api/v1/confirmations:batch permet de regrouper la création, la modification et la suppression d'enregistrements. Le format utilise un tableau items ainsi que des objets create et update distincts :

{
  "items": [
    {
      "operation": "create",
      "create": {
        "itemType": "confirmation",
        "attributes": {
          "customId": "ERP-BATCH-CONFIRMATION-A",
          "category": "Accès",
          "description": "Première Confirmation créée dans un batch."
        },
        "relationships": [
          {
            "targetId": "{CLIENT_ID}",
            "targetDataSet": "clients",
            "targetItemType": "client"
          }
        ]
      }
    },
    {
      "operation": "update",
      "id": "{EXISTING_ID}",
      "ifMatch": "{EXISTING_ETAG}",
      "update": {
        "attributes": {
          "description": "Description mise à jour dans un batch."
        }
      }
    },
    {
      "operation": "delete",
      "id": "{RECORD_TO_DELETE_ID}",
      "ifMatch": "{RECORD_TO_DELETE_ETAG}"
    }
  ]
}
curl --fail-with-body --silent --show-error \
  --request POST \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: erp-confirmations-batch-0001" \
  --data-binary @confirmations-batch.json \
  "$BASE_URL/api/v1/confirmations:batch"
{
  "data": {
    "items": [
      {
        "index": 0,
        "operation": "create",
        "status": 201,
        "id": "{CREATED_ID}",
        "data": { "meta": { "etag": "{CREATED_ETAG}" } }
      }
    ],
    "succeeded": 1,
    "failed": 0
  }
}

Chaque élément de modification ou de suppression a besoin de son propre ifMatch actuel. Un batch n'est pas une transaction globale. En cas de résultat partiel, l'API peut renvoyer 207 Multi-Status : analysez donc chaque élément séparément et ne répétez pas les opérations déjà réussies.


Confirmations - supprimer un enregistrement

Avant la suppression, relisez l'enregistrement, vérifiez l'UUID et l'ETag actuel, puis envoyez la requête avec une clé d'idempotence distincte :

curl --fail-with-body --silent --show-error \
  --request DELETE \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  --header "If-Match: {CURRENT_ETAG}" \
  --header "Idempotency-Key: erp-confirmation-delete-0001" \
  "$BASE_URL/api/v1/confirmations/{CONFIRMATION_ID}"

Une réponse réussie renvoie 200 OK et data=true. Après la suppression, vérifiez que l'UUID n'est plus disponible :

curl --fail-with-body --silent --show-error \
  --header "X-Codenica-Client-Id: $PUBLIC_API_CLIENT_ID" \
  --header "X-Codenica-Client-Secret: $PUBLIC_API_CLIENT_SECRET" \
  "$BASE_URL/api/v1/confirmations/{CONFIRMATION_ID}"

Le résultat attendu est 404 Not Found avec le code confirmation_not_found. Supprimer une Confirmation ne supprime pas automatiquement les documents, actifs ou notes associés.


Confirmations - erreurs, limites et séquence sûre

Les erreurs utilisent le format Problem Details. Journalisez status, code et requestId, mais jamais le Client Secret ni les en-têtes complets :

HTTP
Code
Réaction
400
validation_failed
Corrigez le body, le paramètre ou la valeur du champ.
401
authentication_required ou authentication_failed
Vérifiez l'adresse et les deux en-têtes.
403
confirmation_client_required
La décision doit être prise par le Client affecté à la Confirmation.
404
confirmation_not_found
L'enregistrement n'existe pas ou n'est pas visible.
409
confirmation_unique_constraint ou confirmation_concurrency_conflict
Relisez l'enregistrement, vérifiez l'ETag ou supprimez le doublon.
412 / 428
if_match_failed, if_match_required
Relisez l'ETag actuel et relancez l'opération de manière contrôlée.
422
confirmation_decision_rejected, confirmation_pin_rejected
Vérifiez l'état du processus, la clé du Client et les règles de l'opération.
429
rate_limit_exceeded
Appliquez un délai croissant et lisez Retry-After.

Lisez X-RateLimit-Limit et X-RateLimit-Remaining. Mettez en cache le schéma et les valeurs de champs, limitez la concurrence et appliquez un backoff après 429.

Une séquence sûre est la suivante : context, schema, choix du Client, liste ou lecture, création avec Idempotency-Key, conservation de l'UUID et de l'ETag, ajout des relations ou des fichiers, modification avec If-Match, épinglage, décision via /decision, lecture de vérification, puis suppression. Le même enchaînement peut être reproduit dans n8n en transmettant l'UUID, l'ETag et les clés d'idempotence entre les étapes.