# Pickups \[NEW]

### Business Context

Pickup service is commonly offered for tours and activities. It allows customers to be collected from one of the designated locations, or even from a customer-defined point within a supported pickup area, instead of the main meeting point.

This service may be included for free or offered at an additional cost.

The OCTO Pickups Capability allows:

* **Supplier systems** to indicate whether a product option supports pickup, whether pickup is required, and to provide structured pickup locations and areas.
* **Reseller systems** to obtain pickup data, display available choices to customers during the booking flow, pass the customer’s selected pickup location when creating, confirming, or updating a booking, and leverage a capability-specific endpoint to validate pickup availability based on a customer-defined point (e.g., latitude/longitude).

\
Identical functionality is also available for dropoffs through the [Dropoffs Capability,](https://docs.octo.travel/capabilities-optional/dropoffs-new) which mirrors pickups and provides structured or customer-defined end-of-tour return options.

### Capability Summary

To enable this capability when supported by a supplier system’s OCTO API, the reseller system must include `pickups` in the `Octo-Capabilities` header of its requests to the supplier system.

Adding `pickups` to your `Octo-Capabilities` header will alter OCTO Core endpoint behavior as follows:

<table data-full-width="true"><thead><tr><th width="254.8671875" data-type="content-ref">Endpoint</th><th>Pickups Capability Enhancements to OCTO Core</th></tr></thead><tbody><tr><td><a href="../../octo-api-core/supplier#get-supplier">#get-supplier</a></td><td><em>No additional functionality.</em></td></tr><tr><td><a href="../../octo-api-core/products#get-product-list">#get-product-list</a></td><td><a href="#get-product-list-and-get-product-with-pickups">Response</a> payload includes, per product option, whether pickup is available, required for booking, and a list of supported locations/areas with their details. </td></tr><tr><td><a href="../../octo-api-core/products#get-product">#get-product</a></td><td><a href="#get-product-list-and-get-product-with-pickups">Response</a> payload includes, per product option, whether pickup is available, required for booking, and a list of supported locations/areas with their details. </td></tr><tr><td><a href="../../octo-api-core/availability#availability-calendar">#availability-calendar</a></td><td><a href="#post-availability-calendar-with-pickups">Request</a> can specify if the customer wants pickup and the chosen location. <a href="#post-availability-calendar-with-pickups">Response</a> includes, per calendar day, whether pickup is available, required, and the list of supported locations/areas with details. </td></tr><tr><td><a href="../../octo-api-core/availability#availability-check">#availability-check</a></td><td><a href="#post-availability-check-with-pickups">Request</a> can specify if the customer wants pickup and the chosen location. <a href="#post-availability-check-with-pickups">Response</a> includes, per availability, whether pickup is available, required, the list of supported locations/areas with details, including pickup time window.</td></tr><tr><td><a href="../../octo-api-core/bookings#create-booking">#create-booking</a></td><td><a href="#post-create-booking-patch-update-booking-with-pickups">Request</a> can specify if the customer wants pickup, the chosen location, as well as any pickup notes for booking. <a href="#post-create-booking-patch-update-booking-with-pickups">Response</a> includes if the pickup is requested for the booking, the selected pickup location with details, including the pickup time window. </td></tr><tr><td><a href="../../octo-api-core/bookings#extend-pending-booking-expiration">#extend-pending-booking-expiration</a></td><td><a href="#post-create-booking-patch-update-booking-with-pickups">Response</a> includes if the pickup is requested for the booking, the selected pickup location with details, including the pickup time window. </td></tr><tr><td><a href="../../octo-api-core/bookings#confirm-booking">#confirm-booking</a></td><td><a href="#post-create-booking-patch-update-booking-with-pickups">Response</a> includes if the pickup is requested for the booking, the selected pickup location with details, including the pickup time window. </td></tr><tr><td><a href="../../octo-api-core/bookings#cancel-booking">#cancel-booking</a></td><td><a href="#post-create-booking-patch-update-booking-with-pickups">Response</a> includes if the pickup is requested for the booking, the selected pickup location with details, including the pickup time window. </td></tr><tr><td><a href="../../octo-api-core/bookings#update-booking">#update-booking</a></td><td><a href="#post-create-booking-patch-update-booking-with-pickups">Request</a> can specify if the customer wants pickup, the chosen location, as well as any pickup notes for booking. <a href="../../octo-api-core/bookings#update-booking">Response</a> includes if the pickup is requested for the booking, the selected pickup location with details, including the pickup time window. </td></tr><tr><td><a href="../../octo-api-core/bookings#get-booking-list">#get-booking-list</a></td><td><a href="#post-create-booking-patch-update-booking-with-pickups">Response</a> includes if the pickup is requested for the booking, the selected pickup location with details, including the pickup time window. </td></tr><tr><td><a href="../../octo-api-core/bookings#get-booking">#get-booking</a></td><td><a href="#post-create-booking-patch-update-booking-with-pickups">Response</a> includes if the pickup is requested for the booking, the selected pickup location with details, including the pickup time window. </td></tr></tbody></table>

\
**GET Booking Pickup Locations Endpoint**

Additionally, this capability provides a dedicated endpoint [GET Booking Pickup Locations](#get-booking-pickup-locations), which enables searching for pickup locations based on a customer-defined latitude and longitude, and validates whether pickup service is available at that exact location or recommends alternate pickup locations.&#x20;

### Additional OCTO Core Parameters & Schemas

#### [**GET Product List**](https://docs.octo.travel/octo-api-core/products#get-product-list) **AND** [**GET Product**](https://docs.octo.travel/octo-api-core/products#get-product) **(with `pickups`)**

**Request Body:**

```json
{
// ...rest of the OPTION object
  "pickupAvailable": true,
  "pickupRequired": false,
  "pickupLocations": [
    {
      "id": "e7c0f5a6-3b3a-4c8f-9a1d-2f4a7a9b1c23",
      "title": "Hotel Avenida Palace",
      "shortDescription": "Pickup available directly from Hotel Avenida Palace, located in the heart of Lisbon near Rossio Square. Guests should wait at the main lobby entrance.",
      "place": {
        "latitude": 38.7123,
        "longitude": -9.1334,
        "postalAddress": {
          "streetAddress": "Rua 1",
          "addressLocality": "Lisboa",
          "addressRegion": "Lisboa",
          "postalCode": "1000-000",
          "addressCountry": "PT",
          "postOfficeBoxNumber": null
        },
        "identifiers": [
          { "googlePlaceId": "ChIJd7zN_th2GQ0Rj..." },
          { "tripadvisorLocationId": "123456" }
        ],
        "sameAs": [
          "https://maps.google.com/?cid=..."
        ]
      },
     },
    {
      "id": "9f1b0a77-6d52-4f0a-9b7c-3d1a2b5c6e88",
      "title": "Praça do Comércio",
      "shortDescription": "Pickup available from Lisbon’s iconic Praça do Comércio, a large public square facing the Tagus River. Meeting point is next to the central equestrian statue.",
      "place": {
        "latitude": 38.7079,
        "longitude": -9.1366,
        "postalAddress": {
          "streetAddress": "Praça do Comércio",
          "addressLocality": "Lisboa",
          "addressRegion": "Lisboa",
          "postalCode": "1100-148",
          "addressCountry": "PT",
          "postOfficeBoxNumber": null
        },
        "identifiers": [
          { "googlePlaceId": "ChIJW0..." }
        ],
        "sameAs": [
          "https://maps.google.com/?cid=..."
        ]
      },
    }
  ],
  # Optional, just intended as a visual aid
  "pickupAreas": [
    {
      "title": "Downtown Zone",
      "shortDescription": "Pickup available across the downtown Lisbon area, covering hotels, landmarks, and popular meeting points such as Rossio, Baixa, and Cais do Sodré. Guests can be collected from designated stops within this zone.",
      "area": {
        "coordinates": [
          { "latitude": 38.7139, "longitude": -9.1437 },
          { "latitude": 38.7132, "longitude": -9.1379 },
          { "latitude": 38.7098, "longitude": -9.1375 },
          { "latitude": 38.7139, "longitude": -9.1437 } # end up where you start
        ],
        "identifiers": [
          { "googlePlaceId": "ChIJd7zN_th2GQ0Rj..." },
          { "tripadvisorLocationId": "123456" }
        ],
        "sameAs": [
          "https://maps.google.com/?cid=...",
          "https://www.tripadvisor.com/Attraction_Review-..."
        ]
      },
    }
  ]
}
```

#### [**POST Availability Calendar**](https://docs.octo.travel/octo-api-core/availability#availability-calendar) **(with `pickups`)** &#x20;

**Request Body:**

```json
{
  // ... rest of the OCTO Core availability request body
  "pickupRequested": true,
  "pickupLocationId": "9f1a3c1e-6b28-4e2a-9c7e-32d5a3a1f45e"
}
```

<table data-full-width="true"><thead><tr><th width="184.6015625">Field</th><th width="125.7734375">Type</th><th width="141.08203125">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>pickupRequested</code></td><td>boolean</td><td>optional</td><td>Whether the customer requested pickup. </td></tr><tr><td><code>pickupLocationId</code></td><td>string</td><td>optional</td><td>The pickup location ID selected by the customer (must match one of <code>pickupLocations[].id)</code>.</td></tr></tbody></table>

**Response Body:**&#x20;

```json
{
  // ...rest of the CALENDAR DAY object
  "pickupAvailable": true,
  "pickupRequired": false
}
```

<table data-full-width="true"><thead><tr><th width="184.6015625">Field</th><th width="125.7734375">Type</th><th width="141.08203125">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>pickupAvailable</code></td><td>boolean</td><td>required</td><td>Indicates whether pickup service is offered for this date.</td></tr><tr><td><code>pickupRequired</code></td><td>boolean</td><td>required</td><td>Indicates whether selecting a pickup location is mandatory for booking.</td></tr></tbody></table>

#### [**POST Availability Check**](https://docs.octo.travel/octo-api-core/availability#post-availability) **(with `pickups`)** &#x20;

**Request Body:**

```json
{
// ... rest of the OCTO Core availability request body
  "pickupRequested": true,
  "pickupLocationId": null (optional, if pickupLocation is requested up-front)
}

```

<table data-full-width="true"><thead><tr><th width="184.6015625">Field</th><th width="125.7734375">Type</th><th width="141.08203125">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>pickupRequested</code></td><td>boolean</td><td>optional</td><td>Whether the customer requested pickup. </td></tr><tr><td><code>pickupLocationId</code></td><td>string</td><td>optional</td><td>The pickup location ID selected by the customer (must match one of <code>pickupLocations[].id)</code>.</td></tr></tbody></table>

**Response Body:**&#x20;

```json
{
// ...rest of the AVAILABILITY object
  // ...note addition of localDateTimeStart and localDateTimeEnd below 
  "pickupAvailable": true,
  "pickupRequired": false,
  "localPickupDateTimeStart": null, (only set if pickupLocationId is set)
  "localPickupDateTimeEnd": null, (only set if pickupLocationId is set)
}

```

<table data-full-width="true"><thead><tr><th>Field</th><th width="242.22265625">Type</th><th width="118.24609375">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>localPickupDateTimeStart</code></td><td>string (<a href="https://www.iso.org/iso-8601-date-and-time-format.html">ISO 8601</a>, i.e. YYYY-MM-DD)</td><td>optional</td><td>Start of the pickup time window in the local time zone of the pickup location. Indicates the earliest time the customer can be collected. </td></tr><tr><td><code>localPickupDateTimeEnd</code></td><td>string (<a href="https://www.iso.org/iso-8601-date-and-time-format.html">ISO 8601</a>, i.e. YYYY-MM-DD)</td><td>optional</td><td>End of the pickup time window in the local time zone of the pickup location. Indicates the latest time the customer can be collected.</td></tr></tbody></table>

#### [**POST Create Booking**](https://docs.octo.travel/octo-api-core/bookings#create-booking) **/** [**PATCH Update Booking**](https://docs.octo.travel/octo-api-core/bookings#update-booking) **(with `pickups`)**&#x20;

**Request Body:**

```json
{
// ... rest of the OCTO Core CREATE BOOKING request body
  "pickupRequested": true,
  "pickupLocationId": "9f1a3c1e-6b28-4e2a-9c7e-32d5a3a1f45e"
  "pickupNotes": "Blue door next to the bakery"
}
```

<table data-full-width="true"><thead><tr><th>Field</th><th width="158.88671875">Type</th><th width="126.9609375">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>pickupRequested</code></td><td>boolean</td><td>optional</td><td>Whether the customer requested pickup. </td></tr><tr><td><code>pickupLocationId</code></td><td>string</td><td>optional</td><td>The pickup location ID selected by the customer (must match one of pickupLocations[].id).</td></tr><tr><td><code>pickupNotes</code></td><td>string</td><td>optional</td><td>Free-text notes provided by the customer for pickup (e.g., Airbnb directions, gate code, nearby landmark, hotel room, etc).</td></tr></tbody></table>

**Response Body:**

```json
 // ...rest of the BOOKING object
  "pickupRequested": true,
  "pickupLocationId": "e7c0f5a6-3b3a-4c8f-9a1d-2f4a7a9b1c23",
  "pickupNotes": "Blue door next to the bakery",
  "localPickupDateTimeStart": "2025-12-01T05:40:00-08:00",
  "localPickupDateTimeEnd": "2025-12-01T05:55:00-08:00",
  "pickupLocation": {
    "id": "e7c0f5a6-3b3a-4c8f-9a1d-2f4a7a9b1c23",
    "title": "Hotel Avenida Palace",
    "shortDescription": "Pickup available directly from Hotel Avenida Palace, located in the heart of Lisbon near Rossio Square. Guests should wait at the main lobby entrance.",
    "place": {
      "latitude": 38.7123,
      "longitude": -9.1334,
      "postalAddress": {
        "streetAddress": "Rua 1",
        "addressLocality": "Lisboa",
        "addressRegion": "Lisboa",
        "postalCode": "1000-000",
        "addressCountry": "PT",
        "postOfficeBoxNumber": null
      },
      "identifiers": [
        { "googlePlaceId": "ChIJd7zN_th2GQ0Rj..." },
        { "tripadvisorLocationId": "123456" }
      ],
      "sameAs": [
        "https://maps.google.com/?cid=..."
      ]
    }
  }
}
```

### GET Booking Pickup Locations

`GET` {host}/bookings/{uuid}/pickupLocations?latitude={lat}\&longitude={lng}

**Query Parameters:**&#x20;

<table data-full-width="true"><thead><tr><th>Name</th><th>Type</th><th width="185.03515625">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>latitude</code></td><td>number</td><td>required</td><td>Customer-defined latitude (WGS84).</td></tr><tr><td><code>longitude</code></td><td>number</td><td>required</td><td>Customer-defined longitude (WGS84).</td></tr></tbody></table>

When latitude and longitude are not provided, the supplier system should return the full list of pickup locations.

When latitude and longitude *are* provided, the supplier system may choose to either:

* return the full list of pickup locations in any order,
* return the full list ordered in a way that reflects the lat/lon query,
* return only a subset of locations that best match the passenger’s position, or
* generate a new, virtual pickup location on the fly that corresponds to the provided coordinates and can be used for booking creation or updates.

Reseller systems must be prepared for scenarios where a pickup location ID returned during availability or booking does not appear in the static list retrieved via the general `pickupLocations` query for that product option.

**Response Body:**

```json
{
    "localPickupDateTimeStart": "2025-12-01T05:40:00-08:00",
    "localPickupDateTimeEnd": "2025-12-01T05:55:00-08:00",
    "pickupLocation": {
      "id": "9f1a3c1e-6b28-4e2a-9c7e-32d5a3a1f45e",
      "title": "Americania Hotel - 121 7th St",
      "shortDescription": "Meet next to the parking lot entrance.",
      "place": {
        "latitude": 37.7788005,
        "longitude": -122.4102065,
        "postalAddress": {
          "streetAddress": "121 7th Street",
          "addressLocality": "San Francisco",
          "addressRegion": "California",
          "postalCode": "94103",
          "addressCountry": "US"
        },
        "identifiers": [
          { "googlePlaceId": "ChIJOTbxc4OAhYARrK82JwxWZFY" }
        ],
        "sameAs": [
          "https://www.americaniahotel.com",
          "https://maps.google.com/?q=121+7th+St+San+Francisco"
        ]
      }
    }
  },
  {
    "localPickupDateTimeStart": "2025-12-01T06:10:00-08:00",
    "localPickupDateTimeEnd": "2025-12-01T06:25:00-08:00",
    "pickupLocation": {
      "id": "d41e236b-3927-48ad-9c68-66c3a4789a2f",
      "title": "Union Square - 333 Post St",
      "shortDescription": "Pickup near the central monument.",
      "place": {
        "latitude": 37.788056,
        "longitude": -122.4075,
        "postalAddress": {
          "streetAddress": "333 Post Street",
          "addressLocality": "San Francisco",
          "addressRegion": "California",
          "postalCode": "94108",
          "addressCountry": "US"
        }
      }
    },
  }
]
```
