Aller directement au contenu principal

Canali OTA

Cette page n'est pas encore disponible dans votre langue. Affichage de la version par défaut.

Dernière mise à jour : 27 octobre 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.

Cookies et confidentialité

Nous utilisons des cookies indispensables pour garantir la sécurité et le bon fonctionnement de l'application. Les cookies facultatifs ne seront utilisés qu'avec votre consentement.

Consultez la politique de confidentialité Consultez la politique relative aux cookies

Indispensable

Les cookies essentiels sont indispensables au bon fonctionnement du site web et ne peuvent pas être désactivés.

Toujours activé

Fonctionnel

Les cookies fonctionnels permettent d'améliorer les fonctionnalités et la personnalisation, par exemple en mémorisant votre langue et vos préférences.

Analytique

Les cookies d'analyse nous aident à comprendre comment les visiteurs interagissent avec l'application afin que nous puissions l'améliorer.

Marketing

Les cookies marketing servent à suivre les visiteurs d'un site web à l'autre afin de leur proposer des publicités pertinentes et attrayantes.