التوثيق · واجهة PMS

API Reference XML

URL unique, authentification, enveloppe <?Label?>, envoi et récupération des messages, accusés RESULT.

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

هذا التوثيق التقني متاح باللغة الفرنسية فقط.

Le modèle XML s'adresse aux PMS installés chez l'hôtel. Il parle le dialecte XML Fidelio d'Oracle OPERA (OXI) et repose sur un principe simple : toutes les connexions partent de l'hôtel. Bridg_ n'appelle jamais le PMS ; le PMS pousse ses messages vers Bridg_ et vient chercher ceux de Bridg_. Aucune adresse publique ni ouverture de pare-feu n'est nécessaire côté hôtel.

Identifiant d'adaptateur : opera-oxi. Cible validée : OPERA 5 on-premise avec OXI (module servlet) — voir Paramétrage Oracle OPERA / OXI. Tout PMS capable d'émettre et de lire ce dialecte peut utiliser ce modèle.

Pages du modèle XML :

Topologie

                         POST …/messages?key=<secret>   (le PMS envoie : ARI, réservations, RESULT, MessageRequest)
   PMS (OXI) ────────────────────────────────────────────▶  Bridg_
   PMS (OXI) ◀────────────────────────────────────────────  Bridg_
                         GET  …/messages?key=<secret>    (le PMS vient chercher : réservations OTA/directes, RESULT)

Une seule URL à configurer dans le PMS, pour l'envoi comme pour la réception :

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

Authentification

Deux schémas sont acceptés sur chaque appel ; le premier est recommandé pour OXI, dont l'écran de configuration HTTP n'a pas de champ d'identifiants.

Schéma Comment Exemple
Clé dans l'URL (recommandé) paramètre de query key=<secret> …/messages?key=9f1e…
HTTP Basic Authorization: Basic base64(clientToken:secret) user = pms_3f9c…, password = secret
  • Si key est présent dans l'URL, il est seul évalué.
  • OXI ajoute ses propres paramètres à l'URL configurée (&propertyName=<code>&zipData=N) ; ils sont acceptés et ignorés. zipData doit rester à N (pas de compression).
  • Réponse 401 UNAUTHORIZED si la clé, l'identifiant ou le mot de passe est faux ; 404 si le connectionId est inconnu ; 403 CONNECTION_INACTIVE si la connexion est en pause.

L'enveloppe <?Label ?>

Tout message, dans les deux sens, commence par la déclaration XML puis l'instruction de traitement Label, qui sert au routage :

XML
<?xml version="1.0" encoding="UTF-8"?>
<?Label ATLALG|RTAV|2841178|NEW?>
Champ Position Description
propertyName 1 Code de l'établissement chez le PMS (externalPropertyCode de la connexion). Bridg_ le renvoie tel quel dans ses RESULT.
messageType 2 Type de message : RTAV, RATE, RAVL, RESTRICTION, RESERVATION, RESULT, MESSAGEREQUEST
transactionId 3 Identifiant du message chez l'émetteur. Entier de 1 à 999999999 pour les messages servis par Bridg_ ; recommandé aussi pour ceux du PMS. C'est la clé de déduplication et de corrélation des RESULT.
status 4 NEW pour un message ordinaire ; SUCCESS ou FAILED pour un RESULT.

Un message sans Label est refusé 400 MISSING_LABEL ; un Label à moins de 4 champs, 400 MALFORMED_LABEL. Aucun champ ne peut contenir | ni ?.

Types de message

messageType Sens Contenu Support
RTAV PMS → Bridg_ disponibilité par type de chambre et par nuit détail
RATE PMS → Bridg_ prix par plan tarifaire (DETAIL, HEADERWITHDETAIL) ; un HEADER est acquitté sans effet détail
RAVL PMS → Bridg_ restrictions par code tarifaire détail
RESTRICTION PMS → Bridg_ restrictions par tarif × type de chambre détail
RESERVATION PMS → Bridg_ réservation créée, modifiée ou annulée dans le PMS détail
RESERVATION Bridg_ → PMS réservation OTA ou directe (servie par GET) détail
RESULT les deux sens accusé de traitement détail
MESSAGEREQUEST PMS → Bridg_ redemande d'une RESERVATION perdue ✅ (type RESERVATION seulement)
RAVR PMS → Bridg_ restrictions par type de chambre RESULT FAILED RESTRICTION_GRANULARITY_MISMATCH — utiliser RAVL
INVENTORY, ALLOTMENT, HURDLE PMS → Bridg_ hors-service et limites de vente, allotements, hurdles RESULT FAILED UNSUPPORTED_MESSAGE_TYPE
PROFILE, STAY, PACKAGES, autres PMS → Bridg_ RESULT FAILED UNSUPPORTED_MESSAGE_TYPE

Un message d'un type non supporté est acquitté par un RESULT d'échec (réponse HTTP 200), jamais par un 4xx : le PMS peut ainsi continuer à envoyer ce type sans bloquer sa file, et l'hôtelier voit le refus dans le journal.

Envoyer un message

Request

POST{base}/api/pms/v1/connections/{connectionId}/messages?key={secret}
Content-Type: text/xml; charset=UTF-8
XML
<?xml version="1.0" encoding="UTF-8"?>
<?Label ATLALG|RTAV|2841178|NEW?>
<RtavMessage xmlns="rtav.fidelio.4.0">
  <HotelReference hotelCode="ATLALG"/>
  <DailyInventories>
    <DailyInventory datum="2026-10-10">
      <RoomTypeInventories>
        <RoomTypeInventory roomType="DLX" physicalRooms="20" outOfOrder="1" available="12" roomTypeOverbook="2"/>
      </RoomTypeInventories>
    </DailyInventory>
  </DailyInventories>
</RtavMessage>
curl
curl -X POST "https://staging.bridgchannel.app/api/pms/v1/connections/$CONNECTION_ID/messages?key=$SECRET" \
  -H "Content-Type: text/xml; charset=UTF-8" \
  --data-binary @rtav.xml

Success Response

200 OK — le message est reçu et persisté. Le verdict de traitement est un RESULT mis en file, à récupérer par GET. Le corps de la réponse contient, à titre indicatif, le même RESULT (text/xml) pour un message ARI, ou un objet JSON pour les autres types ; OXI n'en lit pas le contenu.

XML
<?xml version="1.0" encoding="UTF-8"?>
<?Label ATLALG|RESULT|2841178|SUCCESS?>
<RESULT xmlns="result.fidelio.4.0" success="SUCCESS" timeStamp="2026-09-11T10:39:18.895">
  <resortId>ATLALG</resortId>
  <resultMessage>Successfully applied in Bridg Channel Manager</resultMessage>
</RESULT>

200 OK avec verdict négatif en file (type non supporté, code non mappé, message illisible mais enveloppe lisible) :

JSON
{ "accepted": true, "verdictQueued": true }

202 Accepted — même transactionId reçu à nouveau pendant son traitement ; ne pas réémettre.

Error Response

400 Bad Request — enveloppe absente ou malformée (aucune corrélation possible) :

JSON
{ "error": "Instruction <?Label ...?> absente — enveloppe OXI obligatoire", "code": "MISSING_LABEL" }

401 Unauthorized · 403 Forbidden (CONNECTION_INACTIVE) · 404 Not Found · 429 Too Many Requests

500 Internal Server Error — échec transitoire ; le message est conservé et rejoué côté Bridg_, et le PMS doit le réémettre après un délai :

JSON
{ "error": "Message reçu mais non appliqué — reprise programmée", "code": "INGEST_FAILED" }

Returns

Cas HTTP Verdict
Message appliqué 200 RESULT SUCCESS en file
Message appliqué partiellement (items refusés) 200 RESULT FAILED en file, resultMessage détaille les items (#0 UNMAPPED_UNIT_TYPE — …)
Type non supporté, restriction non traduisible, corps illisible 200 RESULT FAILED en file
Doublon déjà traité 200 accusé mémorisé, pas de nouveau RESULT
Doublon en cours de traitement 202
Enveloppe illisible 400
Échec transitoire 500 réémettre

Récupérer le prochain message

Le PMS vient chercher, un message par appel, dans l'ordre FIFO : réservations OTA et directes (RESERVATION) et accusés de traitement (RESULT) des messages qu'il a envoyés.

Request

GET{base}/api/pms/v1/connections/{connectionId}/messages?key={secret}
curl
curl -i "https://staging.bridgchannel.app/api/pms/v1/connections/$CONNECTION_ID/messages?key=$SECRET"

Success Response

200 OK avec un message. L'en-tête HTTP title reprend l'enveloppe et permet de router sans parser le corps.

HTTP/1.1 200 OK
Content-Type: text/xml; charset=UTF-8
title: ATLALG|RESERVATION|42|NEW

<?xml version="1.0" encoding="UTF-8"?>
<?Label ATLALG|RESERVATION|42|NEW?>
<Reservation xmlns="reservation.fidelio.4.0" mfReservationAction="ADD">
  …
</Reservation>

200 OK sans message : corps vide et Content-Length: 0 (jamais un 204).

HTTP/1.1 200 OK
Content-Length: 0

Error Response

401 Unauthorized · 403 Forbidden (CONNECTION_INACTIVE) · 404 Not Found · 429 Too Many Requests

Returns

Cas Réponse
Un message est en attente 200, corps XML, en-tête title
Rien en attente 200, Content-Length: 0

Note

  • Rythme : interroger toutes les 30 à 120 secondes ; quand un message est servi, ré-interroger immédiatement jusqu'à obtenir un corps vide.
  • Une RESERVATION servie reste en attente de votre RESULT (corrélé sur son transactionId). Sans RESULT sous 30 minutes, elle est resservie avec un nouveau transactionId : dédupliquez sur reservationID.
  • Un RESULT servi n'attend rien en retour.
  • L'ordre est garanti par réservation : la modification d'une réservation n'est jamais servie avant sa création ; une réservation en dead-letter bloque ses propres événements suivants, pas ceux des autres réservations.

Accusés de traitement

Le protocole est asynchrone par construction : la réponse HTTP n'accuse que la réception.

Sens Message Verdict Corrélation
PMS → Bridg_ ARI, réservation, MessageRequest RESULT mis en file par Bridg_, récupéré par GET transactionId du message du PMS
Bridg_ → PMS RESERVATION servie par GET RESULT envoyé par le PMS sur POST …/messages transactionId que Bridg_ a posé sur la réservation

Format et sémantique du RESULT : reservations.md.

Conventions de dates

Forme Sémantique
<TimeSpan timeUnitType="DAY"><startTime>2026-10-10T00:00:00.000</startTime><numberOfTimeUnits>3</numberOfTimeUnits></TimeSpan> RAVL, RESTRICTION, RESERVATION première nuit + nombre de nuits (1 à 3 700). DAY uniquement.
<DaysOfWeek><monday>1</monday>…</DaysOfWeek> RAVL, RESTRICTION, RATE (RateDaysOfWeek) masque jour-de-semaine appliqué à la plage ; absent ou tout à 1 = toute la plage. 1, Y, true = actif.
<startDate>2026-10-10</startDate><endDate>2026-10-12</endDate> RATE endDate inclusive par défaut (rateEndDateInclusive).
datum="2026-10-10" RTAV une nuit.

Les dates sont des dates civiles ; la partie heure de startTime est ignorée.

Codes d'erreur propres au XML

code Cause
MISSING_LABEL, MALFORMED_LABEL enveloppe absente ou incomplète (HTTP 400)
UNEXPECTED_MESSAGE élément racine inattendu pour le type annoncé
INVALID_TIMESPAN, INVALID_DATE_RANGE TimeSpan ou startDate/endDate illisibles ou hors bornes
UNSUPPORTED_MESSAGE_TYPE type non traduit (INVENTORY, PROFILE…)
RESTRICTION_GRANULARITY_MISMATCH RAVR — utiliser RAVL
UNSUPPORTED_RESTRICTION code de restriction sans équivalent (ADVBOOK_MIN…)
UNSUPPORTED_ROOM_CLASS, UNSUPPORTED_RATE_CATEGORY, UNSUPPORTED_SCOPE, UNSUPPORTED_BLOCK_RESTRICTION restriction par classe, catégorie, hôtel entier ou bloc
UNSUPPORTED_TIERED_RATE, UNSUPPORTED_WEEKEND_RATE, UNSUPPORTED_RATE_MESSAGE tarifs par durée de séjour, prix week-end, rateMessageType inconnu
UNSUPPORTED_TIME_UNIT timeUnitType autre que DAY
MISSING_RATE_CODE, MISSING_RESTRICTION_CODE, MISSING_REFERENCE, MISSING_AMOUNT, DUPLICATE_NIGHT, NEGATIVE_COUNT champ requis absent ou incohérent