Canali OTA
Esta página aún no está disponible en tu idioma. Se muestra la versión predeterminada.
Última actualización: 27 de octubre de 2026
Canali OTA
Superficie di prenotazione in ingresso per le OTA (partner tipo Viator).
Il contratto è indipendente dal provider e stabile — gli stessi percorsi
servono ogni provider, {provider} seleziona la mappatura del payload.
Viator è uno skeleton documentato, generic parla questo contratto così
com'è per integrazioni su misura, GetYourGuide risponde 501 fino alla
certificazione. Solo in ingresso: l'app non spinge mai disponibilità al
partner.
Endpoint
GET /api/ota/{provider}/availability?product_id={id}&date=YYYY-MM-DD[&to_date=YYYY-MM-DD]
POST /api/ota/{provider}/bookings
POST /api/ota/{provider}/bookings/{external_reference}/cancel
{provider} è uno tra viator, getyourguide, generic. Provider
sconosciuti o disabilitati rispondono 404.
Rate limit: 60 richieste al minuto per collegamento.
Autenticazione
Ogni richiesta porta due header:
X-Ota-Connection: {public_id}— l'id pubblico del collegamento, visibile nella pagina admin dei canali OTA. Mai l'id interno.X-Ota-Signature: {hex}— HMAC-SHA256 esadecimale con chiave il segreto di firma del collegamento (mostrato una sola volta alla creazione o rotazione) calcolato su:
{METHOD}\n{REQUEST-URI}\n{RAW-BODY}
REQUEST-URI è l'esatto request target inclusa la query string —
/api/ota/viator/availability?product_id=P-1&date=2027-01-15. RAW-BODY è
il corpo non parsato (stringa vuota per le GET).
$signature = hash_hmac(
'sha256',
"POST\n/api/ota/viator/bookings\n".$rawJsonBody,
$webhookSecret,
);
Errori: collegamento sconosciuto 404 {"error":"unknown_connection"}; firma
mancante o errata 401 {"error":"bad_signature"}. L'azienda si risolve
sempre dal collegamento — il payload non può scegliere il tenant.
Mappatura prodotti
I partner vendono valori external_product_id. Ogni id si mappa
nell'interfaccia admin a un solo prenotabile — un evento o un'area — più una
price_key opzionale (null usa la risoluzione prezzo predefinita del
prenotabile). Gli id non mappati rispondono 404 {"error":"unknown_product"}.
Disponibilità
GET /api/ota/generic/availability?product_id=P-1&date=2027-01-15
{
"product_id": "P-1",
"days": [
{"date": "2027-01-15", "available": true, "remaining": 7}
]
}
availablefalse significa chiuso, esaurito o fuori dalla finestra vendita.remainingè la capacità residua;nullsignifica senza limite.- I prodotti-area restituiscono in più
windows: [{from, to, remaining}]— i segmenti vendibili del giorno. Ogni segmento ha la propria disponibilità (capienza del segmento meno il picco simultaneo, limitata da ogni pool giornaliero che il segmento occupa); ilremainingdel giorno è il gruppo più grande che entra in UN solo segmento, non il totale del giorno. - Il
remainingdi un evento è limitato da OGNI data del suo periodo — una prenotazione consuma il pool di ogni giorno che l'evento occupa. - Un evento senza fine vale solo nel suo giorno di inizio.
to_dateestende l'intervallo fino a 31 giorni.
Creare una prenotazione
POST /api/ota/generic/bookings
{
"product_id": "P-1",
"external_reference": "partner-ref-1001",
"customer": {"name": "Mario Bianchi", "email": "[email protected]", "phone": "+39002"},
"number": 2,
"from": "2027-01-15T10:00:00+00:00",
"to": "2027-01-15T11:00:00+00:00",
"date": "2027-01-15"
}
from/to valgono per i prodotti-area (finestre vendibili); date è il
giorno di calendario per i prodotti-evento e deve cadere dentro il periodo
dell'evento.
I prodotti-evento prenotano la foglia che il canale può indirizzare: un
evento semplice si prenota direttamente, un evento con fasce orarie prenota
la fascia che inizia a from (from diventa obbligatorio — mancante o non
corrispondente risponde 422), e un evento con posti risponde
available: false invece di pubblicizzare uno slot che il partner non
potrebbe mai prenotare (la scelta del posto resta sul widget).
Risposta:
{"booking": {"reference": "partner-ref-1001", "status": "confirmed",
"booking_code": "BK-AB12", "number": 2,
"created_at": "2027-01-10T09:30:00+00:00"}}
Le prenotazioni arrivano gratuite — se il prenotabile mappato richiederebbe
un pagamento la prenotazione è rifiutata con 422 {"error":"payment_required"}
e la capacità impegnata viene rilasciata. Il denaro incassato dal partner si
riconcilia fuori dall'app.
Gli errori di validazione rispondono 422 con error (booking_failed) e
una mappa fields. I replay di un riferimento fallito restituiscono lo
stesso esito registrato.
Idempotenza
external_reference è la chiave di idempotenza, unica per collegamento. Un
retry che ri-invia lo stesso riferimento riceve l'esito registrato — 200
con lo stesso payload di prenotazione — senza toccare di nuovo la capacità.
Non riusare mai un riferimento per ordini diversi.
Annullamento
POST /api/ota/{provider}/bookings/{external_reference}/cancel
Annulla la prenotazione sottostante attraverso il normale flusso di
cancellazione e porta la riga del registro a cancelled. Riferimento
sconosciuto → 404 {"error":"unknown_reference"}. Annullare un riferimento
già annullato è un no-op 200. Il rimborso del denaro incassato dal partner
è affare del partner — l'endpoint non innesca mai un rimborso.
Checklist onboarding partner
- Owner/admin crea un collegamento nella pagina dei canali OTA
(
/ota, feature di pianoota) e copia ilpublic_id. - Ruota/copia il segreto di firma una volta — dopo è solo in scrittura.
- Mappa ogni
external_product_iddel partner su un evento o un'area (+price_keyopzionale). - Il partner firma
METHOD\nREQUEST-URI\nRAW-BODYa ogni chiamata e invia entrambi gli header. - Smoke-test
availability→bookings→cancelcon un riferimento usa-e-getta, poi go-live.