Offerte e codici promozionali
Gli endpoint di catalogo rispondono alla domanda “che cosa posso prenotare in ogni tipo di camera”. Questi rispondono a “quali offerte valgono per questo soggiorno”, cioè a ciò che serve a un motore di prenotazione per presentarle: nomi pubblici, descrizioni, immagini, che cosa comprende un pacchetto e il prezzo per il gruppo in questione.
Un piano tariffario, un pacchetto e una promozione sono tutti lo stesso tipo di oggetto. Si distinguono per il loro kind e per il modo in cui il prezzo deriva da un piano padre, ed è per questo che un pacchetto si distribuisce e si tariffa esattamente come qualsiasi altra tariffa.
GET /rate-plansAmbito: availability:read
Tutte le offerte che la struttura ha pubblicato per il motore di prenotazione, tariffate per il soggiorno e il gruppo richiesti.
| Parametro | Obbligatorio | Note |
|---|---|---|
check_in | sì | YYYY-MM-DD. |
check_out | sì | YYYY-MM-DD, esclusa. |
adults | no | Predefinito 2. |
children | no | Predefinito 0. |
room_type_id | no | Limita a un solo tipo di camera. |
curl "$VRDN_BASE/rate-plans?check_in=2026-08-01&check_out=2026-08-04&adults=2" \
-H "Authorization: Bearer $VRDN_KEY"{
"check_in": "2026-08-01",
"check_out": "2026-08-04",
"data": [
{
"rate_plan_id": "5c1e8f4a-2b7d-4a9c-8e6f-1d3b9a5c7e02",
"room_type_id": "9b2f6c3e-8d1a-4f5b-a7c9-4e0d2b8f1a63",
"room_type_name": "Ocean Suite",
"public_name": "Half Board Escape",
"kind": "package",
"description": "Breakfast and dinner included daily.",
"image_url": "https://cdn.example.com/half-board.jpg",
"inclusions": [
{ "label": "Breakfast", "frequency": "perGuestPerNight", "included_quantity": 1 },
{ "label": "Dinner", "frequency": "perGuestPerNight", "included_quantity": 1 }
],
"min_los": 2,
"max_los": null,
"currency": "USD",
"total": "1341.60",
"room_subtotal": "1020.00",
"taxes_total": "321.60",
"base_occupancy": 2,
"nightly_rates": [{ "date": "2026-08-01", "day_of_week": 6, "rate": "340.00", "source": "interval" }]
}
]
}Un'offerta compare solo quando valgono tutte le condizioni seguenti. Ciò che non le soddisfa è semplicemente assente dalla risposta, non esiste una voce parziale o “non disponibile”.
- Il piano è attivo e la struttura lo ha abilitato per il motore di prenotazione.
- Il soggiorno rientra nella finestra di prenotazione e nella finestra di soggiorno dell'offerta.
- La durata del soggiorno rispetta il minimo e il massimo dell'offerta, e ogni notte cade in un giorno della settimana consentito.
- Il tipo di camera può ospitare il gruppo.
- Il piano non è protetto da un codice promozionale.
Le offerte protette da un codice promozionale non compaiono mai qui. Sono raggiungibili solo attraverso una convalida riuscita del codice, descritta più sotto.
inclusions elenca ciò che un pacchetto comprende, con la frequenza con cui ogni voce ricorre: perStay, perNight, perGuest o perGuestPerNight. Sono descrittive. Il prezzo a cui un pacchetto viene venduto è l'unico total, e la struttura ripartisce internamente quel totale fra le inclusioni perché ogni componente riceva il giusto trattamento fiscale, ma l'ospite paga una cifra sola.
POST /promo-codes/validateAmbito: availability:read
| Campo | Obbligatorio | Note |
|---|---|---|
code | sì | Maiuscole, minuscole e spazi ai lati vengono ignorati. |
check_in | sì | YYYY-MM-DD. |
check_out | sì | YYYY-MM-DD, esclusa. |
room_type_id | no | Se lo fornisci e l'offerta del codice riguarda un altro tipo di camera, la risposta è l'uniforme valid: false. |
adults | no | Predefinito 2. |
children | no | Predefinito 0. |
child_ages | no | Predefinito []. Quando non è vuoto, la sua lunghezza è il numero di bambini e prevale su children. |
La dimensione del gruppo viene confrontata con l'occupazione massima del tipo di camera, quindi un gruppo dichiarato più piccolo del reale può risultare valido qui e poi fallire su POST /holds.
Un codice sblocca un piano tariffario. Non applica uno sconto proprio: il risparmio è già dentro il piano che il codice rivela, quindi il prezzo che ricevi è il prezzo, senza altro da calcolare.
curl -X POST "$VRDN_BASE/promo-codes/validate" \
-H "Authorization: Bearer $VRDN_KEY" \
-H "Content-Type: application/json" \
-d '{
"code": "SUMMER26",
"check_in": "2026-08-01",
"check_out": "2026-08-04",
"adults": 2
}'Un codice che si applica restituisce l'offerta che sblocca, nella stessa forma di una voce di /rate-plans.
{
"valid": true,
"code": "SUMMER26",
"rate_plan": {
"rate_plan_id": "e2a9d7c4-3f6b-4c1e-9a8d-7b5f0c2e4a19",
"room_type_id": "9b2f6c3e-8d1a-4f5b-a7c9-4e0d2b8f1a63",
"room_type_name": "Ocean Suite",
"public_name": "Early Bird",
"kind": "promotion",
"description": "Book 60 days ahead and save.",
"image_url": "https://cdn.example.com/early-bird.jpg",
"inclusions": [],
"min_los": 3,
"max_los": null,
"currency": "USD",
"total": "1140.36",
"room_subtotal": "867.00",
"taxes_total": "273.36",
"nightly_rates": [{ "date": "2026-08-01", "day_of_week": 6, "rate": "289.00", "source": "interval" }]
}
}Un codice che non si applica restituisce una sola risposta, qualunque sia la causa.
{
"valid": false,
"reason": "That code is not valid for these dates."
}La risposta di errore è volutamente identica per un codice che non esiste, per uno scaduto, per uno già riscattato del tutto e per uno la cui offerta non copre le date richieste. Distinguerli permetterebbe a chi chiama di scoprire quali codici sono reali, quindi la causa precisa non viene mai rivelata.
Il confronto dei codici ignora maiuscole, minuscole e spazi ai lati, quindi summer26 e SUMMER26 sono lo stesso codice.
La convalida dei codici ha un limite più stretto rispetto al resto dell'API, che si aggiunge ai limiti per chiave e per IP descritti in Autenticazione. Errori ripetuti restituiscono 429. Convalida un codice quando l'ospite lo invia, non a ogni tasto premuto.
Passa il codice alla chiamata di prenotazione. Il server lo risolve di nuovo da zero e ricalcola il prezzo del soggiorno.
curl -X POST "$VRDN_BASE/holds" \
-H "Authorization: Bearer $VRDN_KEY" \
-H "Content-Type: application/json" \
-d '{
"guest_id": "c4e7b9d2-6a1f-4e3c-9b8d-2f5a7c0e1d46",
"room_type_id": "9b2f6c3e-8d1a-4f5b-a7c9-4e0d2b8f1a63",
"rate_plan_id": "e2a9d7c4-3f6b-4c1e-9a8d-7b5f0c2e4a19",
"check_in": "2026-08-01",
"check_out": "2026-08-04",
"adults": 2,
"promo_code": "SUMMER26"
}'Due conseguenze di cui tenere conto quando progetti:
- Una risposta di convalida è indicativa. Rispecchia il momento in cui è stata emessa. Se il codice scade, viene disattivato o raggiunge il limite di riscatti prima che l'ospite completi il pagamento, la prenotazione fallisce invece di rispettare il preventivo precedente. Gestisci quell'errore nel tuo flusso di checkout.
- Non inviare mai un prezzo. Il server calcola da sé il prezzo di ogni prenotazione e ignora qualsiasi importo fornito da un client. Un preventivo serve solo a essere mostrato.
Il riscatto viene conteggiato quando una prenotazione viene confermata, non quando un codice viene convalidato, e viene rilasciato se la prenotazione viene annullata. Un codice limitato a un numero fisso di riscatti non può essere venduto in eccesso da prenotazioni simultanee.