Anatomie d'un message JSON
Un message Telebib2 en JSON tient en trois niveaux emboîtés : une enveloppe qui dit qui parle à qui, un ou plusieurs datablocks qui délimitent chacun une unité d'échange et à l'intérieur de chaque datablock le contenu métier : le message proprement dit. Rien de neuf sous le soleil : c'est le découpage qu'EDIFACT opère depuis toujours avec ses segments d'en-tête. Seule la syntaxe change.
L'enveloppe : qui parle à qui
L'enveloppe est décrite par messageEnvelope.202701.json. Elle ne contient aucune donnée métier : son rôle est de transporter. Quatre propriétés y sont obligatoires.
syntaxVersionNumber- vaut toujours1. C'est la version de la syntaxe Telebib2 JSON, pas celle de vos messages.senderIdentificationDetailetrecipientIdentificationDetail- l'adresse de domaine de chaque partie (35 caractères), éventuellement complétée d'une adresse utilisateur et d'un type codé.dataBlocks- un tableau, avec au minimum un élément.
Deux propriétés facultatives méritent d'être connues. groupType qualifie le lot : elle devient nécessaire quand l'enveloppe mélange des types de datablocks différents, ou quand votre correspondant l'exige pour son routage. Et metadata, qui est le seul endroit de tout le message où vous pouvez déposer ce que vous voulez - un identifiant de corrélation, un horodatage de votre bus applicatif. Le reste du message est strictement fermé.
{
"syntaxVersionNumber": 1,
"senderIdentificationDetail": {
"senderDomainAddress": "insurerA.telebib2.be",
"senderTypeCoded": "sendingCompany"
},
"recipientIdentificationDetail": {
"recipientDomainAddress": "insurerB.telebib2.be",
"recipientTypeCoded": "receivingCompany"
},
"dataBlocks": []
}
Les datablocks : une unité d'échange
Une enveloppe peut porter plusieurs datablocks : c'est ainsi qu'on envoie un lot (au même destinataire). Chaque datablock est autonome : son type, son action, sa référence, son contenu. Cinq propriétés y sont obligatoires : exchangeUnitType, exchangeUnitActionCoded, exchangeUnitTypeVersionNumber, exchangeUnitIssuingFormat et content.
Les deux premières situent le message : sa famille (contrat, sinistre, échange financier…) et l'action qu'il porte au sein de cette famille. exchangeUnitIssuingFormat vaut invariablement "json" . C'est ce qui distingue un message de la norme JSON d'un message EDIFACT.
Restent les références libres, senderExchangeUnitIdentifier et recipientExchangeUnitIdentifier (17 caractères). Elles ne sont pas obligatoires, mais ce sont elles que vous retrouverez dans l'accusé de réception : les renseigner vous évitera de rapprocher des messages à l'aveugle.
{
"exchangeUnitType": "contract_ExchangeUnit",
"exchangeUnitActionCoded":
"contractClaimsCertificateContractPart",
"exchangeUnitTypeVersionNumber": "1",
"exchangeUnitIssuingFormat": "json",
"senderExchangeUnitIdentifier": "M0151-2026-001",
"exchangeUnitIssueDateTime": "2026-08-31T09:15:00Z",
"content": {}
}
Le contenu : le message métier
Tout ce qui relève de l'assurance vit dans content. Et les deux premières propriétés de cet objet forment la carte d'identité du message : exchangeUnitBusinessContentDescription nomme le MIG, exchangeUnitBusinessContentDescriptionVersion donne sa version.
Ces deux propriétés sont la transposition directe des éléments de données X943 et X944 d'EDIFACT. Notez le type : le code est une chaîne, la version est un entier. C'est une source d'erreur classique en début d'implémentation.
"content": {
"exchangeUnitBusinessContentDescription": "M0151",
"exchangeUnitBusinessContentDescriptionVersion": 3,
"domain": "motor",
"mainRenewalDateInMonthDay": "06-30"
}
Comment le validateur descend la cascade
Les schémas s'appellent les uns les autres. Vous ne validez jamais un MIG directement : vous validez l'enveloppe et la chaîne se déroule toute seule.
La pièce intéressante est schemaRouter.json, qui fait deux choses distinctes. D'abord un anyOf qui n'accepte que les couples X943+X944 connus : un message annonçant un MIG inexistant, ou une version retirée du service, est rejeté immédiatement plutôt que validé « par défaut ». Ensuite une série de if/then qui aiguille le contenu vers le bon fichier de schéma.
Le routeur est aussi la seule pièce du registre qui change sans changer de nom : il est mis à jour à chaque mise en service d'une version de MIG. Si votre outillage met les schémas en cache, c'est ce fichier-là qu'il faut penser à recharger.
Ce que la structure impose — et ce qu'elle garantit
Les schémas Telebib2 sont fermés : unevaluatedProperties: false. Une propriété que le schéma ne prévoit pas n'est pas ignorée, elle provoque une erreur de validation. C'est délibéré. Dans un échange entre deux systèmes qui ne se parlent pas autrement que par ces messages, une faute de frappe silencieusement acceptée - assuredName au lieu de insuredName - coûte infiniment plus cher qu'un rejet immédiat et explicite.
En contrepartie, vous obtenez un message autoportant : le schéma seul suffit à décider s'il est valide, sans convention hors bande, sans documentation annexe, sans appel téléphonique.
Le message complet
Voici, assemblé, un message minimal valide - un certificat de sinistralité (M0151), réduit à ses propriétés obligatoires.
Et le voici en entier, tel qu'il est publié dans le registre — celui-ci est valide et se copie tel quel dans votre validateur.
{
"syntaxVersionNumber": 1,
"senderIdentificationDetail": {
"senderDomainAddress": "insurerA.telebib2.be"
},
"recipientIdentificationDetail": {
"recipientDomainAddress": "insurerB.telebib2.be"
},
"dataBlocks": [
{
"exchangeUnitType": "contract_ExchangeUnit",
"exchangeUnitActionCoded": "contractClaimsCertificateContractPart",
"exchangeUnitTypeVersionNumber": "1",
"exchangeUnitIssuingFormat": "json",
"content": {
"exchangeUnitBusinessContentDescription": "M0151",
"exchangeUnitBusinessContentDescriptionVersion": 3,
"domain": "motor",
"mainRenewalDateInMonthDay": "06-30",
"policyReference": {
"referenceContent": "POL-2018-4477821"
},
"insurer": {
"partyIdentification": [
{
"partyIdentifier": "0451",
"codeListIdentifier": "valueSpecificToTheFsma"
}
],
"officialName": {
"lastName": "Assurances Continentales SA"
},
"officialAddress": {
"streetName": "Avenue des Arts",
"houseNumber": "44",
"postalCode": "1000",
"cityName": "Bruxelles",
"countryCode": "B"
}
},
"mainPolicyHolder": {
"officialName": {
"lastName": "Dubois",
"firstName": [
"Jean"
]
},
"officialAddress": {
"streetName": "Rue de la Loi",
"houseNumber": "16",
"postalCode": "1040",
"cityName": "Etterbeek",
"countryCode": "B"
}
},
"motorisedVehicle": {
"objectQualifier": "tractorVehicle",
"numberPlate": {
"referenceContent": "1-ABC-123"
},
"divVehicleTypeCode": "AC",
"sasInsuredVehicleUse": "mixedUse",
"motorThirdPartyLiabilityGuarantee": {
"guaranteeType": "clMotor",
"inceptionDate": "2018-07-01",
"periodEndDate": "2026-06-30",
"appliedBonusMalusGrade": "_11"
}
}
}
}
]
}
Chaque message publié dispose de deux payloads de référence dans le registre : une variante min, celle que vous venez de lire et une variante full, qui exerce toutes les propriétés du schéma. Ce sont d'excellents points de départ pour vos premiers tests et d'excellents cas de non-régression par la suite.