{
  "openapi": "3.1.0",
  "info": {
    "title": "VacoTours OCTO API",
    "version": "2.0.0",
    "summary": "Every tour and activity we sell, over the OCTO standard.",
    "description": "An implementation of the OCTO specification (Open Connectivity for Tours, Activities and Attractions), covering every product we sell: our own operators' inventory and the channel inventory we resell, through one model.\n\nEverything a storefront needs is here: the catalogue with photos, descriptions, itineraries and meeting points; a price calendar; live availability by start time; the operator's questions; pickup points; a two step booking with vouchers as QR codes and PDFs; cancellation with the refund worked out for you; and webhooks when anything changes.\n\n## Authentication\n\nSend your token as a bearer credential. It is two halves joined by a dot, `{key}.{secret}`. The secret half is shown once, when the key is issued in your panel.\n\n```http\nAuthorization: Bearer vt_live_xxxxx.sk_xxxxx\n```\n\nA `vt_test_` key is a sandbox key on the same host. Everything works exactly as with a live key, including holds on your wallet, except that a booking made with it is marked `testMode: true`, never reaches the operator and never appears on their manifest.\n\nTrade buyer (reseller) keys can use everything, over the products the key is set to export. An operator's key imports its products through the [Supplier API](/developers/supplier-api) and exports none, its own included: here it is refused on the catalogue, availability and suppliers, and can only read the bookings of its own inventory, cancel them and redeem vouchers at the gate.\n\n## Capabilities\n\nA bare response carries only the core fields, which notably means **no prices**. Ask for more with the `Octo-Capabilities` header, comma separated. The response echoes the capabilities that were applied.\n\n```http\nOcto-Capabilities: octo/pricing, octo/content, octo/questions, octo/pickups, octo/cancellation\n```\n\n| Capability | Adds |\n| --- | --- |\n| `octo/pricing` | Prices on options, units, availability and bookings |\n| `octo/content` | Titles, descriptions, highlights, inclusions, photos, itinerary, meeting point, destination, categories, FAQ |\n| `octo/questions` | What the operator asks before they take a booking |\n| `octo/pickups` | Pickup and dropoff points |\n| `octo/cancellation` | The refund ladder as structured tiers |\n| `octo/webhooks` | Subscribe to changes on your bookings |\n| `octo/mappings` | Every product, option and unit you can sell, flat |\n| `octo/redemption` | Mark a booking used at the gate |\n\n## Languages\n\nThe catalogue is served in six languages: English (`en`), Persian (`fa`), Russian (`ru`), Arabic (`ar`), Hindi (`hi`) and Simplified Chinese (`zh-Hans`). Ask for one with the `Accept-Language` header or `?language=`; the response says which it used in `Content-Language`.\n\n```http\nAccept-Language: fa\n```\n\nOperators write in English and the other five are translated from it as a product is published or reworded, so a product's words can lag its English by a little while. A field not yet translated comes back in English rather than empty, and `product.availableLocales` lists the languages a product has. Anything you are not sent a language for (a region tag such as `ru-RU` is fine) is answered in English.\n\n## Which products\n\nEvery product is one of two kinds, and says which in `product.source`:\n\n| source | Means |\n| --- | --- |\n| `direct` | Run by one of our own operators, who lists it with us |\n| `channel` | Resold from a partner platform |\n\nEach key is set, in your panel under API keys, to export all products, only direct ones or only channel ones. A key set to direct can be narrowed further to one operator or several you choose. A key never sees anything else: not in the catalogue, not by id, not to book.\n\n`GET /whoami` says what the key is set to in `productSource`, and the operators it is narrowed to in `suppliers` (null is every operator); `GET /suppliers` lists those alone. Any catalogue request can narrow further with `?source=direct` or `?source=channel`; it cannot widen what the key is set to.\n\n## Prices\n\nMoney is an integer in the currency's minor units, with an explicit `currencyPrecision`. Every Pricing object carries two figures:\n\n| Field | For a trade buyer |\n| --- | --- |\n| `net` | What you pay us. This is what your wallet is charged. |\n| `retail` | What a traveller pays on our own site: our recommended selling price. |\n\nChoose the currency with `X-Currency: EUR` or `?currency=EUR`. A booking read back in the currency it was made in shows the amounts at the rate captured when it was made.\n\nA product with `pricingPer: BOOKING` (a private tour, a charter, a car with driver) is one price for the whole party. Its units carry no price of their own; read the party price from `pricing` on an availability, and do not multiply it.\n\n## Building a storefront\n\n1. `GET /products?limit=50&offset=0` pages through the catalogue (`X-Total-Count` has the total). Use `updatedSince` for nightly syncs.\n2. `POST /availability/calendar` paints a month: one object per operating day with its \"from\" price.\n3. `POST /availability` with the party (`units`) lists the start times on a date that can take that party, each priced for it. Its `id` is the `availabilityId` you book.\n4. Ask the option's `questions`. A question with `perUnitItem: true` is asked of every traveller.\n5. `POST /bookings` reserves: seats and funds are held, the booking is `ON_HOLD` until `utcExpiresAt`.\n6. `POST /bookings/{uuid}/confirm` sells it: funds are captured and vouchers issued (`QRCODE` and a `PDF_URL` your traveller can open).\n7. `POST /bookings/{uuid}/cancel` cancels, refunding to your wallet on the operator's terms.\n\nAn unconfirmed hold expires by itself and releases everything, so a payment that fails on your side costs nothing.\n\n## Rentals and stays\n\nAn option with `rental` is booked from one date to another: a car or a scooter by the day, a villa by the night, a jet ski by the hour, travel cover by the day. `rental.basis` says how the length is counted (`day` is 24 hour periods from pickup to return, `night` is check-in to check-out, `hour` is started hours), and `minLength` and `maxLength` bound it.\n\nPrices on the calendar and on a plain availability are for one day, night or hour. To price and check a whole period, send `rental` with `POST /availability`:\n\n```json\n{ \"productId\": \"...\", \"optionId\": \"...\", \"localDate\": \"2026-10-03\",\n  \"units\": [{ \"id\": \"...\", \"quantity\": 1 }],\n  \"rental\": { \"returnDate\": \"2026-10-07\", \"pickupTime\": \"10:00\", \"returnTime\": \"10:00\" } }\n```\n\nEach availability then answers for the whole period: `available` is false (with the reason in `statusMessage`) when any date in it is closed or full, when the boat or car is out, or when the length is outside the limits, and `pricing` and `unitPricing` are for the whole of it, longer bookings at their cheaper rate. Book with the same `rental` on `POST /bookings`; the booking carries it back. Without `rental`, a booking is for the shortest length the option allows. `returnLocation` is accepted only where `rental.oneWay` is true, and adds `oneWayFee`.\n\n## Priced on request\n\nA product with `quoteOnly: true` (a tailor-made itinerary, a company incentive) has no calendar: the operator prices each group by hand. Ask with `POST /quote-requests` (group size, dates, budget, what your client wants). When the operator answers, `GET /quote-requests/{uuid}` has `status: quoted`, the `price` you pay for the whole group (and `recommendedRetail`), and `validUntil`. `POST /quote-requests/{uuid}/accept` turns it into an ordinary booking `ON_HOLD`, which you confirm with `POST /bookings/{uuid}/confirm` as usual. Our webhooks do not cover quotes yet: poll `GET /quote-requests?status=quoted`.\n\n## Errors\n\nEvery error is `{ \"error\": CODE, \"errorMessage\": \"...\" }` with a matching status. The ones to handle:\n\n| Status, error | Meaning |\n| --- | --- |\n| 400 `UNAVAILABLE` | The time sold out, or cannot take this party. Check availability again. |\n| 400 `UNPROCESSABLE_ENTITY` | The booking breaks a rule: a missing answer, a choice not offered, a party too large. The message says which, in words you can show. |\n| 400 `BAD_REQUEST` | The request itself is malformed. `errors` lists the fields. |\n| 400 `INVALID_PRODUCT_ID`, `INVALID_OPTION_ID`, `INVALID_UNIT_ID` | An id that is not in the catalogue for your key. |\n| 401, 403 | The key is missing, wrong, revoked, or not allowed this endpoint. |\n| 429 `TOO_MANY_REQUESTS` | Over your limit. `Retry-After` says when to try again. |\n\n## Rate limits\n\nPer key, 120 requests a minute by default, reported in `X-RateLimit-Limit` and `X-RateLimit-Remaining`. Ask us if you need more.",
    "contact": {
      "name": "VacoTours partner support",
      "email": "hello@vacotours.com",
      "url": "https://vacotours.com/for-partners"
    },
    "license": {
      "name": "Proprietary"
    }
  },
  "servers": [
    {
      "url": "https://api.vacotours.com/octo",
      "description": "Production and sandbox (use a vt_test_ key for sandbox)"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Discovery",
      "description": "Who you are and what is supported."
    },
    {
      "name": "Quotes",
      "description": "Products priced on request: ask, read the answer, book it."
    },
    {
      "name": "Products",
      "description": "The catalogue."
    },
    {
      "name": "Availability",
      "description": "What can be sold, when, and for how much."
    },
    {
      "name": "Bookings",
      "description": "Reserve, confirm, amend, cancel and redeem."
    },
    {
      "name": "Webhooks",
      "description": "Hear about changes to your bookings."
    }
  ],
  "paths": {
    "/capabilities": {
      "get": {
        "tags": [
          "Discovery"
        ],
        "summary": "Capabilities",
        "description": "What this server implements. Open, no key needed.",
        "operationId": "capabilities",
        "responses": {
          "200": {
            "description": "The capabilities.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "string"
                      },
                      "revision": {
                        "type": "integer"
                      },
                      "required": {
                        "type": "boolean"
                      },
                      "docs": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": []
      }
    },
    "/whoami": {
      "get": {
        "tags": [
          "Discovery"
        ],
        "summary": "Your key",
        "description": "Who the key belongs to, its environment and scopes, which products it exports (`productSource`, null for an operator's key, which exports none) and, for a direct key narrowed to some operators, which (`suppliers`; null is every operator).",
        "operationId": "whoami",
        "responses": {
          "200": {
            "description": "The key.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "id": "ec3cfb7b-1bbc-4bfb-b91c-cced32426bcb",
                  "name": "Northbound Travel",
                  "type": "reseller",
                  "environment": "sandbox",
                  "endpoint": "https://api.vacotours.com/octo",
                  "capabilities": [
                    "octo/pricing",
                    "octo/content",
                    "octo/questions",
                    "octo/pickups",
                    "octo/cancellation",
                    "octo/webhooks",
                    "octo/mappings",
                    "octo/redemption"
                  ],
                  "scopes": [
                    "products:read",
                    "availability:read",
                    "bookings:read",
                    "bookings:write"
                  ],
                  "productSource": "all",
                  "suppliers": null
                }
              }
            }
          },
          "400": {
            "description": "Rejected. See error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "This key may not do that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Over the rate limit. Retry-After says when.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/suppliers": {
      "get": {
        "tags": [
          "Discovery"
        ],
        "summary": "Suppliers",
        "description": "The operators whose products your key exports. A key narrowed to some operators lists those alone. Trade buyer keys only.",
        "operationId": "suppliers",
        "responses": {
          "200": {
            "description": "Suppliers.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Rejected. See error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "This key may not do that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Over the rate limit. Retry-After says when.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/suppliers/{supplierId}": {
      "get": {
        "tags": [
          "Discovery"
        ],
        "summary": "A supplier",
        "description": "One operator. One a narrowed key does not export is not found.",
        "operationId": "supplier",
        "responses": {
          "200": {
            "description": "The supplier.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Rejected. See error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "This key may not do that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Over the rate limit. Retry-After says when.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "supplierId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/products": {
      "get": {
        "tags": [
          "Products"
        ],
        "summary": "List products",
        "description": "The catalogue, a page at a time, newest popular first. `X-Total-Count` has the total. Channel products are fetched from their sources in parallel; a page takes a few seconds cold and well under one warm.",
        "operationId": "listProducts",
        "responses": {
          "200": {
            "description": "Products.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Product"
                  }
                },
                "example": [
                  {
                    "id": "c86ea1c1-a986-4d1f-bd23-6bec906beffa",
                    "internalName": "Sultanahmet Sunrise Walk",
                    "reference": "old-istanbul-at-first-light-sultanahmet-walking-tour",
                    "locale": "en",
                    "timeZone": "Europe/Istanbul",
                    "allowFreesale": false,
                    "instantConfirmation": true,
                    "instantDelivery": true,
                    "availabilityRequired": true,
                    "availabilityType": "START_TIME",
                    "deliveryFormats": [
                      "PDF_URL",
                      "QRCODE"
                    ],
                    "deliveryMethods": [
                      "TICKET",
                      "VOUCHER"
                    ],
                    "redemptionMethod": "DIGITAL",
                    "options": [
                      {
                        "id": "d7bbe7df-6d64-45a8-b8f9-69dace2d4f9c",
                        "default": true,
                        "internalName": "Sunrise departure (07:00)",
                        "reference": null,
                        "availabilityLocalStartTimes": [
                          "07:00"
                        ],
                        "cancellationCutoff": "24 hours",
                        "cancellationCutoffAmount": 24,
                        "cancellationCutoffUnit": "hour",
                        "availabilityCutoff": "24 hours",
                        "availabilityCutoffAmount": 24,
                        "availabilityCutoffUnit": "hour",
                        "availabilityLocalDateStart": null,
                        "availabilityLocalDateEnd": null,
                        "requiredContactFields": [
                          "firstName",
                          "lastName",
                          "emailAddress"
                        ],
                        "visibleContactFields": [
                          "firstName",
                          "lastName",
                          "emailAddress",
                          "phoneNumber",
                          "country"
                        ],
                        "restrictions": {
                          "minUnits": 0,
                          "maxUnits": null,
                          "minPaxCount": 0,
                          "maxPaxCount": 12
                        },
                        "units": [
                          {
                            "id": "0d04e5e0-67cb-4f6c-aa87-d5d3be2744cb",
                            "internalName": "Adult",
                            "reference": "adult",
                            "type": "ADULT",
                            "requiredContactFields": [],
                            "visibleContactFields": [
                              "firstName",
                              "lastName"
                            ],
                            "restrictions": {
                              "minAge": 18,
                              "maxAge": 64,
                              "idRequired": false,
                              "minQuantity": null,
                              "maxQuantity": 20,
                              "paxCount": 1,
                              "accompaniedBy": [],
                              "required": false
                            },
                            "pricingFrom": [
                              {
                                "original": 3826,
                                "retail": 3826,
                                "net": 3364,
                                "currency": "USD",
                                "currencyPrecision": 2,
                                "includedTaxes": []
                              }
                            ],
                            "unit": {
                              "title": "Adult",
                              "titlePlural": "Adults",
                              "category": "adult",
                              "ageLabel": "Age 18 to 64"
                            }
                          },
                          {
                            "id": "cd1ae236-fe8a-4735-9d82-ba15a1266cfe",
                            "internalName": "Child",
                            "reference": "child",
                            "type": "CHILD",
                            "requiredContactFields": [],
                            "visibleContactFields": [
                              "firstName",
                              "lastName"
                            ],
                            "restrictions": {
                              "minAge": 3,
                              "maxAge": 12,
                              "idRequired": false,
                              "minQuantity": null,
                              "maxQuantity": 20,
                              "paxCount": 1,
                              "accompaniedBy": [],
                              "required": false
                            },
                            "pricingFrom": [
                              {
                                "original": 2186,
                                "retail": 2186,
                                "net": 1991,
                                "currency": "USD",
                                "currencyPrecision": 2,
                                "includedTaxes": []
                              }
                            ],
                            "unit": {
                              "title": "Child",
                              "titlePlural": "Childs",
                              "category": "child",
                              "ageLabel": "Age 3 to 12"
                            }
                          },
                          {
                            "id": "dc694a09-2fd9-42bd-be08-576f943ced39",
                            "internalName": "Senior",
                            "reference": "senior",
                            "type": "SENIOR",
                            "requiredContactFields": [],
                            "visibleContactFields": [
                              "firstName",
                              "lastName"
                            ],
                            "restrictions": {
                              "minAge": 65,
                              "maxAge": 120,
                              "idRequired": false,
                              "minQuantity": null,
                              "maxQuantity": 20,
                              "paxCount": 1,
                              "accompaniedBy": [],
                              "required": false
                            },
                            "pricingFrom": [
                              {
                                "original": 3279,
                                "retail": 3279,
                                "net": 2907,
                                "currency": "USD",
                                "currencyPrecision": 2,
                                "includedTaxes": []
                              }
                            ],
                            "unit": {
                              "title": "Senior",
                              "titlePlural": "Seniors",
                              "category": "senior",
                              "ageLabel": "Age 65+"
                            }
                          },
                          {
                            "id": "8a6665ad-8df0-4c5c-8d8d-39381ee15944",
                            "internalName": "Student",
                            "reference": "student",
                            "type": "STUDENT",
                            "requiredContactFields": [],
                            "visibleContactFields": [
                              "firstName",
                              "lastName"
                            ],
                            "restrictions": {
                              "minAge": 13,
                              "maxAge": 17,
                              "idRequired": false,
                              "minQuantity": null,
                              "maxQuantity": 20,
                              "paxCount": 1,
                              "accompaniedBy": [],
                              "required": false
                            },
                            "pricingFrom": [
                              {
                                "original": 3006,
                                "retail": 3006,
                                "net": 2678,
                                "currency": "USD",
                                "currencyPrecision": 2,
                                "includedTaxes": []
                              }
                            ],
                            "unit": {
                              "title": "Student",
                              "titlePlural": "Students",
                              "category": "student",
                              "ageLabel": "Age 13 to 17"
                            }
                          }
                        ],
                        "pricingFrom": [
                          {
                            "original": 3006,
                            "retail": 3006,
                            "net": 2678,
                            "currency": "USD",
                            "currencyPrecision": 2,
                            "includedTaxes": []
                          }
                        ],
                        "option": {
                          "title": "Sunrise departure (07:00)",
                          "subtitle": "The quiet one. Meets at the Hippodrome obelisk.",
                          "shortDescription": "The quiet one. Meets at the Hippodrome obelisk.",
                          "language": "en",
                          "duration": "3 hours",
                          "durationAmount": "180",
                          "durationUnit": "minute",
                          "instantConfirmation": true,
                          "meetingPoint": {
                            "time": "06:45",
                            "address": "Obelisk of Theodosius, Sultanahmet Square",
                            "latitude": 41.0082,
                            "longitude": 28.9784
                          },
                          "validity": {
                            "type": "only_visit_date"
                          },
                          "voucher": {
                            "requiresPrinting": false,
                            "directAdmission": true
                          },
                          "itinerary": [
                            {
                              "day": 1,
                              "name": "Hippodrome and the Obelisk",
                              "type": "stop",
                              "description": "Where the chariots ran, and why three monuments from three civilisations stand in a row.",
                              "durationAmount": 30,
                              "durationUnit": "minute"
                            },
                            {
                              "day": 1,
                              "name": "Blue Mosque courtyard",
                              "type": "stop",
                              "durationAmount": 40,
                              "durationUnit": "minute"
                            },
                            {
                              "day": 1,
                              "name": "Hagia Sophia exterior",
                              "type": "stop",
                              "durationAmount": 45,
                              "durationUnit": "minute"
                            },
                            {
                              "day": 1,
                              "name": "Soğukçeşme Street",
                              "type": "stop",
                              "durationAmount": 25,
                              "durationUnit": "minute"
                            },
                            {
                              "day": 1,
                              "name": "Tea garden, Gülhane",
                              "type": "stop",
                              "durationAmount": 40,
                              "durationUnit": "minute"
                            }
                          ]
                        },
                        "isRefundable": true,
                        "cancellationPolicies": [
                          {
                            "cutoffHours": 168,
                            "refundPercentage": 100,
                            "cancellationFeePercentage": 0,
                            "serviceFee": {
                              "original": 0,
                              "retail": 0,
                              "net": 0,
                              "currency": "USD",
                              "currencyPrecision": 2,
                              "includedTaxes": []
                            },
                            "serviceFeePerBooking": true
                          },
                          {
                            "cutoffHours": 48,
                            "refundPercentage": 50,
                            "cancellationFeePercentage": 0,
                            "serviceFee": {
                              "original": 0,
                              "retail": 0,
                              "net": 0,
                              "currency": "USD",
                              "currencyPrecision": 2,
                              "includedTaxes": []
                            },
                            "serviceFeePerBooking": true
                          },
                          {
                            "cutoffHours": 24,
                            "refundPercentage": 0,
                            "cancellationFeePercentage": 0,
                            "serviceFee": {
                              "original": 0,
                              "retail": 0,
                              "net": 0,
                              "currency": "USD",
                              "currencyPrecision": 2,
                              "includedTaxes": []
                            },
                            "serviceFeePerBooking": true
                          }
                        ],
                        "questions": [],
                        "pickupAvailable": false,
                        "pickupRequired": false,
                        "pickupPoints": [],
                        "dropoffAvailable": false,
                        "dropoffRequired": false,
                        "dropoffPoints": []
                      },
                      {
                        "id": "f44835e5-6d4e-47bc-8a38-2e53e4f6897e",
                        "default": false,
                        "internalName": "Mid-morning departure (09:30)",
                        "reference": null,
                        "availabilityLocalStartTimes": [
                          "09:30"
                        ],
                        "cancellationCutoff": "24 hours",
                        "cancellationCutoffAmount": 24,
                        "cancellationCutoffUnit": "hour",
                        "availabilityCutoff": "24 hours",
                        "availabilityCutoffAmount": 24,
                        "availabilityCutoffUnit": "hour",
                        "availabilityLocalDateStart": null,
                        "availabilityLocalDateEnd": null,
                        "requiredContactFields": [
                          "firstName",
                          "lastName",
                          "emailAddress"
                        ],
                        "visibleContactFields": [
                          "firstName",
                          "lastName",
                          "emailAddress",
                          "phoneNumber",
                          "country"
                        ],
                        "restrictions": {
                          "minUnits": 0,
                          "maxUnits": null,
                          "minPaxCount": 0,
                          "maxPaxCount": null
                        },
                        "units": [
                          {
                            "id": "524b8ba7-8582-4f3f-8d35-4dc92ce96db9",
                            "internalName": "Adult",
                            "reference": "adult",
                            "type": "ADULT",
                            "requiredContactFields": [],
                            "visibleContactFields": [
                              "firstName",
                              "lastName"
                            ],
                            "restrictions": {
                              "minAge": 18,
                              "maxAge": 64,
                              "idRequired": false,
                              "minQuantity": null,
                              "maxQuantity": 20,
                              "paxCount": 1,
                              "accompaniedBy": [],
                              "required": false
                            },
                            "pricingFrom": [
                              {
                                "original": 3416,
                                "retail": 3416,
                                "net": 3021,
                                "currency": "USD",
                                "currencyPrecision": 2,
                                "includedTaxes": []
                              }
                            ],
                            "unit": {
                              "title": "Adult",
                              "titlePlural": "Adults",
                              "category": "adult",
                              "ageLabel": "Age 18 to 64"
                            }
                          },
                          {
                            "id": "d1553620-ebe4-4a6d-aba8-6e28bbf3eeb1",
                            "internalName": "Child",
                            "reference": "child",
                            "type": "CHILD",
                            "requiredContactFields": [],
                            "visibleContactFields": [
                              "firstName",
                              "lastName"
                            ],
                            "restrictions": {
                              "minAge": 3,
                              "maxAge": 12,
                              "idRequired": false,
                              "minQuantity": null,
                              "maxQuantity": 20,
                              "paxCount": 1,
                              "accompaniedBy": [],
                              "required": false
                            },
                            "pricingFrom": [
                              {
                                "original": 1913,
                                "retail": 1913,
                                "net": 1762,
                                "currency": "USD",
                                "currencyPrecision": 2,
                                "includedTaxes": []
                              }
                            ],
                            "unit": {
                              "title": "Child",
                              "titlePlural": "Childs",
                              "category": "child",
                              "ageLabel": "Age 3 to 12"
                            }
                          },
                          {
                            "id": "2604fe39-f7f8-470d-89ca-d79b64838b74",
                            "internalName": "Senior",
                            "reference": "senior",
                            "type": "SENIOR",
                            "requiredContactFields": [],
                            "visibleContactFields": [
                              "firstName",
                              "lastName"
                            ],
                            "restrictions": {
                              "minAge": 65,
                              "maxAge": 120,
                              "idRequired": false,
                              "minQuantity": null,
                              "maxQuantity": 20,
                              "paxCount": 1,
                              "accompaniedBy": [],
                              "required": false
                            },
                            "pricingFrom": [
                              {
                                "original": 3006,
                                "retail": 3006,
                                "net": 2678,
                                "currency": "USD",
                                "currencyPrecision": 2,
                                "includedTaxes": []
                              }
                            ],
                            "unit": {
                              "title": "Senior",
                              "titlePlural": "Seniors",
                              "category": "senior",
                              "ageLabel": "Age 65+"
                            }
                          },
                          {
                            "id": "abcfe31b-64ef-4f46-baf5-cc618b435919",
                            "internalName": "Student",
                            "reference": "student",
                            "type": "STUDENT",
                            "requiredContactFields": [],
                            "visibleContactFields": [
                              "firstName",
                              "lastName"
                            ],
                            "restrictions": {
                              "minAge": 13,
                              "maxAge": 17,
                              "idRequired": false,
                              "minQuantity": null,
                              "maxQuantity": 20,
                              "paxCount": 1,
                              "accompaniedBy": [],
                              "required": false
                            },
                            "pricingFrom": [
                              {
                                "original": 2733,
                                "retail": 2733,
                                "net": 2449,
                                "currency": "USD",
                                "currencyPrecision": 2,
                                "includedTaxes": []
                              }
                            ],
                            "unit": {
                              "title": "Student",
                              "titlePlural": "Students",
                              "category": "student",
                              "ageLabel": "Age 13 to 17"
                            }
                          }
                        ],
                        "pricingFrom": [
                          {
                            "original": 2733,
                            "retail": 2733,
                            "net": 2449,
                            "currency": "USD",
                            "currencyPrecision": 2,
                            "includedTaxes": []
                          }
                        ],
                        "option": {
                          "title": "Mid-morning departure (09:30)",
                          "language": "en",
                          "duration": "3 hours",
                          "durationAmount": "180",
                          "durationUnit": "minute",
                          "instantConfirmation": true,
                          "meetingPoint": {
                            "time": "09:15",
                            "address": "Obelisk of Theodosius, Sultanahmet Square",
                            "latitude": 41.0082,
                            "longitude": 28.9784
                          },
                          "validity": {
                            "type": "only_visit_date"
                          },
                          "voucher": {
                            "requiresPrinting": false,
                            "directAdmission": true
                          }
                        },
                        "isRefundable": true,
                        "cancellationPolicies": [
                          {
                            "cutoffHours": 168,
                            "refundPercentage": 100,
                            "cancellationFeePercentage": 0,
                            "serviceFee": {
                              "original": 0,
                              "retail": 0,
                              "net": 0,
                              "currency": "USD",
                              "currencyPrecision": 2,
                              "includedTaxes": []
                            },
                            "serviceFeePerBooking": true
                          },
                          {
                            "cutoffHours": 48,
                            "refundPercentage": 50,
                            "cancellationFeePercentage": 0,
                            "serviceFee": {
                              "original": 0,
                              "retail": 0,
                              "net": 0,
                              "currency": "USD",
                              "currencyPrecision": 2,
                              "includedTaxes": []
                            },
                            "serviceFeePerBooking": true
                          },
                          {
                            "cutoffHours": 24,
                            "refundPercentage": 0,
                            "cancellationFeePercentage": 0,
                            "serviceFee": {
                              "original": 0,
                              "retail": 0,
                              "net": 0,
                              "currency": "USD",
                              "currencyPrecision": 2,
                              "includedTaxes": []
                            },
                            "serviceFeePerBooking": true
                          }
                        ],
                        "questions": [],
                        "pickupAvailable": false,
                        "pickupRequired": false,
                        "pickupPoints": [],
                        "dropoffAvailable": false,
                        "dropoffRequired": false,
                        "dropoffPoints": []
                      },
                      {
                        "id": "f658ad11-015f-455f-b9fd-e5c71c38f4d1",
                        "default": false,
                        "internalName": "Evening departure",
                        "reference": null,
                        "availabilityLocalStartTimes": [],
                        "cancellationCutoff": "24 hours",
                        "cancellationCutoffAmount": 24,
                        "cancellationCutoffUnit": "hour",
                        "availabilityCutoff": "24 hours",
                        "availabilityCutoffAmount": 24,
                        "availabilityCutoffUnit": "hour",
                        "availabilityLocalDateStart": null,
                        "availabilityLocalDateEnd": null,
                        "requiredContactFields": [
                          "firstName",
                          "lastName",
                          "emailAddress"
                        ],
                        "visibleContactFields": [
                          "firstName",
                          "lastName",
                          "emailAddress",
                          "phoneNumber",
                          "country"
                        ],
                        "restrictions": {
                          "minUnits": 0,
                          "maxUnits": null,
                          "minPaxCount": 0,
                          "maxPaxCount": null
                        },
                        "units": [],
                        "pricingFrom": [],
                        "option": {
                          "title": "Evening departure",
                          "language": "en",
                          "duration": "Flexible",
                          "durationAmount": "0",
                          "durationUnit": "minute",
                          "instantConfirmation": true,
                          "meetingPoint": {
                            "latitude": 41.0082,
                            "longitude": 28.9784
                          },
                          "validity": {
                            "type": "only_visit_date"
                          },
                          "voucher": {
                            "requiresPrinting": false,
                            "directAdmission": true
                          }
                        },
                        "isRefundable": true,
                        "cancellationPolicies": [],
                        "questions": [],
                        "pickupAvailable": false,
                        "pickupRequired": false,
                        "pickupPoints": [],
                        "dropoffAvailable": false,
                        "dropoffRequired": false,
                        "dropoffPoints": []
                      }
                    ],
                    "defaultCurrency": "USD",
                    "availableCurrencies": [
                      "GEL",
                      "EUR",
                      "GBP",
                      "AED",
                      "KRW",
                      "USD",
                      "IDR"
                    ],
                    "pricingPer": "UNIT",
                    "includeTax": true,
                    "includedTaxes": [],
                    "product": {
                      "title": "Old Istanbul at First Light: Sultanahmet Walking Tour",
                      "slug": "old-istanbul-at-first-light-sultanahmet-walking-tour",
                      "source": "direct",
                      "country": "TR",
                      "location": "Istanbul",
                      "subtitle": "Dawn over the old city, before the crowds arrive.",
                      "shortDescription": "Dawn over the old city, before the crowds arrive.",
                      "description": "Sultanahmet holds two empires in the space of a few hundred metres, and at seven in the morning you get it almost to yourself.\n\nYour guide meets you beside the Hippodrome and walks you through the district as the city wakes up: bakers pulling simit from the oven, gulls over the Bosphorus, the first call to prayer still hanging in the air. You will stand in front of Hagia Sophia without queueing for anything, cross into the Blue Mosque courtyard, and finish in a tea garden where locals rather than tour groups take breakfast.\n\nThis is a walking tour, not a lecture. Expect stories, corrections to things you have read, and enough context that the rest of your week in Istanbul makes better sense.",
                      "highlights": [
                        "Sunrise over the Blue Mosque",
                        "A guide who grew up here",
                        "Tea at the end"
                      ],
                      "inclusions": [
                        "Licensed English-speaking guide",
                        "Turkish tea at the final stop",
                        "Small group, capped at twelve"
                      ],
                      "exclusions": [
                        "Hotel pickup",
                        "Museum entry tickets",
                        "Gratuities"
                      ],
                      "bookingTerms": "Wear shoes you can walk three kilometres in. Shoulders and knees should be covered for the mosque courtyard, and women should bring a scarf. The tour runs in light rain.",
                      "redemptionInstructions": null,
                      "safety": null,
                      "alert": null,
                      "alerts": [],
                      "faqs": [
                        {
                          "question": "How early does it start?",
                          "answer": "We meet at 6:15, which is the point of it."
                        },
                        {
                          "question": "Do we go inside Hagia Sophia?",
                          "answer": "No. This is an outdoor walking tour. Your guide will tell you the best time to go in on your own and how to avoid the queue."
                        },
                        {
                          "question": "Is it suitable for children?",
                          "answer": "Yes, from around eight upwards. It is roughly three kilometres at a gentle pace."
                        }
                      ],
                      "coverImageUrl": "https://api.vacotours.com/storage/products/c86ea1c1-a986-4d1f-bd23-6bec906beffa/3SRhriFoUcN4li37WYtl23WfsOmNMKVf27aCYDGw.jpg",
                      "bannerImageUrl": "https://api.vacotours.com/storage/products/c86ea1c1-a986-4d1f-bd23-6bec906beffa/3SRhriFoUcN4li37WYtl23WfsOmNMKVf27aCYDGw.jpg",
                      "galleryImages": [
                        {
                          "url": "http://localhost:3000/media/products/istanbul-sunrise-hero.jpg",
                          "alt": "Hagia Sophia at sunrise seen from the Sultanahmet square, Istanbul"
                        },
                        {
                          "url": "https://api.vacotours.com/storage/products/c86ea1c1-a986-4d1f-bd23-6bec906beffa/3SRhriFoUcN4li37WYtl23WfsOmNMKVf27aCYDGw.jpg",
                          "width": 1600,
                          "height": 900
                        }
                      ],
                      "images": [
                        {
                          "url": "http://localhost:3000/media/products/istanbul-sunrise-hero.jpg",
                          "alt": "Hagia Sophia at sunrise seen from the Sultanahmet square, Istanbul"
                        },
                        {
                          "url": "https://api.vacotours.com/storage/products/c86ea1c1-a986-4d1f-bd23-6bec906beffa/3SRhriFoUcN4li37WYtl23WfsOmNMKVf27aCYDGw.jpg",
                          "width": 1600,
                          "height": 900
                        }
                      ],
                      "duration": "3 hours",
                      "durationMinutes": 180,
                      "destination": {
                        "id": "98e16112-0b3d-4203-89f5-ce9dfa8809d7",
                        "name": "Istanbul",
                        "country": "TR",
                        "countryName": "Türkiye",
                        "countryId": "badd49dd-d696-437c-b305-bbe6a1c7fe44",
                        "latitude": 41.0082,
                        "longitude": 28.9784,
                        "icon": "landmark",
                        "iconUrl": "https://vacotours.com/map-icons/landmark.svg"
                      },
                      "categories": [
                        {
                          "id": "tours-sightseeing",
                          "uuid": "13658693-27a9-4637-bf8d-5900d7672cec",
                          "title": "Tours & Sightseeing"
                        },
                        {
                          "id": "walking-tours",
                          "uuid": "e1930346-6ce3-4f18-be6d-edd3c9526432",
                          "title": "Walking Tours"
                        }
                      ],
                      "productType": {
                        "code": "walking_tour",
                        "name": "Walking tour",
                        "family": "guided_tour"
                      },
                      "rating": {
                        "average": 4.9,
                        "count": 428
                      },
                      "supplier": {
                        "id": "7dc5de2d-2c45-4bab-a6e8-63a2b28ff67d",
                        "name": "Aurora Trails"
                      },
                      "languages": [
                        "en"
                      ],
                      "updatedAt": "2026-09-28T20:26:59+00:00"
                    }
                  }
                ]
              }
            },
            "headers": {
              "X-Total-Count": {
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "400": {
            "description": "Rejected. See error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "This key may not do that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Over the rate limit. Retry-After says when.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "Octo-Capabilities",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "Comma separated, for example `octo/pricing, octo/content`."
          },
          {
            "name": "X-Currency",
            "in": "header",
            "schema": {
              "type": "string",
              "example": "EUR"
            },
            "description": "Currency for every amount. `?currency=` works too."
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "maximum": 250
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0
            }
          },
          {
            "name": "updatedSince",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "productIds",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Comma separated."
          },
          {
            "name": "country",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "ISO code."
          },
          {
            "name": "city",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "City uuid or slug."
          },
          {
            "name": "category",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Category uuid or slug."
          },
          {
            "name": "source",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "direct",
                "channel"
              ],
              "default": "all"
            },
            "description": "Only our own operators' products (direct), only resold ones (channel), or both. Narrows what the key is set to; never widens it."
          }
        ]
      }
    },
    "/products/{productId}": {
      "get": {
        "tags": [
          "Products"
        ],
        "summary": "Get a product",
        "description": "One product with every option, unit, question and pickup point.",
        "operationId": "getProduct",
        "responses": {
          "200": {
            "description": "The product.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Product"
                },
                "example": {
                  "id": "c86ea1c1-a986-4d1f-bd23-6bec906beffa",
                  "internalName": "Sultanahmet Sunrise Walk",
                  "reference": "old-istanbul-at-first-light-sultanahmet-walking-tour",
                  "locale": "en",
                  "timeZone": "Europe/Istanbul",
                  "allowFreesale": false,
                  "instantConfirmation": true,
                  "instantDelivery": true,
                  "availabilityRequired": true,
                  "availabilityType": "START_TIME",
                  "deliveryFormats": [
                    "PDF_URL",
                    "QRCODE"
                  ],
                  "deliveryMethods": [
                    "TICKET",
                    "VOUCHER"
                  ],
                  "redemptionMethod": "DIGITAL",
                  "options": [
                    {
                      "id": "d7bbe7df-6d64-45a8-b8f9-69dace2d4f9c",
                      "default": true,
                      "internalName": "Sunrise departure (07:00)",
                      "reference": null,
                      "availabilityLocalStartTimes": [
                        "07:00"
                      ],
                      "cancellationCutoff": "24 hours",
                      "cancellationCutoffAmount": 24,
                      "cancellationCutoffUnit": "hour",
                      "availabilityCutoff": "24 hours",
                      "availabilityCutoffAmount": 24,
                      "availabilityCutoffUnit": "hour",
                      "availabilityLocalDateStart": null,
                      "availabilityLocalDateEnd": null,
                      "requiredContactFields": [
                        "firstName",
                        "lastName",
                        "emailAddress"
                      ],
                      "visibleContactFields": [
                        "firstName",
                        "lastName",
                        "emailAddress",
                        "phoneNumber",
                        "country"
                      ],
                      "restrictions": {
                        "minUnits": 0,
                        "maxUnits": null,
                        "minPaxCount": 0,
                        "maxPaxCount": 12
                      },
                      "units": [
                        {
                          "id": "0d04e5e0-67cb-4f6c-aa87-d5d3be2744cb",
                          "internalName": "Adult",
                          "reference": "adult",
                          "type": "ADULT",
                          "requiredContactFields": [],
                          "visibleContactFields": [
                            "firstName",
                            "lastName"
                          ],
                          "restrictions": {
                            "minAge": 18,
                            "maxAge": 64,
                            "idRequired": false,
                            "minQuantity": null,
                            "maxQuantity": 20,
                            "paxCount": 1,
                            "accompaniedBy": [],
                            "required": false
                          },
                          "pricingFrom": [
                            {
                              "original": 3826,
                              "retail": 3826,
                              "net": 3364,
                              "currency": "USD",
                              "currencyPrecision": 2,
                              "includedTaxes": []
                            }
                          ],
                          "unit": {
                            "title": "Adult",
                            "titlePlural": "Adults",
                            "category": "adult",
                            "ageLabel": "Age 18 to 64"
                          }
                        },
                        {
                          "id": "cd1ae236-fe8a-4735-9d82-ba15a1266cfe",
                          "internalName": "Child",
                          "reference": "child",
                          "type": "CHILD",
                          "requiredContactFields": [],
                          "visibleContactFields": [
                            "firstName",
                            "lastName"
                          ],
                          "restrictions": {
                            "minAge": 3,
                            "maxAge": 12,
                            "idRequired": false,
                            "minQuantity": null,
                            "maxQuantity": 20,
                            "paxCount": 1,
                            "accompaniedBy": [],
                            "required": false
                          },
                          "pricingFrom": [
                            {
                              "original": 2186,
                              "retail": 2186,
                              "net": 1991,
                              "currency": "USD",
                              "currencyPrecision": 2,
                              "includedTaxes": []
                            }
                          ],
                          "unit": {
                            "title": "Child",
                            "titlePlural": "Childs",
                            "category": "child",
                            "ageLabel": "Age 3 to 12"
                          }
                        },
                        {
                          "id": "dc694a09-2fd9-42bd-be08-576f943ced39",
                          "internalName": "Senior",
                          "reference": "senior",
                          "type": "SENIOR",
                          "requiredContactFields": [],
                          "visibleContactFields": [
                            "firstName",
                            "lastName"
                          ],
                          "restrictions": {
                            "minAge": 65,
                            "maxAge": 120,
                            "idRequired": false,
                            "minQuantity": null,
                            "maxQuantity": 20,
                            "paxCount": 1,
                            "accompaniedBy": [],
                            "required": false
                          },
                          "pricingFrom": [
                            {
                              "original": 3279,
                              "retail": 3279,
                              "net": 2907,
                              "currency": "USD",
                              "currencyPrecision": 2,
                              "includedTaxes": []
                            }
                          ],
                          "unit": {
                            "title": "Senior",
                            "titlePlural": "Seniors",
                            "category": "senior",
                            "ageLabel": "Age 65+"
                          }
                        },
                        {
                          "id": "8a6665ad-8df0-4c5c-8d8d-39381ee15944",
                          "internalName": "Student",
                          "reference": "student",
                          "type": "STUDENT",
                          "requiredContactFields": [],
                          "visibleContactFields": [
                            "firstName",
                            "lastName"
                          ],
                          "restrictions": {
                            "minAge": 13,
                            "maxAge": 17,
                            "idRequired": false,
                            "minQuantity": null,
                            "maxQuantity": 20,
                            "paxCount": 1,
                            "accompaniedBy": [],
                            "required": false
                          },
                          "pricingFrom": [
                            {
                              "original": 3006,
                              "retail": 3006,
                              "net": 2678,
                              "currency": "USD",
                              "currencyPrecision": 2,
                              "includedTaxes": []
                            }
                          ],
                          "unit": {
                            "title": "Student",
                            "titlePlural": "Students",
                            "category": "student",
                            "ageLabel": "Age 13 to 17"
                          }
                        }
                      ],
                      "pricingFrom": [
                        {
                          "original": 3006,
                          "retail": 3006,
                          "net": 2678,
                          "currency": "USD",
                          "currencyPrecision": 2,
                          "includedTaxes": []
                        }
                      ],
                      "option": {
                        "title": "Sunrise departure (07:00)",
                        "subtitle": "The quiet one. Meets at the Hippodrome obelisk.",
                        "shortDescription": "The quiet one. Meets at the Hippodrome obelisk.",
                        "language": "en",
                        "duration": "3 hours",
                        "durationAmount": "180",
                        "durationUnit": "minute",
                        "instantConfirmation": true,
                        "meetingPoint": {
                          "time": "06:45",
                          "address": "Obelisk of Theodosius, Sultanahmet Square",
                          "latitude": 41.0082,
                          "longitude": 28.9784
                        },
                        "validity": {
                          "type": "only_visit_date"
                        },
                        "voucher": {
                          "requiresPrinting": false,
                          "directAdmission": true
                        },
                        "itinerary": [
                          {
                            "day": 1,
                            "name": "Hippodrome and the Obelisk",
                            "type": "stop",
                            "description": "Where the chariots ran, and why three monuments from three civilisations stand in a row.",
                            "durationAmount": 30,
                            "durationUnit": "minute"
                          },
                          {
                            "day": 1,
                            "name": "Blue Mosque courtyard",
                            "type": "stop",
                            "durationAmount": 40,
                            "durationUnit": "minute"
                          },
                          {
                            "day": 1,
                            "name": "Hagia Sophia exterior",
                            "type": "stop",
                            "durationAmount": 45,
                            "durationUnit": "minute"
                          },
                          {
                            "day": 1,
                            "name": "Soğukçeşme Street",
                            "type": "stop",
                            "durationAmount": 25,
                            "durationUnit": "minute"
                          },
                          {
                            "day": 1,
                            "name": "Tea garden, Gülhane",
                            "type": "stop",
                            "durationAmount": 40,
                            "durationUnit": "minute"
                          }
                        ]
                      },
                      "isRefundable": true,
                      "cancellationPolicies": [
                        {
                          "cutoffHours": 168,
                          "refundPercentage": 100,
                          "cancellationFeePercentage": 0,
                          "serviceFee": {
                            "original": 0,
                            "retail": 0,
                            "net": 0,
                            "currency": "USD",
                            "currencyPrecision": 2,
                            "includedTaxes": []
                          },
                          "serviceFeePerBooking": true
                        },
                        {
                          "cutoffHours": 48,
                          "refundPercentage": 50,
                          "cancellationFeePercentage": 0,
                          "serviceFee": {
                            "original": 0,
                            "retail": 0,
                            "net": 0,
                            "currency": "USD",
                            "currencyPrecision": 2,
                            "includedTaxes": []
                          },
                          "serviceFeePerBooking": true
                        },
                        {
                          "cutoffHours": 24,
                          "refundPercentage": 0,
                          "cancellationFeePercentage": 0,
                          "serviceFee": {
                            "original": 0,
                            "retail": 0,
                            "net": 0,
                            "currency": "USD",
                            "currencyPrecision": 2,
                            "includedTaxes": []
                          },
                          "serviceFeePerBooking": true
                        }
                      ],
                      "questions": [],
                      "pickupAvailable": false,
                      "pickupRequired": false,
                      "pickupPoints": [],
                      "dropoffAvailable": false,
                      "dropoffRequired": false,
                      "dropoffPoints": []
                    },
                    {
                      "id": "f44835e5-6d4e-47bc-8a38-2e53e4f6897e",
                      "default": false,
                      "internalName": "Mid-morning departure (09:30)",
                      "reference": null,
                      "availabilityLocalStartTimes": [
                        "09:30"
                      ],
                      "cancellationCutoff": "24 hours",
                      "cancellationCutoffAmount": 24,
                      "cancellationCutoffUnit": "hour",
                      "availabilityCutoff": "24 hours",
                      "availabilityCutoffAmount": 24,
                      "availabilityCutoffUnit": "hour",
                      "availabilityLocalDateStart": null,
                      "availabilityLocalDateEnd": null,
                      "requiredContactFields": [
                        "firstName",
                        "lastName",
                        "emailAddress"
                      ],
                      "visibleContactFields": [
                        "firstName",
                        "lastName",
                        "emailAddress",
                        "phoneNumber",
                        "country"
                      ],
                      "restrictions": {
                        "minUnits": 0,
                        "maxUnits": null,
                        "minPaxCount": 0,
                        "maxPaxCount": null
                      },
                      "units": [
                        {
                          "id": "524b8ba7-8582-4f3f-8d35-4dc92ce96db9",
                          "internalName": "Adult",
                          "reference": "adult",
                          "type": "ADULT",
                          "requiredContactFields": [],
                          "visibleContactFields": [
                            "firstName",
                            "lastName"
                          ],
                          "restrictions": {
                            "minAge": 18,
                            "maxAge": 64,
                            "idRequired": false,
                            "minQuantity": null,
                            "maxQuantity": 20,
                            "paxCount": 1,
                            "accompaniedBy": [],
                            "required": false
                          },
                          "pricingFrom": [
                            {
                              "original": 3416,
                              "retail": 3416,
                              "net": 3021,
                              "currency": "USD",
                              "currencyPrecision": 2,
                              "includedTaxes": []
                            }
                          ],
                          "unit": {
                            "title": "Adult",
                            "titlePlural": "Adults",
                            "category": "adult",
                            "ageLabel": "Age 18 to 64"
                          }
                        },
                        {
                          "id": "d1553620-ebe4-4a6d-aba8-6e28bbf3eeb1",
                          "internalName": "Child",
                          "reference": "child",
                          "type": "CHILD",
                          "requiredContactFields": [],
                          "visibleContactFields": [
                            "firstName",
                            "lastName"
                          ],
                          "restrictions": {
                            "minAge": 3,
                            "maxAge": 12,
                            "idRequired": false,
                            "minQuantity": null,
                            "maxQuantity": 20,
                            "paxCount": 1,
                            "accompaniedBy": [],
                            "required": false
                          },
                          "pricingFrom": [
                            {
                              "original": 1913,
                              "retail": 1913,
                              "net": 1762,
                              "currency": "USD",
                              "currencyPrecision": 2,
                              "includedTaxes": []
                            }
                          ],
                          "unit": {
                            "title": "Child",
                            "titlePlural": "Childs",
                            "category": "child",
                            "ageLabel": "Age 3 to 12"
                          }
                        },
                        {
                          "id": "2604fe39-f7f8-470d-89ca-d79b64838b74",
                          "internalName": "Senior",
                          "reference": "senior",
                          "type": "SENIOR",
                          "requiredContactFields": [],
                          "visibleContactFields": [
                            "firstName",
                            "lastName"
                          ],
                          "restrictions": {
                            "minAge": 65,
                            "maxAge": 120,
                            "idRequired": false,
                            "minQuantity": null,
                            "maxQuantity": 20,
                            "paxCount": 1,
                            "accompaniedBy": [],
                            "required": false
                          },
                          "pricingFrom": [
                            {
                              "original": 3006,
                              "retail": 3006,
                              "net": 2678,
                              "currency": "USD",
                              "currencyPrecision": 2,
                              "includedTaxes": []
                            }
                          ],
                          "unit": {
                            "title": "Senior",
                            "titlePlural": "Seniors",
                            "category": "senior",
                            "ageLabel": "Age 65+"
                          }
                        },
                        {
                          "id": "abcfe31b-64ef-4f46-baf5-cc618b435919",
                          "internalName": "Student",
                          "reference": "student",
                          "type": "STUDENT",
                          "requiredContactFields": [],
                          "visibleContactFields": [
                            "firstName",
                            "lastName"
                          ],
                          "restrictions": {
                            "minAge": 13,
                            "maxAge": 17,
                            "idRequired": false,
                            "minQuantity": null,
                            "maxQuantity": 20,
                            "paxCount": 1,
                            "accompaniedBy": [],
                            "required": false
                          },
                          "pricingFrom": [
                            {
                              "original": 2733,
                              "retail": 2733,
                              "net": 2449,
                              "currency": "USD",
                              "currencyPrecision": 2,
                              "includedTaxes": []
                            }
                          ],
                          "unit": {
                            "title": "Student",
                            "titlePlural": "Students",
                            "category": "student",
                            "ageLabel": "Age 13 to 17"
                          }
                        }
                      ],
                      "pricingFrom": [
                        {
                          "original": 2733,
                          "retail": 2733,
                          "net": 2449,
                          "currency": "USD",
                          "currencyPrecision": 2,
                          "includedTaxes": []
                        }
                      ],
                      "option": {
                        "title": "Mid-morning departure (09:30)",
                        "language": "en",
                        "duration": "3 hours",
                        "durationAmount": "180",
                        "durationUnit": "minute",
                        "instantConfirmation": true,
                        "meetingPoint": {
                          "time": "09:15",
                          "address": "Obelisk of Theodosius, Sultanahmet Square",
                          "latitude": 41.0082,
                          "longitude": 28.9784
                        },
                        "validity": {
                          "type": "only_visit_date"
                        },
                        "voucher": {
                          "requiresPrinting": false,
                          "directAdmission": true
                        }
                      },
                      "isRefundable": true,
                      "cancellationPolicies": [
                        {
                          "cutoffHours": 168,
                          "refundPercentage": 100,
                          "cancellationFeePercentage": 0,
                          "serviceFee": {
                            "original": 0,
                            "retail": 0,
                            "net": 0,
                            "currency": "USD",
                            "currencyPrecision": 2,
                            "includedTaxes": []
                          },
                          "serviceFeePerBooking": true
                        },
                        {
                          "cutoffHours": 48,
                          "refundPercentage": 50,
                          "cancellationFeePercentage": 0,
                          "serviceFee": {
                            "original": 0,
                            "retail": 0,
                            "net": 0,
                            "currency": "USD",
                            "currencyPrecision": 2,
                            "includedTaxes": []
                          },
                          "serviceFeePerBooking": true
                        },
                        {
                          "cutoffHours": 24,
                          "refundPercentage": 0,
                          "cancellationFeePercentage": 0,
                          "serviceFee": {
                            "original": 0,
                            "retail": 0,
                            "net": 0,
                            "currency": "USD",
                            "currencyPrecision": 2,
                            "includedTaxes": []
                          },
                          "serviceFeePerBooking": true
                        }
                      ],
                      "questions": [],
                      "pickupAvailable": false,
                      "pickupRequired": false,
                      "pickupPoints": [],
                      "dropoffAvailable": false,
                      "dropoffRequired": false,
                      "dropoffPoints": []
                    },
                    {
                      "id": "f658ad11-015f-455f-b9fd-e5c71c38f4d1",
                      "default": false,
                      "internalName": "Evening departure",
                      "reference": null,
                      "availabilityLocalStartTimes": [],
                      "cancellationCutoff": "24 hours",
                      "cancellationCutoffAmount": 24,
                      "cancellationCutoffUnit": "hour",
                      "availabilityCutoff": "24 hours",
                      "availabilityCutoffAmount": 24,
                      "availabilityCutoffUnit": "hour",
                      "availabilityLocalDateStart": null,
                      "availabilityLocalDateEnd": null,
                      "requiredContactFields": [
                        "firstName",
                        "lastName",
                        "emailAddress"
                      ],
                      "visibleContactFields": [
                        "firstName",
                        "lastName",
                        "emailAddress",
                        "phoneNumber",
                        "country"
                      ],
                      "restrictions": {
                        "minUnits": 0,
                        "maxUnits": null,
                        "minPaxCount": 0,
                        "maxPaxCount": null
                      },
                      "units": [],
                      "pricingFrom": [],
                      "option": {
                        "title": "Evening departure",
                        "language": "en",
                        "duration": "Flexible",
                        "durationAmount": "0",
                        "durationUnit": "minute",
                        "instantConfirmation": true,
                        "meetingPoint": {
                          "latitude": 41.0082,
                          "longitude": 28.9784
                        },
                        "validity": {
                          "type": "only_visit_date"
                        },
                        "voucher": {
                          "requiresPrinting": false,
                          "directAdmission": true
                        }
                      },
                      "isRefundable": true,
                      "cancellationPolicies": [],
                      "questions": [],
                      "pickupAvailable": false,
                      "pickupRequired": false,
                      "pickupPoints": [],
                      "dropoffAvailable": false,
                      "dropoffRequired": false,
                      "dropoffPoints": []
                    }
                  ],
                  "defaultCurrency": "USD",
                  "availableCurrencies": [
                    "GEL",
                    "EUR",
                    "GBP",
                    "AED",
                    "KRW",
                    "USD",
                    "IDR"
                  ],
                  "pricingPer": "UNIT",
                  "includeTax": true,
                  "includedTaxes": [],
                  "product": {
                    "title": "Old Istanbul at First Light: Sultanahmet Walking Tour",
                    "slug": "old-istanbul-at-first-light-sultanahmet-walking-tour",
                    "source": "direct",
                    "country": "TR",
                    "location": "Istanbul",
                    "subtitle": "Dawn over the old city, before the crowds arrive.",
                    "shortDescription": "Dawn over the old city, before the crowds arrive.",
                    "description": "Sultanahmet holds two empires in the space of a few hundred metres, and at seven in the morning you get it almost to yourself.\n\nYour guide meets you beside the Hippodrome and walks you through the district as the city wakes up: bakers pulling simit from the oven, gulls over the Bosphorus, the first call to prayer still hanging in the air. You will stand in front of Hagia Sophia without queueing for anything, cross into the Blue Mosque courtyard, and finish in a tea garden where locals rather than tour groups take breakfast.\n\nThis is a walking tour, not a lecture. Expect stories, corrections to things you have read, and enough context that the rest of your week in Istanbul makes better sense.",
                    "highlights": [
                      "Sunrise over the Blue Mosque",
                      "A guide who grew up here",
                      "Tea at the end"
                    ],
                    "inclusions": [
                      "Licensed English-speaking guide",
                      "Turkish tea at the final stop",
                      "Small group, capped at twelve"
                    ],
                    "exclusions": [
                      "Hotel pickup",
                      "Museum entry tickets",
                      "Gratuities"
                    ],
                    "bookingTerms": "Wear shoes you can walk three kilometres in. Shoulders and knees should be covered for the mosque courtyard, and women should bring a scarf. The tour runs in light rain.",
                    "redemptionInstructions": null,
                    "safety": null,
                    "alert": null,
                    "alerts": [],
                    "faqs": [
                      {
                        "question": "How early does it start?",
                        "answer": "We meet at 6:15, which is the point of it."
                      },
                      {
                        "question": "Do we go inside Hagia Sophia?",
                        "answer": "No. This is an outdoor walking tour. Your guide will tell you the best time to go in on your own and how to avoid the queue."
                      },
                      {
                        "question": "Is it suitable for children?",
                        "answer": "Yes, from around eight upwards. It is roughly three kilometres at a gentle pace."
                      }
                    ],
                    "coverImageUrl": "https://api.vacotours.com/storage/products/c86ea1c1-a986-4d1f-bd23-6bec906beffa/3SRhriFoUcN4li37WYtl23WfsOmNMKVf27aCYDGw.jpg",
                    "bannerImageUrl": "https://api.vacotours.com/storage/products/c86ea1c1-a986-4d1f-bd23-6bec906beffa/3SRhriFoUcN4li37WYtl23WfsOmNMKVf27aCYDGw.jpg",
                    "galleryImages": [
                      {
                        "url": "http://localhost:3000/media/products/istanbul-sunrise-hero.jpg",
                        "alt": "Hagia Sophia at sunrise seen from the Sultanahmet square, Istanbul"
                      },
                      {
                        "url": "https://api.vacotours.com/storage/products/c86ea1c1-a986-4d1f-bd23-6bec906beffa/3SRhriFoUcN4li37WYtl23WfsOmNMKVf27aCYDGw.jpg",
                        "width": 1600,
                        "height": 900
                      }
                    ],
                    "images": [
                      {
                        "url": "http://localhost:3000/media/products/istanbul-sunrise-hero.jpg",
                        "alt": "Hagia Sophia at sunrise seen from the Sultanahmet square, Istanbul"
                      },
                      {
                        "url": "https://api.vacotours.com/storage/products/c86ea1c1-a986-4d1f-bd23-6bec906beffa/3SRhriFoUcN4li37WYtl23WfsOmNMKVf27aCYDGw.jpg",
                        "width": 1600,
                        "height": 900
                      }
                    ],
                    "duration": "3 hours",
                    "durationMinutes": 180,
                    "destination": {
                      "id": "98e16112-0b3d-4203-89f5-ce9dfa8809d7",
                      "name": "Istanbul",
                      "country": "TR",
                      "countryName": "Türkiye",
                      "countryId": "badd49dd-d696-437c-b305-bbe6a1c7fe44",
                      "latitude": 41.0082,
                      "longitude": 28.9784,
                      "icon": "landmark",
                      "iconUrl": "https://vacotours.com/map-icons/landmark.svg"
                    },
                    "categories": [
                      {
                        "id": "tours-sightseeing",
                        "uuid": "13658693-27a9-4637-bf8d-5900d7672cec",
                        "title": "Tours & Sightseeing"
                      },
                      {
                        "id": "walking-tours",
                        "uuid": "e1930346-6ce3-4f18-be6d-edd3c9526432",
                        "title": "Walking Tours"
                      }
                    ],
                    "productType": {
                      "code": "walking_tour",
                      "name": "Walking tour",
                      "family": "guided_tour"
                    },
                    "rating": {
                      "average": 4.9,
                      "count": 428
                    },
                    "supplier": {
                      "id": "7dc5de2d-2c45-4bab-a6e8-63a2b28ff67d",
                      "name": "Aurora Trails"
                    },
                    "languages": [
                      "en"
                    ],
                    "updatedAt": "2026-09-28T20:26:59+00:00"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Rejected. See error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "This key may not do that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Over the rate limit. Retry-After says when.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "Octo-Capabilities",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "Comma separated, for example `octo/pricing, octo/content`."
          },
          {
            "name": "X-Currency",
            "in": "header",
            "schema": {
              "type": "string",
              "example": "EUR"
            },
            "description": "Currency for every amount. `?currency=` works too."
          },
          {
            "name": "productId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/availability/calendar": {
      "post": {
        "tags": [
          "Availability"
        ],
        "summary": "Price calendar",
        "description": "One object per operating day in a range of up to 366 days, with the cheapest price a booking could pay that day. Send `units` to judge each day against your party.",
        "operationId": "availabilityCalendar",
        "responses": {
          "200": {
            "description": "Days.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AvailabilityCalendar"
                  }
                },
                "example": [
                  {
                    "localDate": "2026-09-30",
                    "available": true,
                    "status": "AVAILABLE",
                    "vacancies": 12,
                    "capacity": 12,
                    "maxUnits": null,
                    "maxPaxCount": null,
                    "utcCutoffAt": "2026-09-29T04:00:00+00:00",
                    "openingHours": [],
                    "availabilityLocalStartTimes": [
                      "07:00"
                    ],
                    "statusMessage": null,
                    "unitPricingFrom": [
                      {
                        "original": 3826,
                        "retail": 3826,
                        "net": 3364,
                        "currency": "USD",
                        "currencyPrecision": 2,
                        "includedTaxes": [],
                        "unitId": "0d04e5e0-67cb-4f6c-aa87-d5d3be2744cb",
                        "unitType": "ADULT"
                      },
                      {
                        "original": 2186,
                        "retail": 2186,
                        "net": 1991,
                        "currency": "USD",
                        "currencyPrecision": 2,
                        "includedTaxes": [],
                        "unitId": "cd1ae236-fe8a-4735-9d82-ba15a1266cfe",
                        "unitType": "CHILD"
                      },
                      {
                        "original": 3279,
                        "retail": 3279,
                        "net": 2907,
                        "currency": "USD",
                        "currencyPrecision": 2,
                        "includedTaxes": [],
                        "unitId": "dc694a09-2fd9-42bd-be08-576f943ced39",
                        "unitType": "SENIOR"
                      },
                      {
                        "original": 3006,
                        "retail": 3006,
                        "net": 2678,
                        "currency": "USD",
                        "currencyPrecision": 2,
                        "includedTaxes": [],
                        "unitId": "8a6665ad-8df0-4c5c-8d8d-39381ee15944",
                        "unitType": "STUDENT"
                      }
                    ],
                    "pricingFrom": {
                      "original": 3006,
                      "retail": 3006,
                      "net": 2678,
                      "currency": "USD",
                      "currencyPrecision": 2,
                      "includedTaxes": []
                    }
                  },
                  {
                    "localDate": "2026-10-01",
                    "available": true,
                    "status": "AVAILABLE",
                    "vacancies": 12,
                    "capacity": 12,
                    "maxUnits": null,
                    "maxPaxCount": null,
                    "utcCutoffAt": "2026-09-30T04:00:00+00:00",
                    "openingHours": [],
                    "availabilityLocalStartTimes": [
                      "07:00"
                    ],
                    "statusMessage": null,
                    "unitPricingFrom": [
                      {
                        "original": 3826,
                        "retail": 3826,
                        "net": 3364,
                        "currency": "USD",
                        "currencyPrecision": 2,
                        "includedTaxes": [],
                        "unitId": "0d04e5e0-67cb-4f6c-aa87-d5d3be2744cb",
                        "unitType": "ADULT"
                      },
                      {
                        "original": 2186,
                        "retail": 2186,
                        "net": 1991,
                        "currency": "USD",
                        "currencyPrecision": 2,
                        "includedTaxes": [],
                        "unitId": "cd1ae236-fe8a-4735-9d82-ba15a1266cfe",
                        "unitType": "CHILD"
                      },
                      {
                        "original": 3279,
                        "retail": 3279,
                        "net": 2907,
                        "currency": "USD",
                        "currencyPrecision": 2,
                        "includedTaxes": [],
                        "unitId": "dc694a09-2fd9-42bd-be08-576f943ced39",
                        "unitType": "SENIOR"
                      },
                      {
                        "original": 3006,
                        "retail": 3006,
                        "net": 2678,
                        "currency": "USD",
                        "currencyPrecision": 2,
                        "includedTaxes": [],
                        "unitId": "8a6665ad-8df0-4c5c-8d8d-39381ee15944",
                        "unitType": "STUDENT"
                      }
                    ],
                    "pricingFrom": {
                      "original": 3006,
                      "retail": 3006,
                      "net": 2678,
                      "currency": "USD",
                      "currencyPrecision": 2,
                      "includedTaxes": []
                    }
                  }
                ]
              }
            }
          },
          "400": {
            "description": "Rejected. See error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "This key may not do that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Over the rate limit. Retry-After says when.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "Octo-Capabilities",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "Comma separated, for example `octo/pricing, octo/content`."
          },
          {
            "name": "X-Currency",
            "in": "header",
            "schema": {
              "type": "string",
              "example": "EUR"
            },
            "description": "Currency for every amount. `?currency=` works too."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "productId": {
                    "type": "string"
                  },
                  "optionId": {
                    "type": "string"
                  },
                  "localDateStart": {
                    "type": "string",
                    "format": "date"
                  },
                  "localDateEnd": {
                    "type": "string",
                    "format": "date"
                  },
                  "units": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "quantity": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                },
                "required": [
                  "productId",
                  "optionId",
                  "localDateStart",
                  "localDateEnd"
                ]
              },
              "example": {
                "productId": "c86ea1c1-a986-4d1f-bd23-6bec906beffa",
                "optionId": "d7bbe7df-6d64-45a8-b8f9-69dace2d4f9c",
                "localDateStart": "2026-10-01",
                "localDateEnd": "2026-10-31"
              }
            }
          }
        }
      }
    },
    "/availability": {
      "post": {
        "tags": [
          "Availability"
        ],
        "summary": "Start times",
        "description": "The times on a date (or up to 62 days) that are on sale, each priced. With `units`, availability is judged against that party and `pricing` is its total. The `id` is what you book.",
        "operationId": "availability",
        "responses": {
          "200": {
            "description": "Times.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Availability"
                  }
                },
                "example": [
                  {
                    "id": "593651fd-fb2d-4132-91cf-1764ceb6c885",
                    "localDateTimeStart": "2026-10-03T07:00:00+03:00",
                    "localDateTimeEnd": "2026-10-03T10:00:00+03:00",
                    "allDay": false,
                    "available": true,
                    "status": "AVAILABLE",
                    "vacancies": 12,
                    "capacity": 12,
                    "maxUnits": null,
                    "maxPaxCount": 12,
                    "utcCutoffAt": "2026-10-02T04:00:00+00:00",
                    "openingHours": [],
                    "statusMessage": null,
                    "unitPricing": [
                      {
                        "original": 3826,
                        "retail": 3826,
                        "net": 3364,
                        "currency": "USD",
                        "currencyPrecision": 2,
                        "includedTaxes": [],
                        "unitId": "0d04e5e0-67cb-4f6c-aa87-d5d3be2744cb",
                        "unitType": "ADULT"
                      },
                      {
                        "original": 2186,
                        "retail": 2186,
                        "net": 1991,
                        "currency": "USD",
                        "currencyPrecision": 2,
                        "includedTaxes": [],
                        "unitId": "cd1ae236-fe8a-4735-9d82-ba15a1266cfe",
                        "unitType": "CHILD"
                      },
                      {
                        "original": 3279,
                        "retail": 3279,
                        "net": 2907,
                        "currency": "USD",
                        "currencyPrecision": 2,
                        "includedTaxes": [],
                        "unitId": "dc694a09-2fd9-42bd-be08-576f943ced39",
                        "unitType": "SENIOR"
                      },
                      {
                        "original": 3006,
                        "retail": 3006,
                        "net": 2678,
                        "currency": "USD",
                        "currencyPrecision": 2,
                        "includedTaxes": [],
                        "unitId": "8a6665ad-8df0-4c5c-8d8d-39381ee15944",
                        "unitType": "STUDENT"
                      }
                    ],
                    "pricing": {
                      "original": 7652,
                      "retail": 7652,
                      "net": 6728,
                      "currency": "USD",
                      "currencyPrecision": 2,
                      "includedTaxes": []
                    },
                    "pickupAvailable": false,
                    "pickupRequired": false,
                    "pickupPoints": []
                  }
                ]
              }
            }
          },
          "400": {
            "description": "Rejected. See error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "This key may not do that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Over the rate limit. Retry-After says when.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "Octo-Capabilities",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "Comma separated, for example `octo/pricing, octo/content`."
          },
          {
            "name": "X-Currency",
            "in": "header",
            "schema": {
              "type": "string",
              "example": "EUR"
            },
            "description": "Currency for every amount. `?currency=` works too."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "productId": {
                    "type": "string"
                  },
                  "optionId": {
                    "type": "string"
                  },
                  "localDate": {
                    "type": "string",
                    "format": "date"
                  },
                  "localDateStart": {
                    "type": "string",
                    "format": "date"
                  },
                  "localDateEnd": {
                    "type": "string",
                    "format": "date"
                  },
                  "availabilityIds": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "units": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "quantity": {
                          "type": "integer"
                        }
                      }
                    }
                  },
                  "rental": {
                    "$ref": "#/components/schemas/RentalRequest"
                  }
                },
                "required": [
                  "productId",
                  "optionId"
                ]
              },
              "example": {
                "productId": "c86ea1c1-a986-4d1f-bd23-6bec906beffa",
                "optionId": "d7bbe7df-6d64-45a8-b8f9-69dace2d4f9c",
                "localDate": "2026-10-03",
                "units": [
                  {
                    "id": "0d04e5e0-67cb-4f6c-aa87-d5d3be2744cb",
                    "quantity": 2
                  }
                ]
              }
            }
          }
        }
      }
    },
    "/bookings": {
      "post": {
        "tags": [
          "Bookings"
        ],
        "summary": "Reserve",
        "description": "Holds the seats and your funds and returns the booking `ON_HOLD` until `utcExpiresAt`. Every answer is checked now, so a booking that reserves will not be refused later for a missing detail. The lead contact may be sent here or at confirm.",
        "operationId": "createBooking",
        "responses": {
          "201": {
            "description": "Reserved.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Booking"
                },
                "example": {
                  "id": "b00b620a-3a67-4e80-8f8b-89d03325bdc5",
                  "uuid": "b00b620a-3a67-4e80-8f8b-89d03325bdc5",
                  "testMode": true,
                  "resellerReference": "NB-2026-00417",
                  "supplierReference": "VT260928N1EVP",
                  "status": "ON_HOLD",
                  "utcCreatedAt": "2026-09-28T20:28:36+00:00",
                  "utcUpdatedAt": "2026-09-28T20:28:36+00:00",
                  "utcExpiresAt": "2026-09-28T20:58:36+00:00",
                  "utcRedeemedAt": null,
                  "utcConfirmedAt": null,
                  "productId": "c86ea1c1-a986-4d1f-bd23-6bec906beffa",
                  "optionId": "d7bbe7df-6d64-45a8-b8f9-69dace2d4f9c",
                  "cancellable": true,
                  "confirmable": true,
                  "freesale": false,
                  "availabilityId": "593651fd-fb2d-4132-91cf-1764ceb6c885",
                  "availability": {
                    "id": "593651fd-fb2d-4132-91cf-1764ceb6c885",
                    "localDateTimeStart": "2026-10-03T07:00:00+03:00",
                    "localDateTimeEnd": "2026-10-03T10:00:00+03:00",
                    "allDay": false,
                    "openingHours": []
                  },
                  "contact": {
                    "fullName": "Hannah Lindqvist",
                    "firstName": "Hannah",
                    "lastName": "Lindqvist",
                    "emailAddress": "hannah@example.com",
                    "phoneNumber": "+46 70 123 4567",
                    "country": "SE",
                    "locales": [
                      "en"
                    ]
                  },
                  "notes": null,
                  "deliveryMethods": [
                    "TICKET",
                    "VOUCHER"
                  ],
                  "voucher": null,
                  "unitItems": [
                    {
                      "uuid": "41f1ced0-29e6-4359-a176-a23ab7a3a796",
                      "id": "41f1ced0-29e6-4359-a176-a23ab7a3a796",
                      "resellerReference": null,
                      "supplierReference": "41f1ced0-29e6-4359-a176-a23ab7a3a796",
                      "unitId": "0d04e5e0-67cb-4f6c-aa87-d5d3be2744cb",
                      "unitType": "ADULT",
                      "status": "ON_HOLD",
                      "utcRedeemedAt": null,
                      "contact": {},
                      "ticket": null,
                      "questionAnswers": [],
                      "pricing": {
                        "original": 3826,
                        "retail": 3826,
                        "net": 3364,
                        "currency": "USD",
                        "currencyPrecision": 2,
                        "includedTaxes": []
                      }
                    },
                    {
                      "uuid": "a07f1196-2969-4f80-b5a1-8daf56178e0a",
                      "id": "a07f1196-2969-4f80-b5a1-8daf56178e0a",
                      "resellerReference": null,
                      "supplierReference": "a07f1196-2969-4f80-b5a1-8daf56178e0a",
                      "unitId": "0d04e5e0-67cb-4f6c-aa87-d5d3be2744cb",
                      "unitType": "ADULT",
                      "status": "ON_HOLD",
                      "utcRedeemedAt": null,
                      "contact": {},
                      "ticket": null,
                      "questionAnswers": [],
                      "pricing": {
                        "original": 3826,
                        "retail": 3826,
                        "net": 3364,
                        "currency": "USD",
                        "currencyPrecision": 2,
                        "includedTaxes": []
                      }
                    }
                  ],
                  "questionAnswers": [],
                  "pricing": {
                    "original": 7652,
                    "retail": 7652,
                    "net": 6728,
                    "currency": "USD",
                    "currencyPrecision": 2,
                    "includedTaxes": []
                  },
                  "pickupRequested": false,
                  "pickupPointId": null,
                  "pickupHotel": null,
                  "pickupHotelRoom": null,
                  "pickupAddress": null,
                  "pickupTime": null,
                  "pickupNotes": null
                }
              }
            }
          },
          "200": {
            "description": "A retry with the same uuid: the first booking.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Booking"
                }
              }
            }
          },
          "400": {
            "description": "Rejected. See error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "This key may not do that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Over the rate limit. Retry-After says when.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "Octo-Capabilities",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "Comma separated, for example `octo/pricing, octo/content`."
          },
          {
            "name": "X-Currency",
            "in": "header",
            "schema": {
              "type": "string",
              "example": "EUR"
            },
            "description": "Currency for every amount. `?currency=` works too."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BookingRequest"
              },
              "example": {
                "productId": "c86ea1c1-a986-4d1f-bd23-6bec906beffa",
                "optionId": "d7bbe7df-6d64-45a8-b8f9-69dace2d4f9c",
                "availabilityId": "593651fd-fb2d-4132-91cf-1764ceb6c885",
                "unitItems": [
                  {
                    "unitId": "0d04e5e0-67cb-4f6c-aa87-d5d3be2744cb",
                    "questionAnswers": [
                      {
                        "questionId": "6f1c...a2",
                        "value": "X1234567"
                      }
                    ]
                  },
                  {
                    "unitId": "0d04e5e0-67cb-4f6c-aa87-d5d3be2744cb",
                    "questionAnswers": [
                      {
                        "questionId": "6f1c...a2",
                        "value": "Y7654321"
                      }
                    ]
                  }
                ],
                "questionAnswers": [
                  {
                    "questionId": "9b0d...14",
                    "value": "Vegetarian"
                  }
                ],
                "contact": {
                  "firstName": "Hannah",
                  "lastName": "Lindqvist",
                  "emailAddress": "hannah@example.com",
                  "phoneNumber": "+46 70 123 4567",
                  "country": "SE"
                },
                "resellerReference": "NB-2026-00417",
                "uuid": "3f0c2b7e-6a55-4f3e-9d0e-0a8e2c1d4b61"
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Bookings"
        ],
        "summary": "List bookings",
        "description": "Your bookings, newest first. `X-Total-Count` has the total.",
        "operationId": "listBookings",
        "responses": {
          "200": {
            "description": "Bookings.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Booking"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Rejected. See error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "This key may not do that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Over the rate limit. Retry-After says when.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "Octo-Capabilities",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "Comma separated, for example `octo/pricing, octo/content`."
          },
          {
            "name": "resellerReference",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "supplierReference",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "localDate",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "localDateStart",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "localDateEnd",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "productId",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "optionId",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 100
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer"
            }
          }
        ]
      }
    },
    "/bookings/{uuid}": {
      "get": {
        "tags": [
          "Bookings"
        ],
        "summary": "Get a booking",
        "description": "One of your bookings.",
        "operationId": "getBooking",
        "responses": {
          "200": {
            "description": "The booking.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Booking"
                },
                "example": {
                  "id": "b00b620a-3a67-4e80-8f8b-89d03325bdc5",
                  "uuid": "b00b620a-3a67-4e80-8f8b-89d03325bdc5",
                  "testMode": true,
                  "resellerReference": "NB-2026-00417",
                  "supplierReference": "VT260928N1EVP",
                  "status": "CONFIRMED",
                  "utcCreatedAt": "2026-09-28T20:28:36+00:00",
                  "utcUpdatedAt": "2026-09-28T20:28:36+00:00",
                  "utcExpiresAt": "2026-09-28T20:58:36+00:00",
                  "utcRedeemedAt": null,
                  "utcConfirmedAt": "2026-09-28T20:28:36+00:00",
                  "productId": "c86ea1c1-a986-4d1f-bd23-6bec906beffa",
                  "optionId": "d7bbe7df-6d64-45a8-b8f9-69dace2d4f9c",
                  "cancellable": true,
                  "confirmable": false,
                  "freesale": false,
                  "availabilityId": "593651fd-fb2d-4132-91cf-1764ceb6c885",
                  "availability": {
                    "id": "593651fd-fb2d-4132-91cf-1764ceb6c885",
                    "localDateTimeStart": "2026-10-03T07:00:00+03:00",
                    "localDateTimeEnd": "2026-10-03T10:00:00+03:00",
                    "allDay": false,
                    "openingHours": []
                  },
                  "contact": {
                    "fullName": "Hannah Lindqvist",
                    "firstName": "Hannah",
                    "lastName": "Lindqvist",
                    "emailAddress": "hannah@example.com",
                    "phoneNumber": "+46 70 123 4567",
                    "country": "SE",
                    "locales": [
                      "en"
                    ]
                  },
                  "notes": null,
                  "deliveryMethods": [
                    "TICKET",
                    "VOUCHER"
                  ],
                  "voucher": {
                    "id": "c83ddd29-5b09-4e0b-b804-d3547eabc3f4",
                    "redemptionMethod": "DIGITAL",
                    "utcRedeemedAt": null,
                    "deliveryOptions": [
                      {
                        "deliveryFormat": "QRCODE",
                        "deliveryValue": "VTOEFJZDB3IH"
                      },
                      {
                        "deliveryFormat": "PDF_URL",
                        "deliveryValue": "https://api.vacotours.com/api/vouchers/c83ddd29-5b09-4e0b-b804-d3547eabc3f4?signature=3b1f...e9a2"
                      }
                    ]
                  },
                  "unitItems": [
                    {
                      "uuid": "41f1ced0-29e6-4359-a176-a23ab7a3a796",
                      "id": "41f1ced0-29e6-4359-a176-a23ab7a3a796",
                      "resellerReference": null,
                      "supplierReference": "41f1ced0-29e6-4359-a176-a23ab7a3a796",
                      "unitId": "0d04e5e0-67cb-4f6c-aa87-d5d3be2744cb",
                      "unitType": "ADULT",
                      "status": "CONFIRMED",
                      "utcRedeemedAt": null,
                      "contact": {},
                      "ticket": {
                        "id": "c83ddd29-5b09-4e0b-b804-d3547eabc3f4",
                        "redemptionMethod": "DIGITAL",
                        "utcRedeemedAt": null,
                        "deliveryOptions": [
                          {
                            "deliveryFormat": "QRCODE",
                            "deliveryValue": "VTOEFJZDB3IH"
                          },
                          {
                            "deliveryFormat": "PDF_URL",
                            "deliveryValue": "https://api.vacotours.com/api/vouchers/c83ddd29-5b09-4e0b-b804-d3547eabc3f4?signature=3b1f...e9a2"
                          }
                        ]
                      },
                      "questionAnswers": [],
                      "pricing": {
                        "original": 3826,
                        "retail": 3826,
                        "net": 3364,
                        "currency": "USD",
                        "currencyPrecision": 2,
                        "includedTaxes": []
                      }
                    },
                    {
                      "uuid": "a07f1196-2969-4f80-b5a1-8daf56178e0a",
                      "id": "a07f1196-2969-4f80-b5a1-8daf56178e0a",
                      "resellerReference": null,
                      "supplierReference": "a07f1196-2969-4f80-b5a1-8daf56178e0a",
                      "unitId": "0d04e5e0-67cb-4f6c-aa87-d5d3be2744cb",
                      "unitType": "ADULT",
                      "status": "CONFIRMED",
                      "utcRedeemedAt": null,
                      "contact": {},
                      "ticket": {
                        "id": "2b4198f3-8f8c-44a1-9c7d-e872df3c5995",
                        "redemptionMethod": "DIGITAL",
                        "utcRedeemedAt": null,
                        "deliveryOptions": [
                          {
                            "deliveryFormat": "QRCODE",
                            "deliveryValue": "VTGAXVRPZAKA"
                          },
                          {
                            "deliveryFormat": "PDF_URL",
                            "deliveryValue": "https://api.vacotours.com/api/vouchers/2b4198f3-8f8c-44a1-9c7d-e872df3c5995?signature=3b1f...e9a2"
                          }
                        ]
                      },
                      "questionAnswers": [],
                      "pricing": {
                        "original": 3826,
                        "retail": 3826,
                        "net": 3364,
                        "currency": "USD",
                        "currencyPrecision": 2,
                        "includedTaxes": []
                      }
                    }
                  ],
                  "questionAnswers": [],
                  "pricing": {
                    "original": 7652,
                    "retail": 7652,
                    "net": 6728,
                    "currency": "USD",
                    "currencyPrecision": 2,
                    "includedTaxes": []
                  },
                  "pickupRequested": false,
                  "pickupPointId": null,
                  "pickupHotel": null,
                  "pickupHotelRoom": null,
                  "pickupAddress": null,
                  "pickupTime": null,
                  "pickupNotes": null
                }
              }
            }
          },
          "400": {
            "description": "Rejected. See error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "This key may not do that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Over the rate limit. Retry-After says when.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "Octo-Capabilities",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "Comma separated, for example `octo/pricing, octo/content`."
          },
          {
            "name": "uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      },
      "patch": {
        "tags": [
          "Bookings"
        ],
        "summary": "Update a booking",
        "description": "Change the lead contact, a traveller's details (by unit item uuid), notes or your reference.",
        "operationId": "updateBooking",
        "responses": {
          "200": {
            "description": "The booking.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Booking"
                }
              }
            }
          },
          "400": {
            "description": "Rejected. See error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "This key may not do that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Over the rate limit. Retry-After says when.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "contact": {
                    "$ref": "#/components/schemas/Contact"
                  },
                  "notes": {
                    "type": "string"
                  },
                  "resellerReference": {
                    "type": "string"
                  },
                  "unitItems": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "uuid": {
                          "type": "string"
                        },
                        "contact": {
                          "$ref": "#/components/schemas/Contact"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/bookings/{uuid}/confirm": {
      "post": {
        "tags": [
          "Bookings"
        ],
        "summary": "Confirm",
        "description": "Sells the hold: funds are captured, the operator is told and vouchers are issued. Send the lead contact here if you did not at reserve.",
        "operationId": "confirmBooking",
        "responses": {
          "200": {
            "description": "Confirmed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Booking"
                },
                "example": {
                  "id": "b00b620a-3a67-4e80-8f8b-89d03325bdc5",
                  "uuid": "b00b620a-3a67-4e80-8f8b-89d03325bdc5",
                  "testMode": true,
                  "resellerReference": "NB-2026-00417",
                  "supplierReference": "VT260928N1EVP",
                  "status": "CONFIRMED",
                  "utcCreatedAt": "2026-09-28T20:28:36+00:00",
                  "utcUpdatedAt": "2026-09-28T20:28:36+00:00",
                  "utcExpiresAt": "2026-09-28T20:58:36+00:00",
                  "utcRedeemedAt": null,
                  "utcConfirmedAt": "2026-09-28T20:28:36+00:00",
                  "productId": "c86ea1c1-a986-4d1f-bd23-6bec906beffa",
                  "optionId": "d7bbe7df-6d64-45a8-b8f9-69dace2d4f9c",
                  "cancellable": true,
                  "confirmable": false,
                  "freesale": false,
                  "availabilityId": "593651fd-fb2d-4132-91cf-1764ceb6c885",
                  "availability": {
                    "id": "593651fd-fb2d-4132-91cf-1764ceb6c885",
                    "localDateTimeStart": "2026-10-03T07:00:00+03:00",
                    "localDateTimeEnd": "2026-10-03T10:00:00+03:00",
                    "allDay": false,
                    "openingHours": []
                  },
                  "contact": {
                    "fullName": "Hannah Lindqvist",
                    "firstName": "Hannah",
                    "lastName": "Lindqvist",
                    "emailAddress": "hannah@example.com",
                    "phoneNumber": "+46 70 123 4567",
                    "country": "SE",
                    "locales": [
                      "en"
                    ]
                  },
                  "notes": null,
                  "deliveryMethods": [
                    "TICKET",
                    "VOUCHER"
                  ],
                  "voucher": {
                    "id": "c83ddd29-5b09-4e0b-b804-d3547eabc3f4",
                    "redemptionMethod": "DIGITAL",
                    "utcRedeemedAt": null,
                    "deliveryOptions": [
                      {
                        "deliveryFormat": "QRCODE",
                        "deliveryValue": "VTOEFJZDB3IH"
                      },
                      {
                        "deliveryFormat": "PDF_URL",
                        "deliveryValue": "https://api.vacotours.com/api/vouchers/c83ddd29-5b09-4e0b-b804-d3547eabc3f4?signature=3b1f...e9a2"
                      }
                    ]
                  },
                  "unitItems": [
                    {
                      "uuid": "41f1ced0-29e6-4359-a176-a23ab7a3a796",
                      "id": "41f1ced0-29e6-4359-a176-a23ab7a3a796",
                      "resellerReference": null,
                      "supplierReference": "41f1ced0-29e6-4359-a176-a23ab7a3a796",
                      "unitId": "0d04e5e0-67cb-4f6c-aa87-d5d3be2744cb",
                      "unitType": "ADULT",
                      "status": "CONFIRMED",
                      "utcRedeemedAt": null,
                      "contact": {},
                      "ticket": {
                        "id": "c83ddd29-5b09-4e0b-b804-d3547eabc3f4",
                        "redemptionMethod": "DIGITAL",
                        "utcRedeemedAt": null,
                        "deliveryOptions": [
                          {
                            "deliveryFormat": "QRCODE",
                            "deliveryValue": "VTOEFJZDB3IH"
                          },
                          {
                            "deliveryFormat": "PDF_URL",
                            "deliveryValue": "https://api.vacotours.com/api/vouchers/c83ddd29-5b09-4e0b-b804-d3547eabc3f4?signature=3b1f...e9a2"
                          }
                        ]
                      },
                      "questionAnswers": [],
                      "pricing": {
                        "original": 3826,
                        "retail": 3826,
                        "net": 3364,
                        "currency": "USD",
                        "currencyPrecision": 2,
                        "includedTaxes": []
                      }
                    },
                    {
                      "uuid": "a07f1196-2969-4f80-b5a1-8daf56178e0a",
                      "id": "a07f1196-2969-4f80-b5a1-8daf56178e0a",
                      "resellerReference": null,
                      "supplierReference": "a07f1196-2969-4f80-b5a1-8daf56178e0a",
                      "unitId": "0d04e5e0-67cb-4f6c-aa87-d5d3be2744cb",
                      "unitType": "ADULT",
                      "status": "CONFIRMED",
                      "utcRedeemedAt": null,
                      "contact": {},
                      "ticket": {
                        "id": "2b4198f3-8f8c-44a1-9c7d-e872df3c5995",
                        "redemptionMethod": "DIGITAL",
                        "utcRedeemedAt": null,
                        "deliveryOptions": [
                          {
                            "deliveryFormat": "QRCODE",
                            "deliveryValue": "VTGAXVRPZAKA"
                          },
                          {
                            "deliveryFormat": "PDF_URL",
                            "deliveryValue": "https://api.vacotours.com/api/vouchers/2b4198f3-8f8c-44a1-9c7d-e872df3c5995?signature=3b1f...e9a2"
                          }
                        ]
                      },
                      "questionAnswers": [],
                      "pricing": {
                        "original": 3826,
                        "retail": 3826,
                        "net": 3364,
                        "currency": "USD",
                        "currencyPrecision": 2,
                        "includedTaxes": []
                      }
                    }
                  ],
                  "questionAnswers": [],
                  "pricing": {
                    "original": 7652,
                    "retail": 7652,
                    "net": 6728,
                    "currency": "USD",
                    "currencyPrecision": 2,
                    "includedTaxes": []
                  },
                  "pickupRequested": false,
                  "pickupPointId": null,
                  "pickupHotel": null,
                  "pickupHotelRoom": null,
                  "pickupAddress": null,
                  "pickupTime": null,
                  "pickupNotes": null
                }
              }
            }
          },
          "400": {
            "description": "Rejected. See error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "This key may not do that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Over the rate limit. Retry-After says when.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "Octo-Capabilities",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "Comma separated, for example `octo/pricing, octo/content`."
          },
          {
            "name": "uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "contact": {
                    "$ref": "#/components/schemas/Contact"
                  },
                  "resellerReference": {
                    "type": "string"
                  },
                  "notes": {
                    "type": "string"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/bookings/{uuid}/cancel": {
      "post": {
        "tags": [
          "Bookings"
        ],
        "summary": "Cancel",
        "description": "A hold is released in full. A confirmed booking is refunded to your wallet on the operator's terms; `cancellation.refundAmount` says how much.",
        "operationId": "cancelBooking",
        "responses": {
          "200": {
            "description": "Cancelled.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Booking"
                },
                "example": {
                  "id": "b00b620a-3a67-4e80-8f8b-89d03325bdc5",
                  "uuid": "b00b620a-3a67-4e80-8f8b-89d03325bdc5",
                  "testMode": true,
                  "resellerReference": "NB-2026-00417",
                  "supplierReference": "VT260928N1EVP",
                  "status": "CANCELLED",
                  "utcCreatedAt": "2026-09-28T20:28:36+00:00",
                  "utcUpdatedAt": "2026-09-28T20:28:37+00:00",
                  "utcExpiresAt": "2026-09-28T20:58:36+00:00",
                  "utcRedeemedAt": null,
                  "utcConfirmedAt": "2026-09-28T20:28:36+00:00",
                  "productId": "c86ea1c1-a986-4d1f-bd23-6bec906beffa",
                  "optionId": "d7bbe7df-6d64-45a8-b8f9-69dace2d4f9c",
                  "cancellable": false,
                  "confirmable": false,
                  "freesale": false,
                  "availabilityId": "593651fd-fb2d-4132-91cf-1764ceb6c885",
                  "availability": {
                    "id": "593651fd-fb2d-4132-91cf-1764ceb6c885",
                    "localDateTimeStart": "2026-10-03T07:00:00+03:00",
                    "localDateTimeEnd": "2026-10-03T10:00:00+03:00",
                    "allDay": false,
                    "openingHours": []
                  },
                  "contact": {
                    "fullName": "Hannah Lindqvist",
                    "firstName": "Hannah",
                    "lastName": "Lindqvist",
                    "emailAddress": "hannah@example.com",
                    "phoneNumber": "+46 70 123 4567",
                    "country": "SE",
                    "locales": [
                      "en"
                    ]
                  },
                  "notes": null,
                  "deliveryMethods": [
                    "TICKET",
                    "VOUCHER"
                  ],
                  "voucher": {
                    "id": "c83ddd29-5b09-4e0b-b804-d3547eabc3f4",
                    "redemptionMethod": "DIGITAL",
                    "utcRedeemedAt": null,
                    "deliveryOptions": [
                      {
                        "deliveryFormat": "QRCODE",
                        "deliveryValue": "VTOEFJZDB3IH"
                      },
                      {
                        "deliveryFormat": "PDF_URL",
                        "deliveryValue": "https://api.vacotours.com/api/vouchers/c83ddd29-5b09-4e0b-b804-d3547eabc3f4?signature=3b1f...e9a2"
                      }
                    ]
                  },
                  "unitItems": [
                    {
                      "uuid": "41f1ced0-29e6-4359-a176-a23ab7a3a796",
                      "id": "41f1ced0-29e6-4359-a176-a23ab7a3a796",
                      "resellerReference": null,
                      "supplierReference": "41f1ced0-29e6-4359-a176-a23ab7a3a796",
                      "unitId": "0d04e5e0-67cb-4f6c-aa87-d5d3be2744cb",
                      "unitType": "ADULT",
                      "status": "CANCELLED",
                      "utcRedeemedAt": null,
                      "contact": {},
                      "ticket": {
                        "id": "c83ddd29-5b09-4e0b-b804-d3547eabc3f4",
                        "redemptionMethod": "DIGITAL",
                        "utcRedeemedAt": null,
                        "deliveryOptions": [
                          {
                            "deliveryFormat": "QRCODE",
                            "deliveryValue": "VTOEFJZDB3IH"
                          },
                          {
                            "deliveryFormat": "PDF_URL",
                            "deliveryValue": "https://api.vacotours.com/api/vouchers/c83ddd29-5b09-4e0b-b804-d3547eabc3f4?signature=3b1f...e9a2"
                          }
                        ]
                      },
                      "questionAnswers": [],
                      "pricing": {
                        "original": 3826,
                        "retail": 3826,
                        "net": 3364,
                        "currency": "USD",
                        "currencyPrecision": 2,
                        "includedTaxes": []
                      }
                    },
                    {
                      "uuid": "a07f1196-2969-4f80-b5a1-8daf56178e0a",
                      "id": "a07f1196-2969-4f80-b5a1-8daf56178e0a",
                      "resellerReference": null,
                      "supplierReference": "a07f1196-2969-4f80-b5a1-8daf56178e0a",
                      "unitId": "0d04e5e0-67cb-4f6c-aa87-d5d3be2744cb",
                      "unitType": "ADULT",
                      "status": "CANCELLED",
                      "utcRedeemedAt": null,
                      "contact": {},
                      "ticket": {
                        "id": "2b4198f3-8f8c-44a1-9c7d-e872df3c5995",
                        "redemptionMethod": "DIGITAL",
                        "utcRedeemedAt": null,
                        "deliveryOptions": [
                          {
                            "deliveryFormat": "QRCODE",
                            "deliveryValue": "VTGAXVRPZAKA"
                          },
                          {
                            "deliveryFormat": "PDF_URL",
                            "deliveryValue": "https://api.vacotours.com/api/vouchers/2b4198f3-8f8c-44a1-9c7d-e872df3c5995?signature=3b1f...e9a2"
                          }
                        ]
                      },
                      "questionAnswers": [],
                      "pricing": {
                        "original": 3826,
                        "retail": 3826,
                        "net": 3364,
                        "currency": "USD",
                        "currencyPrecision": 2,
                        "includedTaxes": []
                      }
                    }
                  ],
                  "questionAnswers": [],
                  "cancellation": {
                    "refund": "PARTIAL",
                    "reason": "Customer changed plans",
                    "utcCancelledAt": "2026-09-28T20:28:37+00:00",
                    "refundAmount": {
                      "original": 3364,
                      "retail": 3364,
                      "net": 3364,
                      "currency": "USD",
                      "currencyPrecision": 2,
                      "includedTaxes": []
                    }
                  },
                  "pricing": {
                    "original": 7652,
                    "retail": 7652,
                    "net": 6728,
                    "currency": "USD",
                    "currencyPrecision": 2,
                    "includedTaxes": []
                  },
                  "pickupRequested": false,
                  "pickupPointId": null,
                  "pickupHotel": null,
                  "pickupHotelRoom": null,
                  "pickupAddress": null,
                  "pickupTime": null,
                  "pickupNotes": null
                }
              }
            }
          },
          "400": {
            "description": "Rejected. See error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "This key may not do that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Over the rate limit. Retry-After says when.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "Octo-Capabilities",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "Comma separated, for example `octo/pricing, octo/content`."
          },
          {
            "name": "uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/bookings/{uuid}/extend": {
      "post": {
        "tags": [
          "Bookings"
        ],
        "summary": "Extend a hold",
        "description": "Push `utcExpiresAt` out, 5 to 1440 minutes from now.",
        "operationId": "extendBooking",
        "responses": {
          "200": {
            "description": "Extended.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Booking"
                }
              }
            }
          },
          "400": {
            "description": "Rejected. See error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "This key may not do that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Over the rate limit. Retry-After says when.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "expirationMinutes": {
                    "type": "integer"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/bookings/{uuid}/redeem": {
      "post": {
        "tags": [
          "Bookings"
        ],
        "summary": "Redeem",
        "description": "Mark a confirmed booking used. Idempotent.",
        "operationId": "redeemBooking",
        "responses": {
          "200": {
            "description": "Redeemed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Booking"
                }
              }
            }
          },
          "400": {
            "description": "Rejected. See error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "This key may not do that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Over the rate limit. Retry-After says when.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/quote-requests": {
      "post": {
        "tags": [
          "Quotes"
        ],
        "summary": "Ask for a price",
        "description": "For a product with `quoteOnly: true`. The operator answers with a price for the whole group; you are emailed and the request moves to `quoted`.",
        "operationId": "createQuoteRequest",
        "responses": {
          "201": {
            "description": "Asked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuoteRequest"
                }
              }
            }
          },
          "400": {
            "description": "Rejected. See error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "This key may not do that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Over the rate limit. Retry-After says when.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/QuoteRequestBody"
              },
              "example": {
                "productId": "0b8f...",
                "groupSize": 12,
                "travelDate": "2026-11-03",
                "endDate": "2026-11-07",
                "budget": 15000,
                "message": "Incentive group, four nights, one gala dinner.",
                "contact": {
                  "firstName": "Nia",
                  "lastName": "Ko",
                  "emailAddress": "nia@example.com"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Quotes"
        ],
        "summary": "List your requests",
        "description": "Newest first. Filter with `?status=quoted` to find answers waiting for you.",
        "operationId": "listQuoteRequests",
        "responses": {
          "200": {
            "description": "Requests.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/QuoteRequest"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Rejected. See error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "This key may not do that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Over the rate limit. Retry-After says when.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer"
            }
          }
        ]
      }
    },
    "/quote-requests/{uuid}": {
      "get": {
        "tags": [
          "Quotes"
        ],
        "summary": "Get a request",
        "description": "Its status and, once answered, the price, the note and how long it stands.",
        "operationId": "getQuoteRequest",
        "responses": {
          "200": {
            "description": "The request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuoteRequest"
                }
              }
            }
          },
          "400": {
            "description": "Rejected. See error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "This key may not do that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Over the rate limit. Retry-After says when.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/quote-requests/{uuid}/accept": {
      "post": {
        "tags": [
          "Quotes"
        ],
        "summary": "Book the quoted price",
        "description": "Only while `bookable`. Makes an ordinary booking on hold, with your funds held; confirm it like any other. Accepting again returns the same booking.",
        "operationId": "acceptQuoteRequest",
        "responses": {
          "201": {
            "description": "Booked, on hold.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "409": {
            "description": "Not quoted, or the price has run out.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "400": {
            "description": "Rejected. See error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "This key may not do that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Over the rate limit. Retry-After says when.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/quote-requests/{uuid}/withdraw": {
      "post": {
        "tags": [
          "Quotes"
        ],
        "summary": "Withdraw",
        "description": "While open or quoted.",
        "operationId": "withdrawQuoteRequest",
        "responses": {
          "200": {
            "description": "Withdrawn.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuoteRequest"
                }
              }
            }
          },
          "400": {
            "description": "Rejected. See error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "This key may not do that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Over the rate limit. Retry-After says when.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/webhooks": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "summary": "List webhooks",
        "description": "Your subscriptions.",
        "operationId": "listWebhooks",
        "responses": {
          "200": {
            "description": "Webhooks.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Webhook"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Rejected. See error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "This key may not do that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Over the rate limit. Retry-After says when.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Subscribe",
        "description": "Receive `booking_update` whenever one of your bookings changes: reserved, confirmed, cancelled, extended, updated, redeemed or expired. Deliveries are POSTed as `{ id, event, createdAt, data: { booking } }` with the booking in the same shape as GET /bookings/{uuid}, signed in `Octo-Signature`, and retried with backoff when your endpoint fails.",
        "operationId": "createWebhook",
        "responses": {
          "201": {
            "description": "Subscribed. Keep the secret.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Webhook"
                }
              }
            }
          },
          "400": {
            "description": "Rejected. See error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "This key may not do that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Over the rate limit. Retry-After says when.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "description": "https only."
                  },
                  "event": {
                    "type": "string",
                    "enum": [
                      "booking_update"
                    ]
                  }
                },
                "required": [
                  "url"
                ]
              },
              "example": {
                "url": "https://example.com/hooks/vacotours",
                "event": "booking_update"
              }
            }
          }
        }
      }
    },
    "/webhooks/{id}": {
      "delete": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Unsubscribe",
        "description": "Stop deliveries to this endpoint.",
        "operationId": "deleteWebhook",
        "responses": {
          "200": {
            "description": "Removed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Webhook"
                }
              }
            }
          },
          "400": {
            "description": "Rejected. See error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "This key may not do that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Over the rate limit. Retry-After says when.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/mappings": {
      "get": {
        "tags": [
          "Products"
        ],
        "summary": "Mappings",
        "description": "Every product, option and unit you can sell, one row each, for matching them to your own catalogue.",
        "operationId": "mappings",
        "responses": {
          "200": {
            "description": "Rows.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Rejected. See error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "This key may not do that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Over the rate limit. Retry-After says when.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 500
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "source",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "direct",
                "channel"
              ],
              "default": "all"
            },
            "description": "Only our own operators' products (direct), only resold ones (channel), or both. Narrows what the key is set to; never widens it."
          }
        ]
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Your token, `{key}.{secret}`."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          },
          "errorMessage": {
            "type": "string"
          },
          "errors": {
            "type": "object"
          }
        }
      },
      "Pricing": {
        "type": "object",
        "properties": {
          "original": {
            "type": "integer",
            "description": "Same as retail."
          },
          "retail": {
            "type": "integer",
            "description": "What a traveller pays on our own site, the recommended selling price, in minor units."
          },
          "net": {
            "type": [
              "integer",
              "null"
            ],
            "description": "What the caller pays, in minor units. Null for a key that is not buying (an operator reading the bookings of its own inventory)."
          },
          "currency": {
            "type": "string",
            "example": "USD"
          },
          "currencyPrecision": {
            "type": "integer",
            "example": 2
          },
          "includedTaxes": {
            "type": "array",
            "items": {
              "type": "object"
            }
          }
        },
        "description": "An OCTO Pricing object."
      },
      "Question": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Send this back as questionId."
          },
          "label": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "required": {
            "type": "boolean"
          },
          "inputType": {
            "type": "string",
            "description": "One of text, textarea, number, select, select_multiple, checkbox, date (YYYY-MM-DD), time (HH:MM), datetime, country (an ISO code or the English name), phone, email, file.",
            "enum": [
              "text",
              "textarea",
              "number",
              "select",
              "select_multiple",
              "checkbox",
              "date",
              "time",
              "datetime",
              "country",
              "phone",
              "email",
              "file"
            ]
          },
          "perUnitItem": {
            "type": "boolean",
            "description": "True when asked of every traveller: answer it on each unit item."
          },
          "scope": {
            "type": "string",
            "enum": [
              "BOOKING",
              "UNIT_ITEM"
            ]
          },
          "selectOptions": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "value": {
                  "type": "string"
                },
                "label": {
                  "type": "string"
                },
                "pricing": {
                  "$ref": "#/components/schemas/Pricing"
                }
              }
            }
          },
          "pricing": {
            "$ref": "#/components/schemas/Pricing"
          },
          "format": {
            "type": "string",
            "description": "A regular expression the answer must match."
          },
          "minNumber": {
            "type": "integer"
          },
          "maxNumber": {
            "type": "integer"
          },
          "validFrom": {
            "type": "string",
            "description": "Only asked for travel on or after this date.",
            "format": "date"
          },
          "validTo": {
            "type": "string",
            "description": "Only asked for travel on or before this date.",
            "format": "date"
          }
        },
        "description": "A question the operator asks. Answers are checked when you reserve: a required per-traveller question must be answered for every traveller, a choice must be one offered, and a format must match.",
        "example": {
          "id": "6f1c...a2",
          "label": "Passport number",
          "required": true,
          "inputType": "text",
          "perUnitItem": true,
          "scope": "UNIT_ITEM"
        }
      },
      "QuestionAnswer": {
        "type": "object",
        "properties": {
          "questionId": {
            "type": "string"
          },
          "value": {
            "type": "string",
            "description": "For a select_multiple, send the answer once per value."
          }
        },
        "required": [
          "questionId",
          "value"
        ]
      },
      "PickupPoint": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "address": {
            "type": "string"
          },
          "latitude": {
            "type": "number"
          },
          "longitude": {
            "type": "number"
          },
          "googlePlaceId": {
            "type": "string"
          },
          "localTime": {
            "type": "string",
            "description": "When the vehicle is there."
          },
          "windowMinutes": {
            "type": "integer"
          },
          "surcharge": {
            "$ref": "#/components/schemas/Pricing"
          }
        }
      },
      "MeetingPoint": {
        "type": "object",
        "properties": {
          "time": {
            "type": [
              "string",
              "null"
            ]
          },
          "address": {
            "type": [
              "string",
              "null"
            ]
          },
          "location": {
            "type": [
              "string",
              "null"
            ],
            "description": "Directions, in words."
          },
          "latitude": {
            "type": [
              "number",
              "null"
            ]
          },
          "longitude": {
            "type": [
              "number",
              "null"
            ]
          },
          "googlePlaceId": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "description": "Where the experience starts."
      },
      "Unit": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "internalName": {
            "type": "string"
          },
          "reference": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "description": "The OCTO type. Our own categories that OCTO has no word for (group, vehicle, single supplement) are OTHER; unit.category has ours.",
            "enum": [
              "ADULT",
              "YOUTH",
              "CHILD",
              "INFANT",
              "FAMILY",
              "SENIOR",
              "STUDENT",
              "MILITARY",
              "OTHER"
            ]
          },
          "requiredContactFields": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "visibleContactFields": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "restrictions": {
            "type": "object",
            "properties": {
              "minAge": {
                "type": "integer"
              },
              "maxAge": {
                "type": "integer"
              },
              "idRequired": {
                "type": "boolean"
              },
              "minQuantity": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "maxQuantity": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "paxCount": {
                "type": "integer",
                "description": "How many travellers one of these is. A family ticket is four."
              },
              "accompaniedBy": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "required": {
                "type": "boolean",
                "description": "A booking must include at least minQuantity of these."
              },
              "perDeparture": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "How many of this one departure has in all: cabins of a grade, seats in a zone, rooms of a type. What is left is unitAvailability on each availability."
              }
            }
          },
          "pricingFrom": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Pricing"
            }
          },
          "unit": {
            "type": "object",
            "properties": {
              "title": {
                "type": "string"
              },
              "titlePlural": {
                "type": "string"
              },
              "subtitle": {
                "type": "string"
              },
              "category": {
                "type": "string",
                "description": "Our own category."
              },
              "ageLabel": {
                "type": "string"
              }
            },
            "description": "octo/content"
          }
        }
      },
      "Option": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "default": {
            "type": "boolean"
          },
          "internalName": {
            "type": "string"
          },
          "reference": {
            "type": [
              "string",
              "null"
            ]
          },
          "availabilityLocalStartTimes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "availabilityLocalDateStart": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "availabilityLocalDateEnd": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "cancellationCutoff": {
            "type": "string"
          },
          "cancellationCutoffAmount": {
            "type": "integer"
          },
          "cancellationCutoffUnit": {
            "type": "string"
          },
          "availabilityCutoff": {
            "type": "string"
          },
          "availabilityCutoffAmount": {
            "type": "integer"
          },
          "availabilityCutoffUnit": {
            "type": "string"
          },
          "requiredContactFields": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "visibleContactFields": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "restrictions": {
            "type": "object",
            "properties": {
              "minUnits": {
                "type": "integer"
              },
              "maxUnits": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "minPaxCount": {
                "type": "integer"
              },
              "maxPaxCount": {
                "type": [
                  "integer",
                  "null"
                ]
              }
            }
          },
          "units": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Unit"
            }
          },
          "rental": {
            "$ref": "#/components/schemas/RentalTerms"
          },
          "pricingFrom": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Pricing"
            }
          },
          "option": {
            "type": "object",
            "properties": {
              "title": {
                "type": "string"
              },
              "subtitle": {
                "type": "string"
              },
              "shortDescription": {
                "type": "string"
              },
              "language": {
                "type": "string"
              },
              "duration": {
                "type": "string"
              },
              "durationAmount": {
                "type": "string"
              },
              "durationUnit": {
                "type": "string"
              },
              "instantConfirmation": {
                "type": "boolean"
              },
              "meetingPoint": {
                "$ref": "#/components/schemas/MeetingPoint"
              },
              "details": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "section": {
                      "type": "string",
                      "description": "rental_terms, coverage, pass_inclusions, event_details, guide_profile, course_schedule, transfer_route, route, accommodation, cabins, seating or quote_settings."
                    },
                    "label": {
                      "type": "string",
                      "description": "The section, in words."
                    },
                    "fields": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string"
                          },
                          "label": {
                            "type": "string"
                          },
                          "type": {
                            "type": "string",
                            "enum": [
                              "text",
                              "textarea",
                              "number",
                              "money",
                              "boolean",
                              "time",
                              "select",
                              "multiselect",
                              "list",
                              "countries"
                            ]
                          },
                          "value": {
                            "description": "The raw value: a number, true or false, a string, or a list. Money is US dollars."
                          },
                          "display": {
                            "description": "The value in words, ready to show."
                          }
                        }
                      }
                    }
                  }
                },
                "description": "What this kind of product says about itself: a rental's deposit and driver age, an eSIM's countries and data, a pass's attractions, a venue, a route. Self-describing: show display, or read value."
              },
              "validity": {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string"
                  },
                  "days": {
                    "type": "integer"
                  },
                  "date": {
                    "type": "string"
                  }
                }
              },
              "voucher": {
                "type": "object",
                "properties": {
                  "requiresPrinting": {
                    "type": "boolean"
                  },
                  "directAdmission": {
                    "type": "boolean"
                  },
                  "redemptionAddress": {
                    "type": "string"
                  },
                  "instructions": {
                    "type": "string"
                  }
                }
              },
              "itinerary": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "day": {
                      "type": "integer"
                    },
                    "name": {
                      "type": "string"
                    },
                    "type": {
                      "type": "string"
                    },
                    "description": {
                      "type": "string"
                    },
                    "address": {
                      "type": "string"
                    },
                    "latitude": {
                      "type": "number"
                    },
                    "longitude": {
                      "type": "number"
                    },
                    "durationAmount": {
                      "type": "integer"
                    },
                    "durationUnit": {
                      "type": "string"
                    }
                  }
                }
              }
            },
            "description": "octo/content"
          },
          "isRefundable": {
            "type": "boolean",
            "description": "octo/cancellation"
          },
          "cancellationPolicies": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "cutoffHours": {
                  "type": "integer"
                },
                "refundPercentage": {
                  "type": "integer"
                },
                "cancellationFeePercentage": {
                  "type": "integer"
                },
                "serviceFee": {
                  "$ref": "#/components/schemas/Pricing"
                },
                "serviceFeePerBooking": {
                  "type": "boolean"
                }
              }
            }
          },
          "questions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Question"
            }
          },
          "pickupAvailable": {
            "type": "boolean"
          },
          "pickupRequired": {
            "type": "boolean"
          },
          "pickupPoints": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PickupPoint"
            }
          },
          "dropoffAvailable": {
            "type": "boolean"
          },
          "dropoffRequired": {
            "type": "boolean"
          },
          "dropoffPoints": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PickupPoint"
            }
          }
        }
      },
      "Product": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "internalName": {
            "type": "string"
          },
          "reference": {
            "type": "string"
          },
          "locale": {
            "type": "string"
          },
          "timeZone": {
            "type": "string"
          },
          "allowFreesale": {
            "type": "boolean"
          },
          "instantConfirmation": {
            "type": "boolean"
          },
          "instantDelivery": {
            "type": "boolean"
          },
          "availabilityRequired": {
            "type": "boolean"
          },
          "availabilityType": {
            "type": "string",
            "enum": [
              "START_TIME",
              "OPENING_HOURS"
            ]
          },
          "deliveryFormats": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "deliveryMethods": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "redemptionMethod": {
            "type": "string"
          },
          "options": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Option"
            }
          },
          "defaultCurrency": {
            "type": "string"
          },
          "availableCurrencies": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "pricingPer": {
            "type": "string",
            "description": "BOOKING: one price for the whole party.",
            "enum": [
              "UNIT",
              "BOOKING"
            ]
          },
          "includeTax": {
            "type": "boolean"
          },
          "includedTaxes": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "product": {
            "type": "object",
            "properties": {
              "title": {
                "type": "string"
              },
              "slug": {
                "type": "string"
              },
              "source": {
                "type": "string",
                "description": "direct: run by one of our own operators. channel: resold from a partner platform.",
                "enum": [
                  "direct",
                  "channel"
                ]
              },
              "country": {
                "type": "string"
              },
              "location": {
                "type": "string"
              },
              "subtitle": {
                "type": "string"
              },
              "shortDescription": {
                "type": "string"
              },
              "description": {
                "type": "string"
              },
              "highlights": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "inclusions": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "exclusions": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "bookingTerms": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "redemptionInstructions": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "safety": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "alert": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "alerts": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "faqs": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "question": {
                      "type": "string"
                    },
                    "answer": {
                      "type": "string"
                    }
                  }
                }
              },
              "coverImageUrl": {
                "type": "string"
              },
              "bannerImageUrl": {
                "type": "string"
              },
              "galleryImages": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "url": {
                      "type": "string"
                    },
                    "title": {
                      "type": "string"
                    },
                    "caption": {
                      "type": "string"
                    },
                    "alt": {
                      "type": "string"
                    },
                    "width": {
                      "type": "integer"
                    },
                    "height": {
                      "type": "integer"
                    }
                  }
                }
              },
              "images": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "url": {
                      "type": "string"
                    },
                    "title": {
                      "type": "string"
                    },
                    "caption": {
                      "type": "string"
                    },
                    "alt": {
                      "type": "string"
                    },
                    "width": {
                      "type": "integer"
                    },
                    "height": {
                      "type": "integer"
                    }
                  }
                }
              },
              "duration": {
                "type": "string"
              },
              "durationMinutes": {
                "type": "integer"
              },
              "destination": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  },
                  "state": {
                    "type": "string"
                  },
                  "country": {
                    "type": "string"
                  },
                  "countryName": {
                    "type": "string"
                  },
                  "countryId": {
                    "type": "string"
                  },
                  "address": {
                    "type": "string"
                  },
                  "latitude": {
                    "type": "number"
                  },
                  "longitude": {
                    "type": "number"
                  },
                  "googlePlaceId": {
                    "type": "string"
                  },
                  "icon": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "The marker to draw it with on a map, by name (Lucide's): map-pin, landmark, castle, building-2, mountain, tree-pine, palmtree, waves, sailboat, ship, fish, bird, footprints, bike, bus, car, train-front, plane, camera, tent, ticket, utensils, wine, shopping-bag, music, sun, snowflake."
                  },
                  "iconUrl": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "An SVG of that marker, ready to put on a map."
                  }
                }
              },
              "categories": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "The category slug."
                    },
                    "uuid": {
                      "type": "string"
                    },
                    "title": {
                      "type": "string"
                    }
                  }
                }
              },
              "productType": {
                "type": "object",
                "properties": {
                  "code": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  },
                  "family": {
                    "type": "string"
                  }
                }
              },
              "rating": {
                "type": "object",
                "properties": {
                  "average": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "count": {
                    "type": "integer"
                  }
                }
              },
              "supplier": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  }
                }
              },
              "languages": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "details": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "section": {
                      "type": "string",
                      "description": "rental_terms, coverage, pass_inclusions, event_details, guide_profile, course_schedule, transfer_route, route, accommodation, cabins, seating or quote_settings."
                    },
                    "label": {
                      "type": "string",
                      "description": "The section, in words."
                    },
                    "fields": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string"
                          },
                          "label": {
                            "type": "string"
                          },
                          "type": {
                            "type": "string",
                            "enum": [
                              "text",
                              "textarea",
                              "number",
                              "money",
                              "boolean",
                              "time",
                              "select",
                              "multiselect",
                              "list",
                              "countries"
                            ]
                          },
                          "value": {
                            "description": "The raw value: a number, true or false, a string, or a list. Money is US dollars."
                          },
                          "display": {
                            "description": "The value in words, ready to show."
                          }
                        }
                      }
                    }
                  }
                },
                "description": "What this kind of product says about itself: a rental's deposit and driver age, an eSIM's countries and data, a pass's attractions, a venue, a route. Self-describing: show display, or read value."
              },
              "quoteOnly": {
                "type": "boolean",
                "description": "Priced on request: ask with POST /quote-requests instead of booking a date."
              },
              "updatedAt": {
                "type": "string",
                "format": "date-time"
              }
            },
            "description": "octo/content"
          }
        }
      },
      "Availability": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The availabilityId to book. A slot uuid for our own operators, a date (or date@time) for channel products. Treat it as opaque."
          },
          "localDateTimeStart": {
            "type": "string",
            "format": "date-time"
          },
          "localDateTimeEnd": {
            "type": "string",
            "format": "date-time"
          },
          "allDay": {
            "type": "boolean"
          },
          "available": {
            "type": "boolean",
            "description": "True when this time can take the party asked about. Also false when a boat, vehicle or guide it shares with another option is taken for that time, turnaround included."
          },
          "status": {
            "type": "string",
            "enum": [
              "AVAILABLE",
              "LIMITED",
              "FREESALE",
              "SOLD_OUT",
              "CLOSED"
            ]
          },
          "vacancies": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Seats left. Null means unlimited (FREESALE)."
          },
          "capacity": {
            "type": [
              "integer",
              "null"
            ]
          },
          "maxUnits": {
            "type": [
              "integer",
              "null"
            ]
          },
          "maxPaxCount": {
            "type": [
              "integer",
              "null"
            ]
          },
          "utcCutoffAt": {
            "type": "string",
            "format": "date-time"
          },
          "openingHours": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "statusMessage": {
            "type": [
              "string",
              "null"
            ]
          },
          "unitAvailability": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "unitId": {
                  "type": "string"
                },
                "vacancies": {
                  "type": "integer"
                }
              },
              "description": "What is left of a ticket type with a count of its own on this departure. With units in the request, available is false if any of them does not fit."
            }
          },
          "unitPricing": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "original": {
                  "type": "integer",
                  "description": "Same as retail."
                },
                "retail": {
                  "type": "integer",
                  "description": "What a traveller pays on our own site, the recommended selling price, in minor units."
                },
                "net": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "description": "What the caller pays, in minor units. Null for a key that is not buying (an operator reading the bookings of its own inventory)."
                },
                "currency": {
                  "type": "string",
                  "example": "USD"
                },
                "currencyPrecision": {
                  "type": "integer",
                  "example": 2
                },
                "includedTaxes": {
                  "type": "array",
                  "items": {
                    "type": "object"
                  }
                },
                "unitId": {
                  "type": "string"
                },
                "unitType": {
                  "type": "string"
                }
              },
              "description": "An OCTO Pricing object."
            }
          },
          "pricing": {
            "$ref": "#/components/schemas/Pricing"
          },
          "rental": {
            "type": "object",
            "properties": {
              "basis": {
                "type": "string"
              },
              "length": {
                "type": "integer"
              },
              "pickup": {
                "type": "string",
                "description": "Local, YYYY-MM-DDTHH:MM."
              },
              "return": {
                "type": "string",
                "description": "Local, YYYY-MM-DDTHH:MM."
              },
              "returnLocation": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "available": {
                "type": "boolean"
              },
              "reason": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "description": "Only when rental was sent: the whole period, judged and priced as one."
          },
          "pickupAvailable": {
            "type": "boolean"
          },
          "pickupRequired": {
            "type": "boolean"
          },
          "pickupPoints": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PickupPoint"
            }
          }
        }
      },
      "AvailabilityCalendar": {
        "type": "object",
        "properties": {
          "localDate": {
            "type": "string",
            "format": "date"
          },
          "available": {
            "type": "boolean"
          },
          "status": {
            "type": "string",
            "enum": [
              "AVAILABLE",
              "LIMITED",
              "FREESALE",
              "SOLD_OUT",
              "CLOSED"
            ]
          },
          "vacancies": {
            "type": [
              "integer",
              "null"
            ]
          },
          "capacity": {
            "type": [
              "integer",
              "null"
            ]
          },
          "maxUnits": {
            "type": [
              "integer",
              "null"
            ]
          },
          "maxPaxCount": {
            "type": [
              "integer",
              "null"
            ]
          },
          "utcCutoffAt": {
            "type": [
              "string",
              "null"
            ]
          },
          "statusMessage": {
            "type": [
              "string",
              "null"
            ]
          },
          "openingHours": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "availabilityLocalStartTimes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "unitPricingFrom": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "pricingFrom": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Pricing"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "Contact": {
        "type": "object",
        "properties": {
          "fullName": {
            "type": "string"
          },
          "firstName": {
            "type": "string"
          },
          "lastName": {
            "type": "string"
          },
          "emailAddress": {
            "type": "string",
            "format": "email"
          },
          "phoneNumber": {
            "type": "string"
          },
          "country": {
            "type": "string",
            "description": "ISO 3166-1 alpha-2."
          },
          "locales": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "BookingRequest": {
        "type": "object",
        "properties": {
          "productId": {
            "type": "string"
          },
          "optionId": {
            "type": "string"
          },
          "availabilityId": {
            "type": "string"
          },
          "unitItems": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "unitId": {
                  "type": "string"
                },
                "quantity": {
                  "type": "integer",
                  "description": "Defaults to 1. Send one item per traveller when they have their own details or answers."
                },
                "contact": {
                  "$ref": "#/components/schemas/Contact"
                },
                "questionAnswers": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/QuestionAnswer"
                  }
                }
              },
              "required": [
                "unitId"
              ]
            }
          },
          "contact": {
            "$ref": "#/components/schemas/Contact"
          },
          "questionAnswers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/QuestionAnswer"
            }
          },
          "pickupRequested": {
            "type": "boolean"
          },
          "pickupPointId": {
            "type": "string"
          },
          "pickupHotel": {
            "type": "string"
          },
          "pickupHotelRoom": {
            "type": "string"
          },
          "pickupAddress": {
            "type": "string"
          },
          "pickupNotes": {
            "type": "string"
          },
          "resellerReference": {
            "type": "string",
            "description": "Your own reference. Flows through to the voucher and your statement."
          },
          "notes": {
            "type": "string"
          },
          "expirationMinutes": {
            "type": "integer",
            "description": "How long to hold, 5 to 1440. Default 30."
          },
          "uuid": {
            "type": "string",
            "description": "A UUID you generate. A retry with the same value returns the first booking (200) instead of making another.",
            "format": "uuid"
          },
          "rental": {
            "$ref": "#/components/schemas/RentalRequest"
          }
        },
        "required": [
          "productId",
          "optionId",
          "availabilityId",
          "unitItems"
        ]
      },
      "Ticket": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "redemptionMethod": {
            "type": "string"
          },
          "utcRedeemedAt": {
            "type": [
              "string",
              "null"
            ]
          },
          "deliveryOptions": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "deliveryFormat": {
                  "type": "string",
                  "enum": [
                    "QRCODE",
                    "PDF_URL"
                  ]
                },
                "deliveryValue": {
                  "type": "string",
                  "description": "The QR payload, or a signed link to the PDF that works without a login."
                }
              }
            }
          }
        }
      },
      "Booking": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "uuid": {
            "type": "string"
          },
          "testMode": {
            "type": "boolean"
          },
          "resellerReference": {
            "type": [
              "string",
              "null"
            ]
          },
          "supplierReference": {
            "type": "string",
            "description": "Our booking reference, printed on the voucher."
          },
          "status": {
            "type": "string",
            "enum": [
              "ON_HOLD",
              "CONFIRMED",
              "CANCELLED",
              "EXPIRED",
              "REDEEMED",
              "PENDING",
              "REJECTED",
              "NO_SHOW"
            ]
          },
          "utcCreatedAt": {
            "type": "string"
          },
          "utcUpdatedAt": {
            "type": "string"
          },
          "utcExpiresAt": {
            "type": [
              "string",
              "null"
            ]
          },
          "utcRedeemedAt": {
            "type": [
              "string",
              "null"
            ]
          },
          "utcConfirmedAt": {
            "type": [
              "string",
              "null"
            ]
          },
          "productId": {
            "type": "string"
          },
          "optionId": {
            "type": "string"
          },
          "cancellable": {
            "type": "boolean"
          },
          "confirmable": {
            "type": "boolean"
          },
          "freesale": {
            "type": "boolean"
          },
          "availabilityId": {
            "type": "string"
          },
          "availability": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "localDateTimeStart": {
                "type": "string"
              },
              "localDateTimeEnd": {
                "type": "string"
              },
              "allDay": {
                "type": "boolean"
              },
              "openingHours": {
                "type": "array",
                "items": {
                  "type": "object"
                }
              }
            }
          },
          "contact": {
            "$ref": "#/components/schemas/Contact"
          },
          "notes": {
            "type": [
              "string",
              "null"
            ]
          },
          "deliveryMethods": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "rental": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/RentalPeriod"
              },
              {
                "type": "null"
              }
            ]
          },
          "voucher": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Ticket"
              },
              {
                "type": "null"
              }
            ]
          },
          "unitItems": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "uuid": {
                  "type": "string"
                },
                "id": {
                  "type": "string"
                },
                "resellerReference": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "supplierReference": {
                  "type": "string"
                },
                "unitId": {
                  "type": "string"
                },
                "unitType": {
                  "type": "string"
                },
                "status": {
                  "type": "string"
                },
                "utcRedeemedAt": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "contact": {
                  "$ref": "#/components/schemas/Contact"
                },
                "ticket": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/Ticket"
                    },
                    {
                      "type": "null"
                    }
                  ]
                },
                "questionAnswers": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "questionId": {
                        "type": "string"
                      },
                      "label": {
                        "type": "string"
                      },
                      "value": {
                        "type": "string"
                      }
                    }
                  }
                },
                "pricing": {
                  "$ref": "#/components/schemas/Pricing"
                }
              }
            }
          },
          "questionAnswers": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "questionId": {
                  "type": "string"
                },
                "label": {
                  "type": "string"
                },
                "value": {
                  "type": "string"
                }
              }
            }
          },
          "cancellation": {
            "type": "object",
            "properties": {
              "refund": {
                "type": "string",
                "enum": [
                  "FULL",
                  "PARTIAL",
                  "NONE"
                ]
              },
              "reason": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "utcCancelledAt": {
                "type": "string"
              },
              "refundAmount": {
                "$ref": "#/components/schemas/Pricing"
              }
            }
          },
          "pricing": {
            "$ref": "#/components/schemas/Pricing"
          },
          "pickupRequested": {
            "type": "boolean"
          },
          "pickupPointId": {
            "type": [
              "string",
              "null"
            ]
          },
          "pickupHotel": {
            "type": [
              "string",
              "null"
            ]
          },
          "pickupHotelRoom": {
            "type": [
              "string",
              "null"
            ]
          },
          "pickupAddress": {
            "type": [
              "string",
              "null"
            ]
          },
          "pickupTime": {
            "type": [
              "string",
              "null"
            ]
          },
          "pickupNotes": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "Webhook": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "event": {
            "type": "string"
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "status": {
            "type": "string"
          },
          "failureCount": {
            "type": "integer"
          },
          "lastSuccessAt": {
            "type": [
              "string",
              "null"
            ]
          },
          "lastFailureAt": {
            "type": [
              "string",
              "null"
            ]
          },
          "createdAt": {
            "type": "string"
          },
          "secret": {
            "type": "string",
            "description": "Returned once, when created. Every delivery is signed with it: Octo-Signature is the hex HMAC-SHA256 of the raw body."
          }
        }
      },
      "RentalTerms": {
        "type": "object",
        "properties": {
          "basis": {
            "type": "string",
            "description": "How the length is counted.",
            "enum": [
              "day",
              "night",
              "hour"
            ]
          },
          "minLength": {
            "type": "integer"
          },
          "maxLength": {
            "type": [
              "integer",
              "null"
            ]
          },
          "pricedPer": {
            "type": "string",
            "description": "day, night or hour when each is charged; period when one rate, chosen by length, covers the whole booking."
          },
          "oneWay": {
            "type": "boolean",
            "description": "Can be returned somewhere else, with returnLocation."
          },
          "oneWayFee": {
            "type": [
              "integer",
              "null"
            ],
            "description": "USD minor units."
          },
          "deposit": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Held at pickup, not charged. USD minor units."
          }
        },
        "description": "Present on options booked from one date to another. See Rentals and stays."
      },
      "RentalRequest": {
        "type": "object",
        "properties": {
          "returnDate": {
            "type": "string",
            "format": "date"
          },
          "pickupTime": {
            "type": "string",
            "description": "HH:MM. Defaults to the departure time."
          },
          "returnTime": {
            "type": "string",
            "description": "HH:MM. Defaults to the pickup time."
          },
          "returnLocation": {
            "type": "string",
            "description": "Only where the option allows one way returns."
          }
        },
        "description": "The period of a rental or a stay. Without it, the shortest booking the option allows."
      },
      "RentalPeriod": {
        "type": "object",
        "properties": {
          "basis": {
            "type": "string"
          },
          "length": {
            "type": "integer"
          },
          "pickup": {
            "type": "string",
            "description": "Local, YYYY-MM-DDTHH:MM."
          },
          "return": {
            "type": "string",
            "description": "Local, YYYY-MM-DDTHH:MM."
          },
          "returnLocation": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "QuoteRequestBody": {
        "type": "object",
        "properties": {
          "productId": {
            "type": "string"
          },
          "groupSize": {
            "type": "integer"
          },
          "travelDate": {
            "type": "string",
            "format": "date"
          },
          "endDate": {
            "type": "string",
            "format": "date"
          },
          "datesFlexible": {
            "type": "boolean"
          },
          "budget": {
            "type": "number",
            "description": "For the whole group, USD."
          },
          "message": {
            "type": "string",
            "description": "What your client wants."
          },
          "answers": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "question": {
                  "type": "string"
                },
                "answer": {
                  "type": "string"
                }
              },
              "description": "Answers to the operator's quote settings (their ask list)."
            }
          },
          "option": {
            "type": "string",
            "description": "An option uuid, when the product has several."
          },
          "contact": {
            "type": "object",
            "properties": {
              "firstName": {
                "type": "string"
              },
              "lastName": {
                "type": "string"
              },
              "emailAddress": {
                "type": "string"
              },
              "phoneNumber": {
                "type": "string"
              },
              "country": {
                "type": "string"
              }
            },
            "required": [
              "firstName",
              "lastName",
              "emailAddress"
            ]
          },
          "resellerReference": {
            "type": "string"
          }
        },
        "required": [
          "productId",
          "groupSize",
          "contact"
        ]
      },
      "QuoteRequest": {
        "type": "object",
        "properties": {
          "uuid": {
            "type": "string"
          },
          "reference": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "open",
              "quoted",
              "accepted",
              "declined",
              "withdrawn",
              "expired"
            ]
          },
          "product": {
            "type": "object",
            "properties": {
              "uuid": {
                "type": "string"
              },
              "slug": {
                "type": "string"
              },
              "title": {
                "type": "string"
              }
            }
          },
          "option": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "uuid": {
                "type": "string"
              },
              "title": {
                "type": "string"
              }
            }
          },
          "travelDate": {
            "type": "string",
            "format": "date"
          },
          "endDate": {
            "type": "string",
            "format": "date"
          },
          "datesFlexible": {
            "type": "boolean"
          },
          "groupSize": {
            "type": "integer"
          },
          "budget": {
            "type": "integer",
            "description": "USD minor units."
          },
          "message": {
            "type": "string"
          },
          "answers": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "question": {
                  "type": "string"
                },
                "answer": {
                  "type": "string"
                }
              }
            }
          },
          "contact": {
            "type": "object"
          },
          "resellerReference": {
            "type": "string"
          },
          "price": {
            "$ref": "#/components/schemas/QuotePrice"
          },
          "quoteMessage": {
            "type": "string",
            "description": "The operator's note: what the price includes."
          },
          "quotedAt": {
            "type": "string",
            "format": "date-time"
          },
          "validUntil": {
            "type": "string",
            "format": "date-time"
          },
          "declineReason": {
            "type": "string"
          },
          "bookingId": {
            "type": "string",
            "description": "The booking, once accepted."
          },
          "bookable": {
            "type": "boolean"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "QuotePrice": {
        "type": "object",
        "properties": {
          "total": {
            "type": "integer",
            "description": "What you pay for the whole group, USD minor units."
          },
          "recommendedRetail": {
            "type": "integer",
            "description": "What a traveller would pay."
          },
          "currency": {
            "type": "string"
          }
        }
      }
    }
  }
}
