{
  "openapi": "3.1.0",
  "info": {
    "title": "Vacanze Sicure Partner Distribution & Booking API",
    "version": "0.9.2",
    "description": "Contratto pubblico per partner autorizzati. Copre catalogo risorse, disponibilita, hold e prenotazioni, incluse informazioni di ricerca utili al noleggio come localita di ritiro/restituzione, eta conducente, preferenze carburante/chilometraggio e requisiti di pagamento.",
    "termsOfService": "https://www.vacanzesicure.online/api/partner/"
  },
  "externalDocs": {
    "description": "Documentazione pubblica Partner API",
    "url": "https://www.vacanzesicure.online/api/partner/"
  },
  "servers": [{"url":"https://www.vacanzesicure.online/api/partner/v1"}],
  "security": [{"bearerAuth":[]}],
  "tags": [
    {"name":"Resources","description":"Catalogo delle risorse abilitate per il client partner."},
    {"name":"Availability","description":"Ricerca disponibilita e condizioni applicabili."},
    {"name":"Holds","description":"Blocco temporaneo della risorsa durante il checkout."},
    {"name":"Bookings","description":"Conferma, lettura e cancellazione delle prenotazioni del client autorizzato."}
  ],
  "paths": {
    "/resources.php": {
      "get": {
        "tags":["Resources"],
        "summary":"Elenca le risorse abilitate per il partner",
        "description":"Restituisce soltanto le risorse comprese nel perimetro autorizzato. Per le risorse di noleggio puo includere requisiti pubblicabili come eta conducente, one-way, politiche carburante, chilometraggio, carte accettate, deposito/franchigia, patente e fuori orario.",
        "operationId":"partnerListResources",
        "parameters":[
          {"name":"category","in":"query","description":"Categoria della risorsa.","schema":{"type":"string"}},
          {"name":"location","in":"query","description":"Localita o area servita.","schema":{"type":"string"}},
          {"name":"resource_group","in":"query","description":"Raggruppamento concordato per l'integrazione.","schema":{"type":"string"}}
        ],
        "responses":{
          "200":{"description":"Catalogo filtrato per il client autorizzato."},
          "401":{"description":"Autenticazione assente o non valida."},
          "403":{"description":"Permesso insufficiente."},
          "503":{"description":"Servizio o integrazione non disponibile."}
        }
      }
    },
    "/availability.php": {
      "post": {
        "tags":["Availability"],
        "summary":"Cerca risorse prenotabili nell'intervallo richiesto",
        "description":"Verifica disponibilita, quantita, prezzo e compatibilita con i requisiti della richiesta. Per il noleggio supporta un contesto specifico senza rendere obbligatori campi non pertinenti ad altre categorie.",
        "operationId":"partnerSearchAvailability",
        "requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AvailabilityRequest"}}}},
        "responses":{
          "200":{"description":"Soluzioni compatibili con la richiesta."},
          "401":{"description":"Autenticazione assente o non valida."},
          "403":{"description":"Permesso insufficiente."},
          "422":{"description":"Richiesta semanticamente non valida."},
          "503":{"description":"Servizio o integrazione non disponibile."}
        }
      }
    },
    "/holds.php": {
      "post": {
        "tags":["Holds"],
        "summary":"Crea un hold temporaneo sulla risorsa",
        "description":"Ricontrolla compatibilita e disponibilita, quindi crea un blocco temporaneo. Il contesto di noleggio viene conservato nell'hold per la successiva conferma.",
        "operationId":"partnerCreateHold",
        "parameters":[{"name":"Idempotency-Key","in":"header","required":true,"description":"Chiave univoca generata dal client per rendere sicuri i retry.","schema":{"type":"string","minLength":8}}],
        "requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HoldRequest"}}}},
        "responses":{
          "201":{"description":"Hold creato."},
          "401":{"description":"Autenticazione assente o non valida."},
          "403":{"description":"Permesso insufficiente."},
          "409":{"description":"Disponibilita cambiata o requisiti non compatibili."},
          "422":{"description":"Richiesta semanticamente non valida."},
          "503":{"description":"Servizio o integrazione non disponibile."}
        }
      }
    },
    "/bookings.php": {
      "get": {
        "tags":["Bookings"],
        "summary":"Legge una prenotazione del client autorizzato",
        "operationId":"partnerGetBooking",
        "parameters":[{"name":"reference","in":"query","required":true,"description":"Riferimento Vacanze Sicure della prenotazione.","schema":{"type":"string"}}],
        "responses":{
          "200":{"description":"Prenotazione."},
          "401":{"description":"Autenticazione assente o non valida."},
          "403":{"description":"Permesso insufficiente."},
          "404":{"description":"Prenotazione non trovata nel perimetro autorizzato."}
        }
      },
      "post": {
        "tags":["Bookings"],
        "summary":"Conferma un hold o richiede la cancellazione di una prenotazione",
        "description":"La conferma puo includere un riferimento di arrivo utile all'operativita, per esempio numero volo o treno, senza rendere tale dato obbligatorio per tutte le categorie.",
        "operationId":"partnerWriteBooking",
        "parameters":[{"name":"Idempotency-Key","in":"header","required":true,"description":"Chiave univoca generata dal client per rendere sicuri i retry.","schema":{"type":"string","minLength":8}}],
        "requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/BookingConfirmRequest"},{"$ref":"#/components/schemas/BookingCancelRequest"}]}}}},
        "responses":{
          "201":{"description":"Prenotazione confermata."},
          "200":{"description":"Operazione completata o cancellazione registrata."},
          "401":{"description":"Autenticazione assente o non valida."},
          "403":{"description":"Permesso insufficiente."},
          "404":{"description":"Prenotazione non trovata nel perimetro autorizzato."},
          "409":{"description":"Hold scaduto/non valido o prenotazione non cancellabile."},
          "422":{"description":"Richiesta semanticamente non valida."}
        }
      }
    }
  },
  "components": {
    "securitySchemes":{
      "bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"opaque partner credential","description":"Credenziale fornita al client attraverso un canale riservato durante l'onboarding."}
    },
    "schemas": {
      "RentalContext": {
        "type":"object",
        "description":"Contesto opzionale per risorse di noleggio. I campi non pertinenti possono essere omessi.",
        "properties":{
          "pickup_location":{"type":"string","description":"Localita o punto di ritiro richiesto."},
          "dropoff_location":{"type":"string","description":"Localita o punto di restituzione; puo differire dal ritiro se la soluzione ammette one-way."},
          "driver_age":{"type":"integer","minimum":16,"maximum":100,"description":"Eta del conducente principale, usata per verificare requisiti o supplementi applicabili."},
          "residence_country":{"type":"string","description":"Paese di residenza quando rilevante alle condizioni dell'offerta."},
          "payment_card_type":{"type":"string","description":"Tipo di carta disponibile al ritiro, per esempio credit o debit."},
          "fuel_policy":{"type":"string","description":"Preferenza sulla politica carburante, se supportata dall'offerta."},
          "mileage_preference":{"type":"string","enum":["unlimited","limited","any"]}
        }
      },
      "ArrivalInfo": {
        "type":"object",
        "description":"Riferimento operativo opzionale all'arrivo del viaggiatore.",
        "properties":{
          "mode":{"type":"string","description":"Esempio: flight, train, ferry."},
          "reference":{"type":"string","description":"Numero o riferimento del viaggio, quando necessario al servizio."},
          "scheduled_at":{"type":"string","format":"date-time"}
        }
      },
      "AvailabilityRequest": {
        "type":"object",
        "required":["start_at","end_at"],
        "properties":{
          "start_at":{"type":"string","format":"date-time"},
          "end_at":{"type":"string","format":"date-time"},
          "category":{"type":"string"},
          "location":{"type":"string"},
          "resource_group":{"type":"string"},
          "quantity":{"type":"integer","minimum":1,"default":1},
          "extras":{"type":"array","items":{"type":"string"}},
          "rental":{"$ref":"#/components/schemas/RentalContext"}
        }
      },
      "HoldRequest": {
        "type":"object",
        "required":["resource_id","start_at","end_at"],
        "properties":{
          "resource_id":{"type":"string"},
          "start_at":{"type":"string","format":"date-time"},
          "end_at":{"type":"string","format":"date-time"},
          "quantity":{"type":"integer","minimum":1},
          "extras":{"type":"array","items":{"type":"string"}},
          "rental":{"$ref":"#/components/schemas/RentalContext"}
        }
      },
      "BookingConfirmRequest": {
        "type":"object",
        "required":["hold_id"],
        "properties":{
          "action":{"type":"string","const":"confirm","default":"confirm"},
          "hold_id":{"type":"string"},
          "partner_booking_reference":{"type":"string"},
          "traveler_ref":{"type":"string","description":"Riferimento opaco del viaggiatore nel sistema partner; evitare dati personali se non necessari."},
          "arrival_info":{"$ref":"#/components/schemas/ArrivalInfo"}
        }
      },
      "BookingCancelRequest": {
        "type":"object",
        "required":["action","reference"],
        "properties":{
          "action":{"type":"string","const":"cancel"},
          "reference":{"type":"string"},
          "reason":{"type":"string"}
        }
      }
    }
  },
  "x-vs-access": {
    "status":"public_documentation_access_by_onboarding",
    "required_scopes":["resources:read","availability:read","holds:write","bookings:read","bookings:write"],
    "notes":[
      "L'accesso operativo richiede un client autorizzato.",
      "Il client vede esclusivamente le risorse comprese nel proprio perimetro.",
      "Le credenziali non sono pubblicate nella documentazione o nel repository.",
      "Le condizioni specifiche dell'offerta prevalgono sui valori generici di categoria."
    ]
  }
}
