Salta al contenuto principale

Canali OTA

Ultimo aggiornamento: 27 ottobre 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}
  ]
}
  • available false significa chiuso, esaurito o fuori dalla finestra vendita.
  • remaining è la capacità residua; null significa 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); il remaining del giorno è il gruppo più grande che entra in UN solo segmento, non il totale del giorno.
  • Il remaining di 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_date estende 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

  1. Owner/admin crea un collegamento nella pagina dei canali OTA (/ota, feature di piano ota) e copia il public_id.
  2. Ruota/copia il segreto di firma una volta — dopo è solo in scrittura.
  3. Mappa ogni external_product_id del partner su un evento o un'area (+ price_key opzionale).
  4. Il partner firma METHOD\nREQUEST-URI\nRAW-BODY a ogni chiamata e invia entrambi gli header.
  5. Smoke-test availability → bookings → cancel con un riferimento usa-e-getta, poi go-live.

Cookie e privacy

Utilizziamo cookie essenziali per mantenere l'applicazione sicura e funzionante correttamente. I cookie opzionali verranno utilizzati solo con il tuo consenso.

Leggi l'informativa sulla privacy Leggi la cookie policy

Essenziali

I cookie essenziali sono necessari per il funzionamento del sito e non possono essere disattivati.

Sempre attivi

Funzionali

I cookie funzionali abilitano funzionalità avanzate e personalizzazione, come il ricordo della lingua e delle preferenze.

Analitici

I cookie analitici ci aiutano a capire come i visitatori interagiscono con l'applicazione per poterla migliorare.

Marketing

I cookie di marketing vengono utilizzati per tracciare i visitatori sui siti web al fine di mostrare annunci pertinenti e coinvolgenti.