π API Documentation β Hotel API v3.5.6
-
-
-
La Hotel API Γ¨ l'interfaccia che il sistema PMS dell'hotel (Opera tramite MATLAB/NEXI)
usa per sincronizzare le prenotazioni con BHBeaches. Tutti gli endpoint sono prefissati
/api/hotel/... e richiedono autenticazione tramite
header X-API-Key.
Ogni API Key Γ¨ legata a una singola spiaggia. Le operazioni di lettura/scrittura sono automaticamente
scopate alla spiaggia della chiave: una chiave di BLUBSV non puΓ² vedere o modificare
prenotazioni di un altro hotel.
Flusso end-to-end di una prenotazione
Tutti gli endpoint /api/hotel/* richiedono l'header:
Dove trovare la API Key
Solo i ruoli admin e sede possono visualizzare/rigenerare la API Key. Vai su Spiagge β seleziona la spiaggia β sezione API Key. La generazione produce una chiave nuova e invalida quella precedente.
Rate Limit
| Limite | Valore |
|---|---|
| Richieste massime | 60 al minuto, per API Key |
| Window | 60 secondi rolling |
| Blocco al superamento | 60 secondi |
| Risposta al superamento | HTTP 429 con campo retry_after in secondi |
Il rate limit Γ¨ applicato per chiave (non per IP) perchΓ© la rete dell'hotel puΓ² uscire da un singolo IP NAT.
Errori di autenticazione
| HTTP | Quando |
|---|---|
| 401 | Header X-API-Key mancante |
| 401 | API Key non valida o disattivata |
| 403 | Tentativo di accedere a una prenotazione di un altro hotel |
| 429 | Rate limit superato |
BHBeaches gestisce due semantiche diverse per le date di una prenotazione, ed Γ¨ importante non confonderle. La Hotel API lavora sempre in semantica "checkout hotel" sui campi in input, ma il DB persiste la "data ultimo giorno spiaggia".
| Termine | Significato | Dove |
|---|---|---|
arrival_date |
Data check-in hotel (= primo giorno spiaggia) | Input + DB + response |
departure_date (input) |
Data check-out hotel (= giorno in cui l'ospite parte) | Body POST/PUT della Hotel API |
departure_date (DB / response) |
Ultimo giorno effettivo in spiaggia = checkout β 1 | Tabella bookings + tutte le response |
Esempio
L'ospite Mario Rossi arriva il 1Β° agosto e fa il check-out il 7 agosto:
Tutte le response della Hotel API ritornano la versione DB
(departure_date = ultimo giorno spiaggia), non il checkout originale.
Se il PMS ha bisogno del checkout, deve aggiungere 1 giorno alla departure_date ricevuta.
Validazione "data troppo vecchia" (v3.5.0)
Per evitare errori operativi (es. PMS che invia inavvertitamente una booking con data nel passato),
gli endpoint che accettano arrival_date rifiutano date piΓΉ vecchie di
12 ore rispetto all'orario corrente Europe/Rome. Risposta: HTTP 400.
Eccezione: PUT /bookingInHouse NON applica questa validazione perchΓ© un cambio date di un ospite
giΓ in casa Γ¨ un'operazione legittima anche se le date sono nel passato relativo.
| Codice | Significato | Active |
|---|---|---|
1_pending |
In Attesa Prenotazione creata, ospite non ha ancora scelto l'ombrellone | true |
2_confirmed |
Confermata Ombrellone selezionato + prezzo calcolato | true |
3_expired |
Scaduta Data arrivo passata senza che l'ospite abbia scelto | true |
4_cancelled |
Cancellata Cancellazione tramite API o admin | false |
5_noshow |
No-Show Ospite non si Γ¨ presentato (settato dall'admin) | false |
Diagramma transizioni
Note importanti
- Lazy expire:
3_expirednon Γ¨ settato da un cron ma alla prima visita del link guest dopo l'arrival_date. Una booking pending puΓ² quindi restare nello stato1_pendingin DB anche dopo l'arrivo, fino al primo accesso che la converte in3_expired. - Il link guest
/api/select/<token>Γ¨ "state-driven": indipendentemente da quale URL apra l'ospite, viene reindirizzato alla pagina corretta per lo stato attuale (select, confirmed, cancelled, expired). - 5_noshow Γ¨ settato solo dall'admin via interfaccia, non dalla Hotel API.
π Configurazione API Key (per il tester)
Inserisci la tua API Key per testare gli endpoint qui sotto. VerrΓ usata in tutti i tester di questa pagina.
/api/hotel/booking
β Crea nuova prenotazione
Crea una nuova prenotazione, ritorna l'oggetto booking + il beach_url da inviare via email all'ospite.
Stato risultante
beach_status = 1_pendingactive = trueumbrella_code = nullbeach_price = null
Body fields
| Campo | Tipo | Required | Note |
|---|---|---|---|
arrival_date | string | β | YYYY-MM-DD, check-in hotel |
departure_date | string | β | YYYY-MM-DD, check-out hotel |
confirmation_id | string | β (v3.5.0) | Riferimento PMS. Se omesso o vuoto, il backend autogenera un identificativo nel formato MAN000000000001 usando una sequenza Postgres. Una volta creato, Γ¨ immutabile. |
guest_name | string | β | Pseudonimizzato (es. m.rossi). Max 200 char. |
notes | string | β (v3.5.0) | Note operatore. Max 500 char. Se omesso, viene auto-popolato col guest_name. |
Errori specifici
| HTTP | Quando |
|---|---|
| 400 | arrival_date o departure_date mancanti / formato errato |
| 400 | arrival_date piΓΉ di 12h nel passato (validazione v3.5.0) |
| 409 | Esiste giΓ una booking con lo stesso confirmation_id per questo hotel |
π§ͺ Tester
/api/hotel/booking
β Aggiorna date o nome ospite
Aggiorna una prenotazione esistente identificata da confirmation_id. La logica di gestione
dell'ombrellone giΓ confermato dipende dalle nuove date β vedi sotto.
Logica "smart narrowing" sull'ombrellone
| Caso | Effetto |
|---|---|
Solo guest_name cambia (date invariate) |
Ombrellone mantenuto, prezzo invariato |
| Nuove date sono un sottoinsieme delle vecchie E ombrellone giΓ assegnato |
Ombrellone mantenuto, prezzo ricalcolato sui nuovi giorni |
| Nuove date espandono il range OPPURE si spostano fuori | Ombrellone resettato a null, status torna a 1_pending |
| Nessun ombrellone era assegnato | Solo aggiornamento date, status resta 1_pending |
Il beach_url rimane invariato in tutti i casi: l'ospite puΓ² riusare lo stesso link.
Body fields
| Campo | Required | Note |
|---|---|---|
confirmation_id | β | Identifica la booking |
arrival_date | β | Se presente, validato 12h non-passato (v3.5.0) |
departure_date | β | Checkout hotel |
guest_name | β | β |
Errori specifici
| HTTP | Quando |
|---|---|
| 400 | confirmation_id mancante |
| 400 | arrival_date piΓΉ di 12h nel passato |
| 403 | Booking di un altro hotel |
| 404 | confirmation_id non trovato |
π§ͺ Tester
/api/hotel/bookingCancel
β Cancella prenotazione
Cancella una prenotazione esistente. Libera l'ombrellone (se assegnato) per altre prenotazioni sovrapposte e marca la booking come non attiva.
Stato risultante
beach_status = 4_cancelledactive = falseumbrella_code = nullbeach_price = nullconfirmed_at = null
Comportamento del link guest
Il beach_url non viene cancellato β rimane in DB. Ma se l'ospite lo apre, viene
automaticamente reindirizzato a /api/select/<token>/cancelled
che mostra una pagina informativa "Prenotazione cancellata β contatta la reception".
ReversibilitΓ
La cancellazione Γ¨ reversibile via PUT /api/hotel/bookingReinstate (vedi sotto).
Errori specifici
| HTTP | Quando |
|---|---|
| 400 | confirmation_id mancante |
| 403 | Booking di un altro hotel |
| 404 | confirmation_id non trovato |
π§ͺ Tester
/api/hotel/bookingReinstate
β Ripristina prenotazione cancellata
Riporta una prenotazione precedentemente cancellata in stato attivo. L'ospite dovrΓ ri-selezionare l'ombrellone (perchΓ© Γ¨ stato liberato al momento della cancellazione).
Stato risultante
beach_status = 1_pendingactive = trueumbrella_coderesta null (era stato svuotato in cancel)
Il beach_url torna utilizzabile. Se l'ospite riapre il vecchio link riceve di nuovo la
pagina di selezione ombrellone.
Validazione 12h (v3.5.0)
Non ha senso ripristinare una booking il cui arrival_date Γ¨ giΓ passato. Il backend
rifiuta con HTTP 400 se l'arrival_date Γ¨ piΓΉ vecchio di 12h.
Errori specifici
| HTTP | Quando |
|---|---|
| 400 | confirmation_id mancante |
| 400 | Booking ha arrival_date piΓΉ di 12h nel passato (v3.5.0) |
| 403 | Booking di un altro hotel |
| 404 | confirmation_id non trovato |
π§ͺ Tester
/api/hotel/bookingInHouse
β Cambio date per ospite giΓ in hotel
Endpoint specifico per gestire i cambi di soggiorno fatti in reception per un ospite giΓ in hotel.
Il comportamento dipende dal confronto tra nuova e vecchia departure_date.
Logica condizionale
| Caso | Effetto |
|---|---|
| Nuova departure < vecchia (accorcia) | La booking originale viene aggiornata in-place. Ombrellone mantenuto. Prezzo NON viene ricalcolato automaticamente da questo endpoint. |
| Nuova departure > vecchia (estende) | La booking originale resta INVARIATA con il suo ombrellone. Viene creata una nuova booking per i giorni aggiuntivi con confirmation_id = "<originale>_EXT_NN" (sequenziale a 2 cifre, v3.5.5: _EXT_01, _EXT_02, ...). Le estensioni sono SEMPRE sotto il base originale, mai annidate. La nuova booking nasce in stato 1_pending e beach_price = 0 (l'ospite dovrΓ selezionare un ombrellone per il nuovo periodo). La response include sia original sia extension. |
| Nuova departure = vecchia | Solo eventuale aggiornamento di guest_name. Nessuna altra modifica. |
Validazione 12h (assente per design)
A differenza degli altri endpoint, NON applica la validazione 12h sull'arrival_date. Un ospite giΓ in casa potrebbe avere arrival_date di 5 giorni fa: Γ¨ normale, non Γ¨ un errore.
Body fields
| Campo | Required | Note |
|---|---|---|
confirmation_id | β | Identifica la booking |
departure_date | β | Nuovo checkout hotel |
guest_name | β | β |
Esempio response (estensione)
π§ͺ Tester
/api/hotel/booking/<confirmation_id>/assign
NUOVO v3.5.0
Assegna un ombrellone a una prenotazione esistente, identificata via confirmation_id
nell'URL. Atomico: usa SELECT FOR UPDATE SKIP LOCKED per prevenire double-booking
in caso di chiamate concorrenti.
Quando usarlo
Caso d'uso principale: la reception, dopo aver ricevuto richiesta dell'ospite, vuole assegnare un ombrellone specifico via API senza passare dal flusso "ospite clicca link". Permette al PMS di sincronizzare anche assegnazioni operate manualmente in reception.
Il confirmation_id Γ¨ usato solo per identificare la booking.
Non viene mai modificato β l'identificativo della booking Γ¨ immutabile per tutto il suo ciclo di vita.
URL parameter
| Param | Note |
|---|---|
confirmation_id | Identificativo della booking. Supporta confirmation_id con dash (es. 40470944-459539388) tramite path converter. |
Body fields
| Campo | Required | Note |
|---|---|---|
umbrella_code | β | Code dell'ombrellone, formato corto "A-5" o pieno "BLUBSV-A-5" (entrambi accettati). Solo caratteri alfanumerici, dash, underscore. Max 50 char. |
Effetto
beach_status = 2_confirmedumbrella_code= quello fornito (forma corta normalizzata)beach_pricecalcolato in base alla riga + giorni di soggiornoconfirmed_at= timestamp corrente
Errori specifici
| HTTP | Quando |
|---|---|
| 400 | umbrella_code mancante o non valido |
| 400 | La booking non ha arrival_date o departure_date |
| 400 | arrival_date piΓΉ di 12h nel passato |
| 403 | Booking di un altro hotel |
| 404 | confirmation_id non trovato |
| 409 | Ombrellone non disponibile per il periodo (ha overlap con altra booking) |
| 409 | Ombrellone preso da un'altra chiamata concorrente nell'intervallo tra check e write |
π§ͺ Tester
/api/hotel/booking
β Verifica stato singola prenotazione
Recupera i dettagli di una prenotazione tramite confirmation_id passato come query string.
Read-only, nessun side effect.
Query string
| Param | Required |
|---|---|
confirmation_id | β |
Errori specifici
| HTTP | Quando |
|---|---|
| 400 | Query param confirmation_id mancante |
| 403 | Booking di un altro hotel |
| 404 | Booking non trovata |
π§ͺ Tester
/api/hotel/booking/<confirmation_id>/link
NUOVO v3.5.0
Restituisce il link guest completo (con host) per una prenotazione, da rispedire all'ospite via email/SMS. Caso d'uso: la reception deve reinviare un link senza ricreare la booking.
Logica di lookup
Se per il confirmation_id esistono piΓΉ righe in DB (caso raro: legacy con _EXT
o sync MATLAB anomalo), viene ritornata la piΓΉ recente attiva. Se nessuna Γ¨ attiva,
ritorna la piΓΉ recente in assoluto.
URL parameter
| Param | Note |
|---|---|
confirmation_id | Supporta dash come in 40470944-459539388 tramite path converter. |
Response
Errori specifici
| HTTP | Quando |
|---|---|
| 403 | Booking di un altro hotel |
| 404 | confirmation_id non trovato |
| 404 | Booking trovata ma beach_url vuoto (non dovrebbe succedere in produzione) |
π§ͺ Tester
/api/hotel/bookings
β Lista prenotazioni con filtri
Restituisce un array di prenotazioni filtrate. Tutti i parametri sono opzionali. Se nessun filtro Γ¨
passato, ritorna tutte le booking dell'hotel ordinate per arrival_date desc.
Query parameters
| Param | Valori | Note |
|---|---|---|
tipo_data |
arrivo | partenza | soggiorno |
Default arrivo. Determina come applicare il range date sotto. |
arrival_date |
YYYY-MM-DD | Inizio range filtro |
departure_date |
YYYY-MM-DD | Fine range filtro |
status |
1_pending | 2_confirmed | 3_expired | 4_cancelled | 5_noshow | Filtra per stato |
active |
1/true oppure 0/false |
Filtra solo attive o non attive |
limit |
integer | Max righe ritornate |
Semantiche di tipo_data
| Valore | Filtra su |
|---|---|
arrivo | bookings.arrival_date β [from, to] |
partenza | bookings.departure_date β [from, to] |
soggiorno | Booking che hanno almeno un giorno di overlap col range β formula: arrival β€ to AND departure β₯ from |
π§ͺ Tester
Tutte le risposte di tipo "booking" usano questa struttura, ritornata dalla funzione
_fmt_booking() nel backend.
Note: active Γ¨ boolean (true/false), non integer.
departure_date Γ¨ l'ultimo giorno spiaggia (checkout β 1).
beach_url include lo schema https + host.
| HTTP | Significato | Cause tipiche |
|---|---|---|
| 400 | Bad Request | Body mancante o malformato, campi obbligatori mancanti, date non valide, validazione 12h fallita |
| 401 | Unauthorized | Header X-API-Key mancante o non valido |
| 403 | Forbidden | Tentativo di accesso a una booking di un altro hotel (cross-tenant) |
| 404 | Not Found | confirmation_id non corrisponde a nessuna booking |
| 409 | Conflict | POST: confirmation_id giΓ esistente. Assign: ombrellone non disponibile per il periodo o race condition |
| 410 | Gone | Solo endpoint pubblico POST /api/select/<token>: booking cancellata o link scaduto |
| 429 | Too Many Requests | Rate limit superato (60 req/min per API key). Risposta include retry_after in secondi |
Esempi pronti da eseguire da terminale. Sostituisci $KEY con la tua API Key e
$BASE con l'URL base (es. https://spiagge.bluhotels.it in produzione,
http://localhost:5000 in dev).
Variabili shell
POST /booking
PUT /booking
PUT /bookingCancel
PUT /bookingReinstate
PUT /bookingInHouse
PUT /booking/<conf>/assign (v3.5.0)
GET /booking
GET /booking/<conf>/link (v3.5.0)
GET /bookings (con filtri)
Endpoint nuovi
PUT /api/hotel/booking/<confirmation_id>/assignβ assegna ombrellone via API atomica.GET /api/hotel/booking/<confirmation_id>/linkβ recupera link guest per re-invio.
Modifiche endpoint esistenti
- POST /booking:
confirmation_idora Γ¨ opzionale. Se omesso il backend autogeneraMAN000000000001da una sequenza Postgres atomica. Aggiunto camponotes. - POST /booking + PUT /booking + PUT /bookingReinstate: nuova validazione che rifiuta
arrival_datepiΓΉ vecchio di 12h (Europe/Rome) per evitare errori operativi. - PUT /bookingInHouse: NON ha la validazione 12h (caso d'uso ospite giΓ checked-in con date passate).
Nuovi campi nelle response
notes: stringa free-form fino a 500 char. Auto-popolato colguest_namese non fornito alla creazione.
Stato 5_noshow
Lo stato 5_noshow esisteva da prima ma non era documentato. Γ settato dall'admin via
UI o tramite endpoint admin POST /api/admin/bookings/<id>/noshow.
Non Γ¨ scrivibile direttamente dalla Hotel API.
- Convenzione date:
departure_datein input alle Hotel API Γ¨ il checkout hotel; nel DB e nelle response viene salvata come ultimo giorno spiaggia (checkout β 1). Vedi sezione "Convenzione Date". - Identificativo immutabile: una volta creata una booking, il suo
confirmation_idnon cambia mai piΓΉ. Vale sia per i MAN auto-generati sia per quelli forniti dal PMS. - Multi-row con stesso confirmation_id: legacy puΓ² avere piΓΉ righe (sync MATLAB anomalo o suffisso
_EXT_NNper estensioni).GET /bookingritorna la prima trovata;GET .../linkritorna la piΓΉ recente attiva. - Gli endpoint cross-tenant ritornano sempre 403, non 404, per evitare information disclosure (un attaccante non puΓ² sapere se un confirmation_id esiste su un altro hotel).
- Estensione _EXT_NN: la booking di estensione creata da
bookingInHouseusa il confirmation_id"<originale>_EXT_NN"sequenziale (v3.5.5:_EXT_01,_EXT_02, ...). Le estensioni sono SEMPRE sibling sotto il base originale, mai annidate. Sono trattate come booking normali a tutti gli effetti β possono essere cancellate, modificate, e l'ospite puΓ² sceglierne l'ombrellone tramite il suo link guest. - API Key per spiaggia: una sola chiave attiva per spiaggia. Rigenerare la chiave invalida immediatamente la precedente. Nessuna scadenza automatica.