Documentation · PMS interface

API Reference

Environnements, connexion, objets ARI et réservation, erreurs, limites, fiabilité et API d'administration.

Staginghttps://staging.bridgchannel.appv1.0 · 2026-09-11<?Label BRIDG|DOC|1.0|NEW?>

This technical documentation is available in French only.

Ce document décrit ce qui est commun aux deux modèles (XML et JSON) : environnements, connexion, objets de données, erreurs, limites, fiabilité et API d'administration. Les détails de transport sont dans xml/README.md et json/README.md.

Environnements et versionnement

Environnement URL de base
Staging https://staging.bridgchannel.app

L'URL de production est communiquée par Bridg_ à la mise en service, une fois la certification passée. Les intégrations se développent et se certifient sur le staging.

L'API est versionnée dans le chemin : /api/pms/v1/. Les évolutions compatibles (nouveau champ optionnel, nouveau code d'erreur) ne changent pas la version. Un changement incompatible donnerait un nouveau préfixe /v2/.

Toutes les URL d'ingestion ont la forme :

{base}/api/pms/v1/connections/{connectionId}/{ressource}

La connexion

Une connexion relie un établissement Bridg_ à un PMS. Il y a au plus une connexion par établissement. Elle est créée par le propriétaire de l'établissement (ou par Bridg_) dans le tableau de bord, menu Interface PMS.

Fields

Champ Type Description
connectionId string Identifiant de la connexion. Présent dans toutes les URL.
adapterId string Dialecte, figé à la création : opera-oxi (XML), bridg-hms (JSON webhook), winner (JSON feed).
clientToken string Identifiant public de l'appelant, forme pms_ + 32 caractères hexadécimaux. Non secret à lui seul.
secret string Secret partagé, 64 caractères hexadécimaux. Affiché une seule fois à la création ; stocké chiffré, jamais relisible.
externalPropertyCode string Code de l'établissement chez le PMS. En XML, c'est le propertyName de l'enveloppe et le resortId des RESULT. Ne peut contenir ni | ni ?.
rateEndDateInclusive boolean XML uniquement. RateDetail/endDate est-elle inclusive ? Défaut true. À vérifier en recette.
ariHorizonDays integer Horizon ARI attendu, défaut 365. Informatif : Bridg_ ne rejette pas un item au-delà.
status enum PENDING, ACTIVE, PAUSED, DISABLED.

Statuts

Statut Messages entrants (ARI, réservations) Réservations sortantes Écrans ARI de Bridg_
PENDING acceptés non émises modifiables
ACTIVE acceptés émises lecture seule (le PMS est seul maître)
PAUSED refusés — 403 CONNECTION_INACTIVE non émises modifiables
DISABLED refusés — 403 CONNECTION_INACTIVE non émises modifiables

L'activation est un geste explicite du propriétaire. Régénérer les identifiants invalide immédiatement l'ancien couple clientToken / secret.

Correspondance des codes (mapping)

Bridg_ ne crée jamais de type de chambre ni de plan tarifaire à partir d'un message. Chaque code du PMS doit être associé à un objet Bridg_ avant le premier message.

Kind Code PMS Objet Bridg_ Utilisé par
UNIT_TYPE code de type de chambre (DLX, 1KN…) type de chambre disponibilité, prix, restrictions par type, réservations
RATE_PLAN code tarifaire (BAR1, RACK…) tarif prix, restrictions, réservations

Un code non mappé est refusé item par item (UNMAPPED_UNIT_TYPE, UNMAPPED_RATE_PLAN) ; les autres items du même message sont appliqués. Le mapping se fait dans l'écran Interface PMS (onglet Correspondance des codes) ou par l'API d'administration.

Objets communs

ARI item

Quel que soit le format, un message ARI est traduit en items indépendants. Un item porte une seule nature (disponibilité, prix ou restrictions) sur une plage de nuits. En JSON l'item est envoyé tel quel ; en XML il est produit par la traduction des messages Fidelio.

Champ Type Requis Description
unitTypeCode string pour availability et prices Code PMS du type de chambre (mapping UNIT_TYPE). Optionnel pour une restriction : sans lui, la restriction porte sur le tarif seul.
ratePlanCode string pour prices et restrictions Code PMS du plan tarifaire (mapping RATE_PLAN).
from date AAAA-MM-JJ oui Première nuit, incluse.
to date AAAA-MM-JJ oui Borne de fin, exclue (to > from). from=2026-10-01, to=2026-10-04 couvre les nuits du 1, 2 et 3.
availability integer ≥ 0 une des trois natures Nombre de chambres vendables du type sur chaque nuit de la plage.
overbookingAllowance integer ≥ 0 non Marge de survente autorisée, stockée à part, jamais additionnée à la disponibilité.
prices object une des trois natures { currency, byOccupancy: [ { guests, gross?, net? } ] }.
restrictions object une des trois natures { closed?, closedToArrival?, closedToDeparture?, minLos?, maxLos? }.

Règles d'application :

  • Disponibilité — le chiffre du PMS fait foi. S'il dépasse l'inventaire paramétré dans Bridg_, l'inventaire du type de chambre est relevé à ce niveau.
  • Prix — l'occupation 2 est obligatoire (prix de référence du tarif ; les autres occupations dérivent des modificateurs du tarif Bridg_). Bridg_ retient gross si le tarif est paramétré TTC, net s'il est HT. Le prix doit être > 0. Une baisse de plus de 50 % par rapport au dernier prix connu sur une date est refusée (PRICE_DROP_REJECTED) — tout l'item est rejeté, rien n'est écrit. La devise est celle de l'établissement ; Bridg_ ne convertit pas.
  • Restrictionsseuls les champs fournis sont écrits : un item minLos seul ne rouvre pas un tarif fermé et n'efface pas un CTA. Sans unitTypeCode la restriction porte sur le tarif ; avec, elle porte sur tarif × type et la vue tarif est recalculée comme l'agrégat des types connus (fermé seulement si tous les types sont fermés ; LOS la moins restrictive).
  • Chaque item est appliqué indépendamment ; l'accusé détaille le résultat par item.
  • Après application, Bridg_ relaie la donnée vers les OTA connectés.

Réservation (booking)

Les deux modèles véhiculent la même structure, dans les deux sens. En JSON elle est envoyée telle quelle (camelCase) ; en XML elle est traduite depuis/vers <Reservation> Fidelio ; en webhook JSON elle est envoyée en PascalCase.

Champ Type Description
cmRef string Référence Bridg_ (numéro de réservation). Clé de rapprochement Bridg_ ↔ PMS.
externalRef string Référence chez l'OTA (vide pour une réservation directe). En entrée : référence du PMS.
channel string BOOKING_COM, EXPEDIA, DIRECT… ; PMS pour une réservation venue du PMS.
revision integer Strictement croissant par réservation. Une révision ≤ la dernière traitée est ignorée.
currency string ISO 4217.
totalAmount { gross, net } Montant de la chambre seule. Aujourd'hui gross = net : Bridg_ n'a pas de ventilation de taxes sur les réservations.
paymentType enum PREPAID (payée), ON_SITE (à régler sur place), GUARANTEED (réservé).
paymentCardToken string Jeton PSP uniquement — jamais de numéro de carte.
booker guest { lastName, firstName?, email?, phone? } — celui qui réserve.
customer guest Optionnel, l'occupant s'il diffère.
reservations[] line[] Une ligne par chambre.

Ligne de réservation (reservations[]) :

Champ Type Description
lineCode string Identifiant de ligne, stable à travers les révisions (01, 02…).
state enum CONFIRMED, CANCELLED.
unitTypeCode string Code PMS du type de chambre.
ratePlanCode string Code PMS du plan tarifaire.
from date Arrivée.
to date Départ, exclusif.
occupancy[] { bucket, count }[] bucket = ADULT ou CHILD.
nights[] { date, gross, net }[] Une entrée par nuit, datée explicitement. La somme vaut le total de la ligne.
guests[] guest[] Optionnel.

Règles :

  • Une réservation de 2 chambres identiques = 2 lignes (01, 02).
  • Modification = état complet : la réservation est renvoyée entière ; toute ligne absente est considérée annulée.
  • Annulation : toutes les lignes en CANCELLED (XML), ou message d'annulation dédié (JSON).
  • Bridg_ n'émet jamais vers le PMS une réservation qui vient de ce PMS (anti-boucle).
  • Une réservation entrante est enregistrée avec la source PMS et la référence externe pms:<référence> ; elle ne repart ni vers les OTA ni vers le PMS, et ne modifie pas la disponibilité (seul le flux ARI le fait).

Accusé de traitement (result)

Champ Description
identifiant du message d'origine messageId (JSON) ou transactionId (XML)
success true / false
détail par item en JSON (results[]), texte libre en XML (resultMessage)

Erreurs

Hors accusé XML, toute erreur HTTP a le format :

JSON
{ "error": "Type d'unité \"SUP\" non mappé sur cette connexion", "code": "UNMAPPED_UNIT_TYPE" }
HTTP code Signification Action côté PMS
400 VALIDATION_ERROR, MISSING_LABEL, MALFORMED_LABEL, INVALID_TIMESPAN, INVALID_DATE_RANGE, MISSING_REFERENCE, MISSING_AMOUNT, DUPLICATE_NIGHT, NEGATIVE_COUNT message illisible ou incomplet corriger, ne pas réémettre tel quel
401 UNAUTHORIZED identifiants, clé d'URL ou signature invalides vérifier clientToken / secret / signature
403 CONNECTION_INACTIVE connexion en pause ou désactivée contacter l'hôtel
404 NOT_FOUND connectionId inconnu vérifier l'URL
405 INGRESS_NOT_SUPPORTED flux non prévu pour ce dialecte vérifier le modèle utilisé
422 UNSUPPORTED_MESSAGE_TYPE, UNSUPPORTED_RESTRICTION, UNSUPPORTED_ROOM_CLASS, UNSUPPORTED_RATE_CATEGORY, UNSUPPORTED_SCOPE, UNSUPPORTED_BLOCK_RESTRICTION, UNSUPPORTED_TIME_UNIT, UNSUPPORTED_TIERED_RATE, UNSUPPORTED_WEEKEND_RATE, UNSUPPORTED_RATE_MESSAGE, RESTRICTION_GRANULARITY_MISMATCH, UNMAPPED_UNIT_TYPE, NO_LINES refus déterministe corriger la donnée ou le mapping ; le rejeu donnera le même refus
429 RATE_LIMIT_EXCEEDED trop de requêtes ralentir, réessayer
500 INGEST_FAILED, INTERNAL_ERROR échec transitoire, message conservé réémettre après un délai

Codes par item ARI (dans results[] en JSON, dans resultMessage en XML) : UNMAPPED_UNIT_TYPE, UNMAPPED_RATE_PLAN, INVALID_DATE_RANGE, PRICE_DROP_REJECTED, VALIDATION_ERROR, INTERNAL_ERROR.

En XML, un refus déterministe est signalé par un RESULT d'échec mis en file (réponse HTTP 200), jamais par un 4xx — voir xml/README.md.

Limites

Limite Valeur
Transport HTTPS uniquement, TLS 1.2 ou plus
Taille maximale d'un message entrant 5 Mo
Débit 600 requêtes / minute / adresse IP sur /api/pms/v1/connections/*429 RATE_LIMIT_EXCEEDED
Compression non supportée en entrée : corps non compressé (OXI : zipData=N)
Encodage UTF-8
Plage de dates d'un item 1 à 3 700 nuits
Délai de réponse de Bridg_ quelques centaines de ms ; timeout client conseillé : 60 s

Fiabilité

  • Écriture avant traitement. Tout message entrant est persisté tel quel (octets bruts) avant d'être appliqué. Un message reçu est appliqué ou visible en erreur, jamais perdu.
  • Déduplication. Un identifiant de message déjà traité renvoie l'accusé mémorisé (200) sans retraiter. Reçu à nouveau pendant son traitement : 202 (en attente, ne pas retraiter).
  • Reprise. Un échec transitoire (base indisponible…) répond 500 ; le message reste en inbox et est rejoué automatiquement (5 tentatives, toutes les 30 s). Le PMS doit réémettre sur 500 ; les deux filets se cumulent sans doublon.
  • Échec déterministe (code non mappé, message illisible) : jamais rejoué. Réémettre le même message donnera le même refus tant que la cause n'est pas corrigée. Les octets sont conservés quand même — y compris pour un message que Bridg_ n'a pas su traduire — dès lors que l'enveloppe porte un identifiant : le message reste auditable et rejouable une fois la cause corrigée, au lieu de disparaître avec son refus.
  • Réservations sortantes. File durable FIFO par connexion, ordre garanti par réservation (le MODIFY d'une réservation n'est jamais servi avant son CREATE). Échec transitoire : rejeu avec backoff exponentiel (30 s, 1 min, 2 min… plafonné à 30 min, 8 tentatives). Refus métier : dead-letter visible dans l'écran Interface PMS, rejouable à la main après correction.

Rétention

Donnée Durée
Messages entrants traités (inbox) 30 jours
Émissions sortantes livrées (outbox DONE) 7 jours
Émissions en échec (FAILED) et messages en erreur conservés jusqu'à rejeu ou suppression de la connexion

API d'administration

Base : {base}/api/pms/v1/admin. Authentification par session Bridg_ (JWT). Réservée au propriétaire de l'établissement et au super-administrateur. C'est l'API derrière l'écran Interface PMS ; un intégrateur n'a normalement pas à l'appeler.

Méthode Chemin Rôle
POST /connections Crée la connexion (propertyId, name, adapterId, externalPropertyCode). Renvoie clientToken + secret une seule fois.
GET /connections/by-property/:propertyId La connexion de l'établissement (mappings inclus, sans secret).
PATCH /connections/:id/status { status: PENDING | ACTIVE | PAUSED | DISABLED }.
PATCH /connections/:id/settings name, externalPropertyCode, rateEndDateInclusive, ariHorizonDays.
POST /connections/:id/credentials Régénère clientToken + secret ; les anciens sont invalidés.
PUT /connections/:id/mappings { kind: UNIT_TYPE | RATE_PLAN, bridgId, externalCode }. Un élément Bridg ne porte qu'un code : s'il en avait un, il est remplacé (replacedCode dans la réponse). Un code déjà associé à un autre élément est refusé (409 CODE_ALREADY_USED), jamais déplacé.
DELETE /connections/:id/mappings { kind, externalCode }.
PUT /connections/:id/outbound JSON webhook : pmsBaseUrl, clientToken, accessToken de l'API du PMS.
GET /connections/:id/configuration JSON webhook : découverte du catalogue du PMS (UnitTypes, RatePlans).
GET /connections/:id/overview Vue d'ensemble de la synchronisation : compteurs entrants/sortants par statut, dernières activités, codes reçus sans mapping (unmapped.inbound) et éléments Bridg sans code rencontrés à l'émission (unmapped.outbound).
GET /connections/:id/inbox Journal des messages entrants. Filtres status (RECEIVED, PROCESSED, FAILED), kind (ARI, RESERVATION), limit (≤ 200). Chaque message ARI porte un summary (items rejetés) et ses unmappedCodes.
GET /connections/:id/inbox/:messageId/raw Le message entrant tel que reçu (octets exacts).
GET /connections/:id/reservations Journal des émissions sortantes. Filtre status (PENDING, SENT, DONE, FAILED).
POST /reservations/:outboxId/retry Rejoue une émission FAILED après correction (mapping ajouté…).
DELETE /connections/:id Supprime la connexion, ses mappings et ses journaux.