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 lo standard come server (riceve richieste da PMS/channel manager esterni). Versioni di protocollo supportate: 2024-10. Per la specifica completa del protocollo, consulta alpinebits.org.
Versioni supportate: il server accetta solo le versioni elencate sopra (oggi
2024-10;2026-10verrà aggiunta alla pubblicazione definitiva dello standard). Richieste con un header di versione diverso vengono rifiutate con un erroreOTA_Error. Nell'handshake il server dichiara tutte le versioni supportate: il client sceglie una versione e la usa per ogni richiesta.
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 non supportato 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_PingRQ → OTA_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_ReadRQ → OTA_ResRetrieveRS |
Estrazione prenotazioni in coda (batch max 50, per data creazione) |
OTA_NotifReport:GuestRequests (ack) |
OTA_NotifReportRQ → OTA_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
RatePlanCodee 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 leOffers(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. Per action_OTA_HotelInvCountNotif (FreeRooms):
accept_categories (disponibilità per tipologia, InvTypeCode),
accept_complete_set e accept_deltas (dopo un CompleteSet iniziale si
possono inviare solo i giorni variati).
Apertura e chiusura del rate plan (RestrictionStatus)
Una BookingRule generica con <RestrictionStatus Restriction="Master" Status="Close"/> chiude il rate plan nel range della regola: i periodi del
listino vengono spezzati sui confini della regola e quelli chiusi diventano
non vendibili, conservando le tariffe. In un Overlay Status="Open" (o
una regola senza RestrictionStatus) riapre il range con le tariffe già
presenti. La chiusura è indipendente dalla disponibilità FreeRooms: un range
chiuso resta non vendibile anche con camere libere.
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/Enddi rate e booking rule indicano cheEndè l'ultima notte inclusa, non la data di check-out. La piattaforma memorizza internamente la data di check-out (esclusiva): ogniEndricevuto viene convertito inEnd + 1prima 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 gratis —
Discount Percent="100"conNightsRequired/NightsDiscounted(ed eventualeDiscountPatternper 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). - Family —
Discount Percent="100"conGuests/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
Offerstrasmesse 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). La tariffa a 1 ospite diventa il supplemento singola della
sistemazione "Doppia uso singola": l'ospite singolo paga la tariffa dichiarata
per 1, non quella della camera piena.
Gli AdditionalGuestAmounts (bambini per fascia d'età con AgeQualifyingCode="8"
e MinAge/MaxAge, adulto con AgeQualifyingCode="10") valgono solo per la
camera della rate che li trasmette e per ogni letto oltre lo standard, fino alla
MaxOccupancy dichiarata nell'Inventory (se assente: standard + 2). L'Amount è
il prezzo pagato dall'ospite per notte; Amount="0" = gratis. Oltre la
MaxOccupancy la camera non viene proposta: dichiaratela sempre nell'Inventory.
Una Offer senza Discount che contiene solo OfferRule/Occupancy è una
regola di occupazione del rate plan, non un'offerta: con
AgeQualifyingCode="10", MaxOccupancy limita il numero di adulti per camera e
MinOccupancy impone il minimo di adulti paganti (sotto il minimo si paga la
camera piena). La regola sui bambini non serve: i bambini sono già limitati dalla
MaxOccupancy della camera e dalle sistemazioni (al massimo 2 infant per camera).
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 (
multipartfieldrequest):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 — ERROR:invalid or missing username/password |
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 Request — ERROR:no valid client protocol version provided |
Header X-AlpineBits-ClientProtocolVersion mancante |
400 Bad Request — ERROR:your current alpinebits version does not match one of the servers supported versions |
Header di versione presente ma non tra le versioni supportate |
400 Bad Request — ERROR:unknown or missing action |
Campo action mancante o azione non supportata |
400 Bad Request — ERROR:XML validation error |
Campo request non XML ben formato o non valido contro lo XSD (il dettaglio è registrato nel log richieste della piattaforma) |
OTA_*RS con <Errors> — ERR:... |
Errore di business specifico dell'azione (es. tariffa o camera non mappata) |
Tutti i tentativi (accettati o rifiutati) vengono registrati lato piattaforma per finalità di audit e supporto.
Flusso consigliato
- Handshake (
OTA_Ping:Handshaking) — verifica connettività e scambia le capacità supportate dalle due parti. - Inventory (
OTA_HotelDescriptiveContentNotif:Inventory) — sincronizza i tipi camera prima di inviare tariffe o disponibilità. - RatePlans (
OTA_HotelRatePlanNotif:RatePlans) — invia i listini tariffari. - FreeRooms (
OTA_HotelInvCountNotif:FreeRooms) — invia la disponibilità (consigliato unCompleteSetiniziale, poi aggiornamenti in delta). - 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.