# Pickups

To use this capability, add `octo/pickups` to your `Octo-Capabilities` header.

This capability adds pickup/dropoff configuration to options, timed pickup/dropoff choices to availability responses, and pickup/dropoff selection fields on booking write/booking response objects.

## Routes

Product option fields are returned on:

* `GET /products`
* `GET /products/{productId}`

Availability fields are returned on:

* `POST /availability`
* `POST /availability/batch`

Booking write fields are accepted on:

* `POST /bookings`
* `PATCH /bookings/{uuid}`

## Behaviour

* If both `pickupPointId` and `pickupHotel` are sent, `pickupPointId` takes precedence.
* If both `dropoffPointId` and `dropoffHotel` are sent, `dropoffPointId` takes precedence.
* When `pickupHotel` is provided and no pickup point matches by name, the API geocodes/creates a hotel record and links it to the booking.
* When `dropoffHotel` is provided and no dropoff point matches by name, the API geocodes/creates a hotel record and links it to the booking.
* `pickupAddress` and `dropoffAddress` can be sent to improve hotel geocoding accuracy.
* Send `null` to clear existing values for pickup/dropoff booking fields.
* For custom dropoff products, availability-level `dropoffPoints` require an end time; for stop-based dropoff products, dropoffs are resolved by stop/date.

## Schema Additions (JSON)

These are additive fragments showing only fields introduced by this capability.

### `Option`

```json
{
  "// ...rest of option object": "...",
  "pickupAvailable": true,
  "pickupRequired": true,
  "pickupPoints": [
    {
      "id": "1cfe2c68-4a91-4df8-8d69-4b393d469caf",
      "name": "Union Square Pickup",
      "directions": "Meet outside the main entrance beside the red awning.",
      "address": "333 O'Farrell St, San Francisco, CA 94102",
      "latitude": 37.785452,
      "longitude": -122.408058,
      "googlePlaceId": "ChIJN1t_tDeuEmsRUsoyG83frY4",
      "street": "333 O'Farrell St",
      "postalCode": "94102",
      "locality": "San Francisco",
      "region": "California",
      "state": "CA",
      "country": "US",
      "localDateTime": null,
      "localDateTimeTo": null
    }
  ],
  "dropoffAvailable": true,
  "dropoffRequired": true,
  "dropoffPoints": [
    {
      "id": "8d7a2fd8-f8f8-4e61-bbaf-5adac58f5d46",
      "name": "Fisherman's Wharf Dropoff",
      "directions": "Dropoff opposite Pier 39 bus bay.",
      "address": "2500 Mason St, San Francisco, CA 94133",
      "latitude": 37.808673,
      "longitude": -122.409821,
      "googlePlaceId": "ChIJd8BlQ2B-j4ARk4A6A8sM5d0",
      "street": "2500 Mason St",
      "postalCode": "94133",
      "locality": "San Francisco",
      "region": "California",
      "state": "CA",
      "country": "US",
      "localDateTime": null,
      "localDateTimeTo": null
    }
  ]
}
```

### `Availability`

```json
{
  "// ...rest of availability object": "...",
  "pickupAvailable": true,
  "pickupRequired": true,
  "pickupPoints": [
    {
      "id": "1cfe2c68-4a91-4df8-8d69-4b393d469caf",
      "name": "Union Square Pickup",
      "localDateTime": "2026-05-14T08:30:00-07:00",
      "localDateTimeTo": "2026-05-14T08:45:00-07:00"
    }
  ],
  "dropoffAvailable": true,
  "dropoffRequired": true,
  "dropoffPoints": [
    {
      "id": "8d7a2fd8-f8f8-4e61-bbaf-5adac58f5d46",
      "name": "Fisherman's Wharf Dropoff",
      "localDateTime": "2026-05-14T13:30:00-07:00",
      "localDateTimeTo": null
    }
  ]
}
```

### `AvailabilityBatchRow`

```json
{
  "// ...rest of availability batch row object": "...",
  "pickupAvailable": true,
  "pickupRequired": true,
  "pickupPoints": [
    {
      "id": "1cfe2c68-4a91-4df8-8d69-4b393d469caf",
      "name": "Union Square Pickup",
      "localDateTime": "2026-05-14T08:30:00-07:00",
      "localDateTimeTo": "2026-05-14T08:45:00-07:00"
    }
  ],
  "dropoffAvailable": true,
  "dropoffRequired": true,
  "dropoffPoints": [
    {
      "id": "8d7a2fd8-f8f8-4e61-bbaf-5adac58f5d46",
      "name": "Fisherman's Wharf Dropoff",
      "localDateTime": "2026-05-14T13:30:00-07:00",
      "localDateTimeTo": null
    }
  ]
}
```

### `PackageAvailability`

```json
{
  "// ...rest of package availability object": "...",
  "pickupAvailable": true,
  "pickupRequired": true,
  "pickupPoints": [
    {
      "id": "1cfe2c68-4a91-4df8-8d69-4b393d469caf",
      "name": "Union Square Pickup",
      "localDateTime": "2026-05-14T08:30:00-07:00",
      "localDateTimeTo": "2026-05-14T08:45:00-07:00"
    }
  ],
  "dropoffAvailable": true,
  "dropoffRequired": true,
  "dropoffPoints": [
    {
      "id": "8d7a2fd8-f8f8-4e61-bbaf-5adac58f5d46",
      "name": "Fisherman's Wharf Dropoff",
      "localDateTime": "2026-05-14T13:30:00-07:00",
      "localDateTimeTo": null
    }
  ]
}
```

### `AvailabilityResourcesRequest`

```json
{
  "// ...rest of availability resources request object": "...",
  "pickupPointId": "1cfe2c68-4a91-4df8-8d69-4b393d469caf",
  "dropoffPointId": "8d7a2fd8-f8f8-4e61-bbaf-5adac58f5d46"
}
```

### `BookingWriteRequest`

```json
{
  "// ...rest of booking write request object": "...",
  "pickupRequested": true,
  "pickupPointId": "1cfe2c68-4a91-4df8-8d69-4b393d469caf",
  "pickupHotel": "Hilton Union Square",
  "pickupAddress": "333 O'Farrell St, San Francisco, CA 94102",
  "pickupHotelRoom": "1208",
  "pickupNotes": "Meet the guide by the hotel lobby.",
  "dropoffRequested": true,
  "dropoffPointId": "8d7a2fd8-f8f8-4e61-bbaf-5adac58f5d46",
  "dropoffHotel": "Hotel Riu Plaza Fisherman's Wharf",
  "dropoffAddress": "2500 Mason St, San Francisco, CA 94133",
  "dropoffNotes": "Drop-off at Fisherman's Wharf."
}
```

### `Booking`

```json
{
  "// ...rest of booking object": "...",
  "pickupRequested": true,
  "pickupPointId": "1cfe2c68-4a91-4df8-8d69-4b393d469caf",
  "pickupHotel": "Hilton Union Square, 333 O'Farrell St, San Francisco, CA 94102",
  "pickupHotelRoom": "1208",
  "pickupNotes": "Meet the guide by the hotel lobby.",
  "pickupPoint": {
    "id": "1cfe2c68-4a91-4df8-8d69-4b393d469caf",
    "name": "Union Square Pickup",
    "localDateTime": "2026-05-14T08:30:00-07:00",
    "localDateTimeTo": "2026-05-14T08:45:00-07:00"
  },
  "pickupDispatch": {
    "id": "3d6f0a3a-59d4-4b16-a0c5-11d2d8a4e6b7",
    "vehicle": "coach_12",
    "driver": "Alex Johnson",
    "guide": "Maria Santos",
    "area": "Downtown Loop",
    "notes": "Vehicle departs from Bay 4."
  },
  "dropoffRequested": true,
  "dropoffPointId": "8d7a2fd8-f8f8-4e61-bbaf-5adac58f5d46",
  "dropoffHotel": "Hotel Riu Plaza Fisherman's Wharf, 2500 Mason St, San Francisco, CA 94133",
  "dropoffNotes": "Drop-off at Fisherman's Wharf.",
  "dropoffPoint": {
    "id": "8d7a2fd8-f8f8-4e61-bbaf-5adac58f5d46",
    "name": "Fisherman's Wharf Dropoff",
    "localDateTime": "2026-05-14T13:30:00-07:00",
    "localDateTimeTo": "2026-05-14T13:45:00-07:00"
  },
  "dropoffDispatch": {
    "id": "3d6f0a3a-59d4-4b16-a0c5-11d2d8a4e6b7",
    "vehicle": "coach_12",
    "driver": "Alex Johnson",
    "guide": "Maria Santos",
    "area": "Downtown Loop",
    "notes": "Vehicle departs from Bay 4."
  }
}
```
