Guida integrazione AlpineBits

Questa guida è rivolta a fornitori/PMS (property management system) che vogliono sincronizzare disponibilità, tariffe e prenotazioni con la piattaforma tramite il protocollo standard AlpineBits.

Cos'è AlpineBits

AlpineBits è un protocollo standard aperto per lo scambio di dati tra sistemi alberghieri (PMS/channel manager) e piattaforme di distribuzione, basato su XML OTA (OpenTravel Alliance) trasportato via HTTP. È largamente adottato nell'area alpina (Alto Adige, Trentino, Tirolo) per la sincronizzazione di inventario, tariffe e prenotazioni.

La piattaforma implementa la versione 2024-10 dello standard, come server (riceve richieste da PMS/channel manager esterni). Per la specifica completa del protocollo, consulta alpinebits.org.

Versione supportata: 2024-10 è l'unica versione di protocollo accettata dal server. Richieste con un header di versione diverso vengono rifiutate con un errore OTA_Error (nessun negoziato multi-versione).

Come ottenere le credenziali

Le credenziali di accesso (username e password) non si ottengono tramite autoregistrazione: vengono create dal referente commerciale/tecnico della struttura con cui stai integrando (il tenant che ti ha richiesto la connessione AlpineBits). Contatta direttamente il tuo interlocutore presso la struttura per richiedere un account fornitore.

Ogni account fornitore è associato a una singola struttura (multi-tenant): le credenziali che ricevi valgono solo per i dati di quella struttura.

Endpoint

POST https://<host>/api/alpinebits
Content-Type: multipart/form-data

Dove <host> è il dominio della piattaforma della struttura con cui stai integrando (es. www.tripmaster.cloud o un dominio custom del tenant).

Autenticazione

L'endpoint usa HTTP Basic Authentication sulle credenziali dell'account fornitore:

Authorization: Basic base64(username:password)

Le credenziali NON sono legate a un utente della piattaforma: sono un account fornitore dedicato, creato appositamente per l'integrazione AlpineBits.

Header obbligatorio

Ogni richiesta deve includere l'header di versione protocollo:

X-AlpineBits-ClientProtocolVersion: 2024-10

Senza questo header la richiesta viene rifiutata con 400 Bad Request. Con un valore diverso da 2024-10 la richiesta viene rifiutata con una risposta OTA_Error XML (200 con <Errors> nel corpo, come da standard AlpineBits).

Formato della richiesta: multipart action + request

Il body è multipart/form-data con due campi:

Campo Descrizione
action Identifica l'azione AlpineBits richiesta (vedi tabella sotto)
request Il messaggio XML OTA della richiesta (es. OTA_PingRQ, ecc.)

Azioni supportate

Azione (action) Messaggio richiesta → risposta Capacità dichiarate
OTA_Ping:Handshaking OTA_PingRQOTA_PingRS Scambio capacità/versioni supportate
OTA_HotelDescriptiveContentNotif:Inventory OTA_HotelDescriptiveContentNotifRQ...RS Sincronizzazione tipi camera/inventory
OTA_HotelRatePlanNotif:RatePlans OTA_HotelRatePlanNotifRQ...RS NotifType Full, Overlay e Remove — dettagli nella sezione RatePlans: Full, Overlay, Remove
OTA_HotelInvCountNotif:FreeRooms OTA_HotelInvCountNotifRQ...RS UniqueID/@Instance="CompleteSet" (reset completo) e modalità delta (upsert incrementale, non tocca i giorni non inclusi)
OTA_Read:GuestRequests (pull) OTA_ReadRQOTA_ResRetrieveRS Estrazione prenotazioni in coda (batch max 50, per data creazione)
OTA_NotifReport:GuestRequests (ack) OTA_NotifReportRQOTA_NotifReportRS Acknowledgment delle prenotazioni ricevute (marca come "consegnate/lette")

Ogni richiesta viene validata contro lo schema XSD AlpineBits prima del routing: un XML non conforme produce sempre una risposta di errore coerente, anche per azioni non riconosciute o non ancora supportate.

RatePlans: Full, Overlay, Remove

L'azione OTA_HotelRatePlanNotif:RatePlans accetta tre valori di RatePlanNotifType:

  • Full — replace completo del listino mappato al rate plan: periodi, quote, supplementi, servizi, scontistiche e riduzioni vengono ricostruiti da zero a partire dal messaggio. I dati inseriti a mano sul listino (agenzie, gruppo/profili, gratuità, pagamenti, stop-sale manuali, formato/MinPax) vengono azzerati a ogni Full.
  • Overlay — aggiornamento parziale, solo dati date-dependent: identifica il rate plan per RatePlanCode e sostituisce soltanto ciò che viene effettivamente trasmesso. Un elemento assente dal messaggio resta intatto; un elemento presente ma vuoto (es. <Rates/>) cancella i dati corrispondenti già presenti sul listino. Non tocca mai i dati manuali elencati sopra, né lo static rate, le descrizioni statiche o le Offers (non modificabili via Overlay dalla spec: se trasmesse producono un warning e vengono ignorate).
  • Remove — cancella il listino mappato al rate plan.

Capacità dichiarate in handshake

Per action_OTA_HotelRatePlanNotif_RatePlans il server dichiara: accept_full, accept_overlay, accept_Supplements, accept_FreeNightsOffers, accept_FamilyOffers, accept_ArrivalDOW, accept_DepartureDOW, accept_RatePlan_BookingRule, accept_OfferRule_DOWLOS. Per action_OTA_HotelDescriptiveContentNotif_Inventory: use_rooms e occupancy_children.

Non dichiarate (fase successiva): accept_RatePlanJoin, BookingRule per singola camera (RoomType/mixed BookingRule), accept_OfferRule_BookingOffset, ChargeTypeCode=12, PrerequisiteInventory con InvCode=ALPINEBITSDOW, DOW sulle Offers. Se il PMS li invia comunque non è mai un errore bloccante: la piattaforma li ignora e riporta un warning nella risposta.

Overlay: split automatico dei periodi e snapshot

Ogni <Rate InvTypeCode Start End> trasmessa individua il periodo del listino che copre esattamente quel range. Se il range non corrisponde a un periodo esistente, i periodi che lo intersecano solo in parte vengono spezzati automaticamente sui confini del range trasmesso, in modo che le tariffe trasmesse si applichino esattamente al range dichiarato senza toccare le date adiacenti; i frammenti generati dallo split che restano identici tra loro vengono poi fusi di nuovo a fine elaborazione, per non lasciare il listino frammentato inutilmente. Un range che attraversa un "buco" del listino (nessun periodo esistente lo copre interamente) è un errore bloccante: in quel caso serve un Full.

Prima della prima modifica di un Overlay sul listino, la piattaforma crea in automatico uno snapshot (nome AlpineBits pre-overlay <yyyy-MM-dd>, massimo uno al giorno per listino), così un aggiornamento errato può sempre essere ripristinato manualmente dall'interfaccia.

Semantica delle date: come da spec AlpineBits 4.4 ("departure ≤ End + 1"), Start/End di rate e booking rule indicano che End è l'ultima notte inclusa, non la data di check-out. La piattaforma memorizza internamente la data di check-out (esclusiva): ogni End ricevuto viene convertito in End + 1 prima di essere applicato a periodi e calendari.

Supplements: mapping su ChargeTypeCode

Per ogni InvCode è previsto un supplement statico (MandatoryIndicator, ChargeTypeCode, descrizioni) più eventuali supplement date-dependent con l'importo. In base a MandatoryIndicator e ChargeTypeCode il comportamento sulla piattaforma cambia:

ChargeTypeCode Unità di misura (spec OTA) MandatoryIndicator=true MandatoryIndicator=false
19 per camera, per notte applicato sempre, ogni notte proposto come extra su richiesta
21 per persona, per notte applicato sempre, ogni notte per persona proposto come extra su richiesta
1 per item, per giorno applicato sempre, ogni notte proposto come extra su richiesta
18 per camera, per soggiorno applicato automaticamente una tantum proposto come extra su richiesta
20 per persona, per soggiorno applicato automaticamente una tantum proposto come extra su richiesta
24 per item, per soggiorno applicato automaticamente una tantum proposto come extra su richiesta
12 legacy, non presente nella spec 2024-10 ignorato, warning ignorato, warning

In Overlay solo i prezzi date-dependent dei supplement possono essere aggiornati (Start/End/Amount nel range trasmesso); il supplement statico (definizione, obbligatorietà, ChargeTypeCode) non è modificabile via Overlay e va ridichiarato con un Full.

Offerte supportate (Offers)

Ogni rate plan può avere fino a 3 Offer. Sono riconosciute:

  • Notti gratisDiscount Percent="100" con NightsRequired/ NightsDiscounted (ed eventuale DiscountPattern per distribuire le notti gratis lungo il soggiorno invece di raggrupparle tutte alla fine): tradotta in una scontistica "notti gratis" applicata dal motore di calcolo (es. soggiorno di 7 notti pagate 6).
  • FamilyDiscount Percent="100" con Guests/Guest AgeQualifyingCode="8" (bambino): tradotta in bambini gratuiti per posizione letto, secondo i vincoli di età dichiarati nell'offerta.
  • Ogni altra Offer (non free-nights, non family) → warning "Offer non supportata", ignorata.
  • Le Offers trasmesse in un messaggio Overlay vengono sempre ignorate con warning: la spec AlpineBits non ammette la modifica delle offerte fuori da un Full.

Occupancy

Il prezzo base del listino corrisponde alla tariffa dichiarata per un numero di ospiti pari alla StandardOccupancy della camera, letta dall'Inventory (GuestRoom/Occupancy/@StandardOccupancy; se non dichiarata, il default è 2). Tariffe trasmesse per un numero di ospiti diverso dallo standard (BaseByGuestAmt con NumberOfGuests ≠ standard) generano automaticamente supplementi di sottoccupazione (meno ospiti dello standard, es. singola in doppia) o riduzioni per i letti aggiuntivi (più ospiti dello standard). In un Overlay, se una rate ritrasmette valori di occupancy diversi dallo standard queste righe derivate vengono ricalcolate e sostituite; se l'elemento non viene ritrasmesso, quelle già presenti restano intatte.

Esempio curl: handshake completo

curl -X POST "https://<host>/api/alpinebits" \
  -u "<username>:<password>" \
  -H "X-AlpineBits-ClientProtocolVersion: 2024-10" \
  -F "action=OTA_Ping:Handshaking" \
  -F "request=<OTA_PingRQ xmlns=\"http://www.opentravel.org/OTA/2003/05\" Version=\"8.000\"><EchoData>{\"versions\":[{\"version\":\"2024-10\",\"actions\":[{\"action\":\"action_OTA_HotelRatePlanNotif_RatePlans\"},{\"action\":\"action_OTA_HotelInvCountNotif\"}]}]}</EchoData></OTA_PingRQ>"

La risposta è un OTA_PingRS XML con header X-AlpineBits-Server: BCMS e, in assenza di errori, nessun elemento <Errors> nel corpo.

Download XSD e campioni

  • Scarica lo schema XSD usato per validare richieste e risposte.

  • Campioni XML di riferimento (multipart field request):

    Campione Link
    Handshake — richiesta (OTA_PingRQ) Scarica
    Handshake — risposta (OTA_PingRS) Scarica
    Inventory — richiesta base Scarica
    RatePlans — richiesta Scarica
    FreeRooms — richiesta Scarica
    GuestRequests — risposta con prenotazione Scarica

Codici di errore comuni

Codice / risposta Significato
401 Unauthorized Credenziali mancanti, errate o account fornitore disattivato
402 Payment Required L'abbonamento della struttura non è attivo (trial scaduto/cancellato) oppure il pacchetto Channel Manager non è attivo per la struttura (corpo JSON error distingue i due casi)
400 Bad RequestERR:no protocol version Header X-AlpineBits-ClientProtocolVersion mancante
OTA_ErrorERR:unsupported protocol version Header di versione presente ma diverso da 2024-10
OTA_*RS con <Errors>ERR:... Errore di validazione XSD, azione sconosciuta o errore di business specifico dell'azione

Tutti i tentativi (accettati o rifiutati) vengono registrati lato piattaforma per finalità di audit e supporto.

Flusso consigliato

  1. Handshake (OTA_Ping:Handshaking) — verifica connettività e scambia le capacità supportate dalle due parti.
  2. Inventory (OTA_HotelDescriptiveContentNotif:Inventory) — sincronizza i tipi camera prima di inviare tariffe o disponibilità.
  3. RatePlans (OTA_HotelRatePlanNotif:RatePlans) — invia i listini tariffari.
  4. FreeRooms (OTA_HotelInvCountNotif:FreeRooms) — invia la disponibilità (consigliato un CompleteSet iniziale, poi aggiornamenti in delta).
  5. GuestRequests — effettua periodicamente il pull (OTA_Read) delle nuove prenotazioni e invia l'ack (OTA_NotifReport) una volta che il PMS le ha importate correttamente, per evitare di riceverle di nuovo nel pull successivo.