πŸ“š API Documentation β€” Hotel API v3.5.6

-

-

-

Logo
πŸ–οΈ Cos'Γ¨ la Hotel API e come si usa

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

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Opera (PMS) β”‚ Operatore inserisce prenotazione β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ Polling ogni N minuti ↓ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ MATLAB / NEXI β”‚ Legge le nuove booking β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ POST /api/hotel/booking ↓ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ BHBeaches DB β”‚ Crea booking in stato 1_pending β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ Risposta: { beach_url: "https://.../api/select/<token>" } ↓ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ MATLAB / NEXI β”‚ Riceve il link β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ Invia email all'ospite via Outlook con il link ↓ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ OSPITE β”‚ Apre il link, sceglie l'ombrellone β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ POST /api/select/<token> (con umbrella_code + accept regolamento) ↓ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ BHBeaches DB β”‚ Booking passa a 2_confirmed con prezzo + ombrellone β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ Polling MATLAB ↓ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ MATLAB / NEXI β”‚ Legge GET /api/hotel/bookings, aggiorna OHIP β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
πŸ” Autenticazione e Rate Limit

Tutti gli endpoint /api/hotel/* richiedono l'header:

X-API-Key: <la-tua-api-key>

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

LimiteValore
Richieste massime60 al minuto, per API Key
Window60 secondi rolling
Blocco al superamento60 secondi
Risposta al superamentoHTTP 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

HTTPQuando
401Header X-API-Key mancante
401API Key non valida o disattivata
403Tentativo di accedere a una prenotazione di un altro hotel
429Rate limit superato
πŸ“… Convenzione Date β€” leggere con attenzione

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".

TermineSignificatoDove
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:

POST /api/hotel/booking Body inviato: arrival_date = "2026-08-01" departure_date = "2026-08-07" ← checkout hotel DB salvato: arrival_date = "2026-08-01" departure_date = "2026-08-06" ← ultimo giorno spiaggia Calcolo prezzo: 6 giorni di spiaggia (1, 2, 3, 4, 5, 6 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.

πŸ” Stati Prenotazione e Transizioni
CodiceSignificatoActive
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

POST /booking β”‚ ↓ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ 1_pendingβ”œβ”€β”€β”€ PUT /bookingCancel ────────────→│ 4_cancelled β”‚ β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ ←──── PUT /bookingReinstate β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ POST /api/select/<token> (ospite sceglie) ↓ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ 2_confirmed β”œβ”€β”€ admin POST /bookings/X/noshow─→│ 5_noshow β”‚ β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ Lazy expire: arrival_date passa senza azioni ↓ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ 3_expired β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Note importanti

  • Lazy expire: 3_expired non Γ¨ settato da un cron ma alla prima visita del link guest dopo l'arrival_date. Una booking pending puΓ² quindi restare nello stato 1_pending in DB anche dopo l'arrivo, fino al primo accesso che la converte in 3_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.

POST /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_pending
  • active = true
  • umbrella_code = null
  • beach_price = null
Body fields
CampoTipoRequiredNote
arrival_datestringβœ…YYYY-MM-DD, check-in hotel
departure_datestringβœ…YYYY-MM-DD, check-out hotel
confirmation_idstring❌ (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_namestring❌Pseudonimizzato (es. m.rossi). Max 200 char.
notesstring❌ (v3.5.0)Note operatore. Max 500 char. Se omesso, viene auto-popolato col guest_name.
Errori specifici
HTTPQuando
400arrival_date o departure_date mancanti / formato errato
400arrival_date piΓΉ di 12h nel passato (validazione v3.5.0)
409Esiste giΓ  una booking con lo stesso confirmation_id per questo hotel
πŸ§ͺ Tester
// Clicca "Esegui" per testare
PUT /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
CasoEffetto
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
CampoRequiredNote
confirmation_idβœ…Identifica la booking
arrival_date❌Se presente, validato 12h non-passato (v3.5.0)
departure_date❌Checkout hotel
guest_nameβŒβ€”
Errori specifici
HTTPQuando
400confirmation_id mancante
400arrival_date piΓΉ di 12h nel passato
403Booking di un altro hotel
404confirmation_id non trovato
πŸ§ͺ Tester
// Clicca "Esegui" per testare
PUT /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_cancelled
  • active = false
  • umbrella_code = null
  • beach_price = null
  • confirmed_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
HTTPQuando
400confirmation_id mancante
403Booking di un altro hotel
404confirmation_id non trovato
πŸ§ͺ Tester
// Clicca "Esegui" per testare
PUT /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_pending
  • active = true
  • umbrella_code resta 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
HTTPQuando
400confirmation_id mancante
400Booking ha arrival_date piΓΉ di 12h nel passato (v3.5.0)
403Booking di un altro hotel
404confirmation_id non trovato
πŸ§ͺ Tester
// Clicca "Esegui" per testare
PUT /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
CasoEffetto
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
CampoRequiredNote
confirmation_idβœ…Identifica la booking
departure_dateβœ…Nuovo checkout hotel
guest_nameβŒβ€”
Esempio response (estensione)
{ "action": "extended", "original": { "confirmation_id": "40470944-459539388", "departure_date": "2026-08-06", ... }, "extension": { "confirmation_id": "40470944-459539388_EXT_01", "departure_date": "2026-08-09", "beach_status": "1_pending", "beach_price": 0, ... }, "message": "Soggiorno esteso. Nuova prenotazione per i giorni aggiuntivi." }
πŸ§ͺ Tester
// Clicca "Esegui" per testare
PUT /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
ParamNote
confirmation_idIdentificativo della booking. Supporta confirmation_id con dash (es. 40470944-459539388) tramite path converter.
Body fields
CampoRequiredNote
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_confirmed
  • umbrella_code = quello fornito (forma corta normalizzata)
  • beach_price calcolato in base alla riga + giorni di soggiorno
  • confirmed_at = timestamp corrente
Errori specifici
HTTPQuando
400umbrella_code mancante o non valido
400La booking non ha arrival_date o departure_date
400arrival_date piΓΉ di 12h nel passato
403Booking di un altro hotel
404confirmation_id non trovato
409Ombrellone non disponibile per il periodo (ha overlap con altra booking)
409Ombrellone preso da un'altra chiamata concorrente nell'intervallo tra check e write
πŸ§ͺ Tester
// Clicca "Esegui" per testare
GET /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
ParamRequired
confirmation_idβœ…
Errori specifici
HTTPQuando
400Query param confirmation_id mancante
403Booking di un altro hotel
404Booking non trovata
πŸ§ͺ Tester
// Clicca "Esegui" per testare
GET /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
ParamNote
confirmation_idSupporta dash come in 40470944-459539388 tramite path converter.
Response
{ "beach_url": "https://spiagge.bluhotels.it/api/select/abc123def456..." }
Errori specifici
HTTPQuando
403Booking di un altro hotel
404confirmation_id non trovato
404Booking trovata ma beach_url vuoto (non dovrebbe succedere in produzione)
πŸ§ͺ Tester
GET /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
ParamValoriNote
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
ValoreFiltra su
arrivobookings.arrival_date ∈ [from, to]
partenzabookings.departure_date ∈ [from, to]
soggiornoBooking che hanno almeno un giorno di overlap col range β€” formula: arrival ≀ to AND departure β‰₯ from
πŸ§ͺ Tester
// Clicca "Esegui" per testare
πŸ“¦ Struttura Response Standard

Tutte le risposte di tipo "booking" usano questa struttura, ritornata dalla funzione _fmt_booking() nel backend.

{ "id": 123, "hotel_code": "BLUBSV", "confirmation_id": "40470944-459539388", "guest_name": "m.rossi", "notes": "Famiglia Rossi 4 pax", "arrival_date": "2026-07-30", "departure_date": "2026-08-02", "umbrella_code": null, "beach_status": "1_pending", "beach_price": null, "beach_url": "https://spiagge.bluhotels.it/api/select/abc123...", "created_at": "2026-07-30 14:30:00", "updated_at": "2026-07-30 14:30:00", "link_sent_at": null, "confirmed_at": null, "active": true }

Note: active Γ¨ boolean (true/false), non integer. departure_date Γ¨ l'ultimo giorno spiaggia (checkout βˆ’ 1). beach_url include lo schema https + host.

⚠️ Codici Errore HTTP
HTTPSignificatoCause tipiche
400Bad RequestBody mancante o malformato, campi obbligatori mancanti, date non valide, validazione 12h fallita
401UnauthorizedHeader X-API-Key mancante o non valido
403ForbiddenTentativo di accesso a una booking di un altro hotel (cross-tenant)
404Not Foundconfirmation_id non corrisponde a nessuna booking
409ConflictPOST: confirmation_id giΓ  esistente. Assign: ombrellone non disponibile per il periodo o race condition
410GoneSolo endpoint pubblico POST /api/select/<token>: booking cancellata o link scaduto
429Too Many RequestsRate limit superato (60 req/min per API key). Risposta include retry_after in secondi
πŸ’» Esempi curl pronti

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
export KEY="la-tua-api-key" export BASE="https://spiagge.bluhotels.it"
POST /booking
curl -X POST "$BASE/api/hotel/booking" \ -H "X-API-Key: $KEY" \ -H "Content-Type: application/json" \ -d '{ "confirmation_id": "40470944-459539388", "guest_name": "m.rossi", "notes": "Famiglia Rossi 4 pax", "arrival_date": "2026-07-30", "departure_date": "2026-08-03" }'
PUT /booking
curl -X PUT "$BASE/api/hotel/booking" \ -H "X-API-Key: $KEY" \ -H "Content-Type: application/json" \ -d '{ "confirmation_id": "40470944-459539388", "departure_date": "2026-08-05" }'
PUT /bookingCancel
curl -X PUT "$BASE/api/hotel/bookingCancel" \ -H "X-API-Key: $KEY" \ -H "Content-Type: application/json" \ -d '{ "confirmation_id": "40470944-459539388" }'
PUT /bookingReinstate
curl -X PUT "$BASE/api/hotel/bookingReinstate" \ -H "X-API-Key: $KEY" \ -H "Content-Type: application/json" \ -d '{ "confirmation_id": "40470944-459539388" }'
PUT /bookingInHouse
curl -X PUT "$BASE/api/hotel/bookingInHouse" \ -H "X-API-Key: $KEY" \ -H "Content-Type: application/json" \ -d '{ "confirmation_id": "40470944-459539388", "departure_date": "2026-08-10" }'
PUT /booking/<conf>/assign (v3.5.0)
curl -X PUT "$BASE/api/hotel/booking/40470944-459539388/assign" \ -H "X-API-Key: $KEY" \ -H "Content-Type: application/json" \ -d '{ "umbrella_code": "A-5" }'
GET /booking
curl "$BASE/api/hotel/booking?confirmation_id=40470944-459539388" \ -H "X-API-Key: $KEY"
GET /booking/<conf>/link (v3.5.0)
curl "$BASE/api/hotel/booking/40470944-459539388/link" \ -H "X-API-Key: $KEY"
GET /bookings (con filtri)
curl "$BASE/api/hotel/bookings?tipo_data=soggiorno&arrival_date=2026-07-01&departure_date=2026-08-31&status=2_confirmed&limit=50" \ -H "X-API-Key: $KEY"
πŸ†• Cosa Γ¨ nuovo in v3.5.0
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_id ora Γ¨ opzionale. Se omesso il backend autogenera MAN000000000001 da una sequenza Postgres atomica. Aggiunto campo notes.
  • POST /booking + PUT /booking + PUT /bookingReinstate: nuova validazione che rifiuta arrival_date piΓΉ 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 col guest_name se 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.

πŸ“ Note Importanti β€” leggi prima di integrare
  • Convenzione date: departure_date in 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_id non 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_NN per estensioni). GET /booking ritorna la prima trovata; GET .../link ritorna 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 bookingInHouse usa 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.