Aller au contenu

Conventions de payload v2

En bref

Une seule enveloppe pour tous les succès, un seul format pour toutes les erreurs, une seule façon de cibler un dossier Sage. Ces trois règles sont le contrat stable du protocole v2 : elles ne dépendent d'aucune opération particulière et ne changent pas sans préavis.

Ce sont les règles à implémenter une fois dans votre client. Le détail opération par opération est dans les groupes.

Enveloppe des réponses en succès

Toute réponse 2xx est emballée par le connecteur ; aucun contrôleur ne construit l'enveloppe à la main, la forme est donc rigoureusement identique partout.

{
  "success": true,
  "data": {},
  "meta": {
    "correlationId": "8f2a…",
    "dossiers": ["DEMO"],
    "pagination": null,
    "durationMs": 128,
    "warnings": null
  }
}
Champ de meta Type Contenu
correlationId string identifiant de corrélation, égal à l'en-tête X-Correlation-Id de la réponse
dossiers string[] dossiers Sage réellement interrogés ; null pour les opérations mono-objet
pagination objet { limit, offset, total } — présent dans le contrat, pas encore alimenté
durationMs entier durée de traitement côté connecteur
warnings tableau dégradations non bloquantes : { code, message }pas encore alimenté

warnings remplacera les échecs silencieux de l'ancien protocole : un dossier écarté, un indicateur partiel, y seront signalés sans faire échouer l'appel.

PascalCase métier, camelCase sur le fil

La règle prête à confusion, elle mérite d'être dite précisément :

  • côté connecteur, les propriétés des DTO sont déclarées en PascalCase (Reference, CorrelationId) — c'est la convention du code métier ;
  • sur le fil, le sérialiseur les expose en camelCase (reference, correlationId). La convention est épinglée explicitement dans la configuration du connecteur, elle ne dépend pas d'un réglage d'environnement.

Ce choix est aligné sur les erreurs : le format ProblemDetails impose des champs en minuscules, et forcer le PascalCase aurait cassé cette conformité.

Deux exceptions, assumées

  • POST /v2/query et POST /v2/search : le contenu de data est produit par un sérialiseur interne et ses clés sont les noms de colonnes SQL Sage bruts (CT_Num, AR_Ref…), non transformés — c'est un retour fidèle du schéma Sage. Seule l'enveloppe qui les entoure est en camelCase.
  • Le corps de POST /v2/query suit le modèle hérité, en minuscules et snake_case (model, columns, where, order_by, target_base, limit…).

Corps des requêtes

Écritures par DTO

Les écritures d'objets métier (/v2/tiers, /v2/articles, /v2/entites/{entite}, et toutes les routes /v2/<objet>) attendent un JSON partiel du DTO.

Règle Conséquence pour l'intégrateur
Reconnaissance par nom de propriété DTO, insensible à la casse {"reference": …} et {"Reference": …} sont équivalents
Les noms de colonnes SQL Sage ne sont pas reconnus {"AR_Ref": …} est ignoré : utilisez reference
Liaison partielle sûre seules les propriétés présentes dans le corps sont marquées comme modifiées ; les autres champs Sage ne sont pas écrasés
Aller-retour garanti un objet lu en camelCase peut être réécrit tel quel

C'est le point le plus important pour éviter les dégâts : n'envoyez que les champs que vous voulez modifier. Envoyer un objet complet relu puis modifié fonctionne aussi, mais réécrit tout.

Modèles hérités

Route Modèle attendu
POST /v2/query champs en minuscules / snake_case : model, alias, columns, columns_array, where, join, order_by, aggregate, computed_columns, limit, offset, unfilter, parameters, target_base, mediaSize, escapeDate, sqlQuery
POST /v2/search models, searchTerm, limit

La liaison est insensible à la casse, ce qui rend ces modèles tolérants. Ils sont partagés avec la surface historique : leur casse n'est pas alignée sur le reste de la v2, c'est une dette assumée jusqu'au retrait de celle-ci.

Drapeau des écritures

Les écritures v2 (POST, PUT, DELETE) sont derrière un drapeau du connecteur (AutoriserEcrituresV2). Tant qu'il n'est pas activé, toute écriture répond 503 avec le code SAGE.COM.UNAVAILABLE. Un objet exposé en lecture seule par la couche d'interopérabilité répond 409 (SAGE.READONLY).

Paramètres transverses

Paramètre Rôle Détail
targets dossier(s) Sage cible Forme canonique v2, séparateur virgule : ?targets=DEMO,DEMO2. Sans valeur, tous les dossiers autorisés. Alias hérités acceptés : target, target_base, base, bases (séparateurs , ou \|). Toujours filtré par les autorisations de l'utilisateur.
limit nombre maximum de lignes 0 = illimité
offset décalage pagination, à combiner avec limit

Ils sont résolus au même endroit pour toute l'API, et honorés par /v2/query, /v2/search, les indicateurs, la balance, le cadencier, les tarifs, et les listes d'objets (GET /v2/<objet>), dont le résultat est alors indexé par dossier avec meta.dossiers renseigné.

Écriture = un seul dossier

Une écriture doit viser un dossier unique. Plusieurs valeurs dans targets renvoient DOSSIER.AMBIGUOUS (400) ; aucune valeur alors que l'utilisateur a plusieurs dossiers autorisés renvoie DOSSIER.REQUIRED (400).

Erreurs

Format

Une réponse ≥ 400 ne passe pas par l'enveloppe. Elle sort en application/problem+json (ProblemDetails, RFC 9457), avec deux extensions SenSaaS : code et correlationId.

{
  "type": "https://sensaas.fr/errors/sage-readonly",
  "title": "Objet en lecture seule",
  "status": 409,
  "detail": "…",
  "instance": "/v2/tierstype",
  "code": "SAGE.READONLY",
  "correlationId": "8f2a…"
}

Les erreurs venant d'un processus métier Sage portent en plus une extension sageDetail : le message renvoyé par Sage lui-même (par exemple « L'article X existe déjà ! »).

Aucune trace d'exécution n'est exposée ; sur une erreur 5xx le détail est masqué et ne se retrouve que dans les journaux du connecteur, repérable par le correlationId.

Branchez-vous sur code, pas sur title

title et detail sont des textes destinés à l'humain et peuvent évoluer. code appartient à une taxonomie stable : un code peut être ajouté, jamais renommé ni supprimé.

Taxonomie CodesErreur

Code Situation
AUTH.INVALID_CREDENTIALS identifiants refusés
AUTH.TOKEN_EXPIRED jeton expiré : renouveler par POST /v2/auth/refresh-token
AUTH.FORBIDDEN action interdite à cet utilisateur
Code Situation
VALIDATION.MODEL corps absent, vide ou invalide (400)
VALIDATION.PARAMETER paramètre de requête invalide
Code Situation
DOSSIER.UNKNOWN dossier inexistant
DOSSIER.NOT_AUTHORIZED dossier non autorisé à l'utilisateur (403)
DOSSIER.AMBIGUOUS plusieurs dossiers alors qu'un seul est attendu (400)
DOSSIER.REQUIRED écriture sans cible explicite alors que plusieurs dossiers sont autorisés (400)
DOSSIER.IGNORED cible écartée parmi des cibles valides — avertissement, pas une erreur
Code Situation
SAGE.NOT_FOUND référence, pièce ou clé introuvable (404)
SAGE.LOCK.RECORD enregistrement verrouillé (409)
SAGE.LOCK.CONTROLLER contrôleur Sage verrouillé
SAGE.COM.PROCESS échec d'un processus métier : transformation, lettrage, attribution de lots (422)
SAGE.COM.UNAVAILABLE Sage injoignable, ou écritures v2 désactivées (503)
SAGE.READONLY écriture sur un objet exposé en lecture seule (409)
Code Situation
LICENCE.EXPIRED licence du connecteur expirée
LICENCE.QUOTA quota de licence atteint
QUERY.INVALID requête /v2/query invalide
QUERY.FORBIDDEN requête interdite par les filtres
INTERNAL erreur non prévue ; le détail est dans les journaux, repérable par correlationId

Les URI du champ type sont construites sur la base https://sensaas.fr/errors/.

SageErreur, côté connecteur

Les erreurs métier remontées par la passerelle Sage voyagent dans une exception dédiée qui porte déjà son code de taxonomie et son statut HTTP. Le gestionnaire d'exceptions global la traduit directement en ProblemDetails. Concrètement, pour l'intégrateur : le statut HTTP et le code sont décidés au plus près de Sage, ils sont donc fiables et stables d'une version à l'autre.

Fabrique Code Statut
Introuvable SAGE.NOT_FOUND 404
Verrou d'enregistrement SAGE.LOCK.RECORD 409
Processus métier en échec SAGE.COM.PROCESS 422 (+ extension sageDetail)
Sage indisponible SAGE.COM.UNAVAILABLE 503
Lecture seule SAGE.READONLY 409
Dossier non autorisé DOSSIER.NOT_AUTHORIZED 403
Dossier ambigu DOSSIER.AMBIGUOUS 400
Dossier requis DOSSIER.REQUIRED 400

Deux voies d'accès aux objets métier

L'API v2 offre deux chemins complémentaires vers la même surface Sage.

Un contrôleur par objet métier, rangé par catégorie et étiqueté Catégorie.Objet — c'est ce qui donne les groupes de cette documentation (Catalogue.Article, Tiers.TiersBanque, Comptabilite.Journal…).

Routes : GET | POST | PUT | DELETE /v2/<objet>, plus POST /v2/<objet>/save, POST /v2/<objet>/recherche et GET | POST /v2/<objet>/count.

C'est la voie privilégiée : routes stables, clé dans l'URL pour les objets majeurs (/v2/articles/{reference}, /v2/tiers/clients/{ctNum}), DTO typé.

Repli universel pour la longue traîne et la découverte.

Route Rôle
GET /v2/entites catalogue des objets accessibles — aucun accès à Sage, idéal pour explorer
GET /v2/entites/{entite}/{cle} lecture par clé, pour les objets qui l'exposent (Article, Tiers client et fournisseur, Document achat et vente) ; sinon 400, passer par /v2/query
POST /v2/entites/{entite} création ou mise à jour, derrière le drapeau des écritures

Un objet en lecture seule renvoie 409 à l'écriture.

Voir aussi