# Introduction

For resellers looking to sell products on the Peek OCTO API platform

This documentation details Peek Pro's implementation of the [OCTO API](https://www.octo.travel/) spec, which is an open API standard initiative for the experiences industry. We have implemented the core specification along with a few optional capabilities:

* [Pricing](https://octodocs.peek.com/capabilities-1/pricing)
* [Webhooks](https://octodocs.peek.com/capabilities-1/webhooks)

### Glossary Of Terms

<table><thead><tr><th width="177">Name</th><th>Description</th></tr></thead><tbody><tr><td>Reseller</td><td>You are the reseller, connecting via the API</td></tr><tr><td>Supplier</td><td>The Peek Pro partner you are connecting to</td></tr><tr><td>Product</td><td>The activity or rental</td></tr><tr><td>Option</td><td>Additional information on the activity or rental (for now, only one option exists per product)</td></tr><tr><td>Unit</td><td>A bookable item associated with the product option (different rental options, or a single activity)</td></tr><tr><td>Unit Item</td><td>A line item per unit within the booking</td></tr><tr><td>Voucher</td><td>A single QR code that can be used for the whole booking</td></tr></tbody></table>


# Basics

What you need to do to do your first request

### Authentication <a href="#authentication" id="authentication"></a>

First, you must obtain your OCTO API Key. See [Request Access](/getting-started/request-access) for details.

OCTP uses Bearer authentication which you can use to authenticate:

```
GET integrations/octo/products HTTP/1.1
Host: octo.peek.com
Authorization: Bearer 5bd1629a-323e-4edb-ac9b-327ef51e6136
```

{% hint style="info" %}
All communication must be sent over HTTPS
{% endhint %}

If the token is invalid or is deactivated a HTTP 403 Forbidden error will be returned.

### JSON Content Type

Every `POST`, `PATCH` and `DELETE` request must use `Content-Type: application/json` header and the request body must be a JSON encoded string. Every endpoint will return JSON unless otherwise stated.


# Request Access

How to request access to Peek's OCTO API

To request access, please send an email to <ben.smithart@peek.com>. Peek Pro's Product team will reach out to you shortly.


# Headers

Pass these in your API calls

## Request Headers <a href="#request-headers" id="request-headers"></a>

| Header         | Description                                                                   |
| -------------- | ----------------------------------------------------------------------------- |
| `Content-Type` | This must be `application/json` for all `POST` `PATCH` and `DELETE` requests. |

## Response Headers <a href="#response-headers" id="response-headers"></a>

| Header              | Description                                                                                                                                      |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| `Octo-Capabilities` | <p>A list of the capabilities that were initialised with this request.</p><p>e.g. <code>Octo-Capabilities: octo/pricing, octo/content</code></p> |
| `Octo-Env`          | This will return `test` if the request is in test, or `live` if it wasn't.                                                                       |


# Capabilities

How to use core extensions

Peek Pro currently supports the following capabilities:

* `Pricing`
* `Webhooks`

They are enabled by passing them into the request header, as mentioned in the previous Headers section. Capabilities are optional but may provide functionality to improve your integration.

| Name                                                          | ID              | Description                                                                                     |
| ------------------------------------------------------------- | --------------- | ----------------------------------------------------------------------------------------------- |
| [Pricing](https://octodocs.peek.com/capabilities-1/pricing)   | `octo/pricing`  | Adds pricing to most endpoints giving you advanced static and dynamic pricing capabilities.     |
| [Webhooks](https://octodocs.peek.com/capabilities-1/webhooks) | `octo/webhooks` | Programatically create webhooks to listen for booking confirmations, updates and cancellations. |

Each capability is defined like the following:

```javascript
{
  "id": "octo/pricing",
  "revision": 1,
  "required": true,
  "dependencies": ["octo/pricing"],
  "default": true
}
```

| Field          | Description                                                                                                                                |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `id`           | The identifier of this capability. You'll need to include this in the request header or parameter to use this capability.                  |
| `revision`     | A auto-incrementing integer indicating the supported revision of this capability. Capability revisions will always be backward compatible. |
| `required`     | Whether supporting this capability is required in order to sell this product.                                                              |
| `dependencies` | An array of other capabilities that this capability requires in order to be used.                                                          |
| `docs`         | A URL to the online documentation for this capability.                                                                                     |
| `default`      | Whether this is a default capability that's enabled.                                                                                       |

By default, Peek Pro will enable the full list of capabilities all the time. There is currently no mechanism for controlling which capabilities are active.

To know which capabilities you are using, the HTTP response will echo the `Octo-Capabilities` header including the list that were applied. For example:

```http
HTTP/1.1 200 OK
Octo-Capabilities: octo/pricing, octo/webhooks
```

## Required Capabilities

Some products cannot be sold without the use of a capability. If that is the case then the `required: true` will be put on the capability object within that product. If you have not implemented that capability then you cannot sell the product.

## Capability Versioning

The capabilities defined on products include a `revision` number which will increment each time we update the capability. It's important to note that capabilities will **NEVER** introduce breaking changes, if they do then a new capability will be written entirely. For example: `octo/pricing2`


# Errors

OCTO will respond to every request with either a `200 OK` if everything went ok or `400 Bad Request` if it didn't. In the case of the `400 Bad Request` the response body will look like this:

```
{
    "error": "INVALID_PRODUCT_ID",
    "errorMessage": "The Product ID was invalid or missing",
    "productId": "av_123"
}
```

You will always receive `error` and `errorMessage` which is defined as:

| Field          | Description                                                     |
| -------------- | --------------------------------------------------------------- |
| `error`        | The error code, a table of possible error codes is shown below. |
| `errorMessage` | A human readable error message.                                 |

Depending on the error code we also may pass additional fields which can make it easier to understand what's wrong in your request. In the example above we provide `productId` and pass the value that was sent in the request, indicating that the productId of `av_123` is not valid.

## List of Error Codes <a href="#list-of-error-codes" id="list-of-error-codes"></a>

Below is a list of the error codes and a description of what each means. Further down this page we also provide an example request body for all the error codes that provide additional attributes.

| Code                      | Description                                                                                                                                                          |
| ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `INVALID_PRODUCT_ID`      | Missing or invalid `productId` in the request                                                                                                                        |
| `INVALID_OPTION_ID`       | Missing or invalid `optionId` in the request                                                                                                                         |
| `INVALID_UNIT_ID`         | Missing or invalid `unitId` in the request                                                                                                                           |
| `INVALID_AVAILABILITY_ID` | Missing or invalid `availabilityId` in the request                                                                                                                   |
| `INVALID_BOOKING_UUID`    | Missing or invalid booking uuid, or if you're confirming the booking the booking may have expired already.                                                           |
| `BAD_REQUEST`             | If your request body is not formatted correctly, you have missing required fields or any of the data types are incorrect.                                            |
| `UNPROCESSABLE_ENTITY`    | If your request body is technically correct but cannot be processed for other reasons. e.g. you tried to cancel a booking after the cancellation cutoff had elapsed. |
| `INTERNAL_SERVER_ERROR`   | Hopefully this never happens, but if the backend server is down or there's a network outage.                                                                         |
| `UNAUTHORIZED`            | You didn't send the API Key in the `Authorization` header to an endpoint that requires authentication.                                                               |
| `FORBIDDEN`               | You sent an API Key that was invalid or has been revoked by the backend system. Or you're trying to access an endpoint/resource that you do not have access to.      |

As explained above it's also possible for specific error codes to have additional attributes that help you diagnose what is wrong with your request. Below are all the specific errors that contain these attributes:

#### INVALID\_PRODUCT\_ID

```
{
    "error": "INVALID_PRODUCT_ID",
    "errorMessage": "The Product ID was invalid or missing",
    "productId": "av_123"
}
```

#### INVALID\_OPTION\_ID <a href="#invalid_option_id" id="invalid_option_id"></a>

```
{
    "error": "INVALID_PRODUCT_ID",
    "errorMessage": "The Option ID was invalid or missing",
    "optionId": "av_123"
}
```

#### INVALID\_UNIT\_ID <a href="#invalid_unit_id" id="invalid_unit_id"></a>

```
{
    "error": "INVALID_UNIT_ID",
    "errorMessage": "The Unit ID was invalid or missing",
    "unitId": "ecbdb23e-9840-4d15-b6f4-254a9ea401b2"
}
```

#### INVALID\_AVAILABILITY\_ID <a href="#invalid_availabiliy_id" id="invalid_availabiliy_id"></a>

```
{
    "error": "INVALID_AVAILABILITY_ID",
    "errorMessage": "The Availability ID was invalid or missing",
    "availabilityId": "20220111120000_60_5214a9d6-5271-4958-a306-14a07e4084c6"
}
```


# Products

List available products for purchase

This endpoint returns all products the operator has enabled for your connection.

## List Products

<mark style="color:blue;">`GET`</mark> `https://octo.peek.com/integrations/octo/products`

Returns all products the operator has enabled for the connection

{% tabs %}
{% tab title="200: OK " %}

```javascript
[
  {
    "id": "av_123",
    "internalName": "Rent-a-Kayak",
    "reference": "BRC-KAYAK",
    "locale": "en",
    "timeZone": "America/Los_Angeles",
    "allowFreesale": true,
    "availabilityType": "START_TIME",
    "deliveryFormats": ["QRCODE"],
    "deliveryMethods": ["VOUCHER"],
    "redemptionMethod": "DIGITAL",
    "capabilities": [
      {
        "id": "octo/pricing",
        "revision": 1,
        "required": true,
        "dependencies": []
      },
      {
        "id": "octo/webhooks",
        "revision": 1,
        "required": false,
        "dependencies": []
      }
    ],
    "options": [
      {
        "id": "av_123",
        "default": true,
        "internalName": "Rent-a-Kayak",
        "reference": null,
        "restrictions": {},
        "units": [
          {
            "id": "ea5fbd4c-9c2a-42f5-80c5-251a9f04da04",
            "internalName": "1-Seater Kayak",
            "reference": "1seat",
            "type": "ADULT",
            "restrictions": {
              "minAge": 18,
              "maxAge": 99,
              "idRequired": false,
              "minQuantity": 1,
              "maxQuantity": null,
              "paxCount": 1,
              "accompaniedBy": []
            }
          },
          {
            "id": "582fd9d7-43fd-4685-a9b2-35b102eaec3a",
            "internalName": "2-Seater Kayak",
            "reference": "2seat",
            "type": "ADULT",
            "restrictions": {
              "minAge": 18,
              "maxAge": 99,
              "idRequired": false,
              "minQuantity": 2,
              "maxQuantity": null,
              "paxCount": 1,
              "accompaniedBy": []
            }
          }
        ]
      }
    ]
  },
  //...rest of the products
]
```

{% endtab %}
{% endtabs %}

A description of each of the keys is given below:

| Field                                   | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| id                                      | The product id, you'll need to save this.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| internalName                            | The name this supplier calls the product                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| reference                               | An optional code this supplier might use to identify the product                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| locale                                  | A language code indicating what language this product content is in                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| timeZone                                | The IANA timeZone name this product is located in.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| allowFreesale                           | Whether a booking can be made for this product without having to query availability first.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| instantConfirmation                     | Whether bookings will be immediately confirmed when a sale is made, otherwise the supplier will later either accept or reject the booking.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `availabilityRequired`                  | Whether an `availabilityId` is required when creating a booking. Without this the booking will be open-dated and not have a specified travel date.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `availabilityType`                      | What type of availability this product has, possible values are: `START_TIME` if there are fixed departure times which you must pick one. Typical for day tours or activities. `OPENING_HOURS` if you just select a date and can visit any time when the venue is open.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| `deliveryFormats`                       | <p>An array of formats the API will deliver the tickets as. Possible values are:</p><p><code>QRCODE</code> A code to be presented as a QR CODE barcode</p><p><code>CODE128</code>A code to be presented as a CODE 128 barcode</p><p><code>PDF\_URL</code> A URL to a PDF file which contains all the ticket details</p>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| `deliveryMethods`                       | <p>How the formats described in <code>deliveryFormats</code> will be delivered in the booking response, possible values are:</p><p><code>TICKET</code> Individually per unit in the order (i.e. single ticket for each person)</p><p><code>VOUCHER</code> One ticket for the whole booking</p>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `redemptionMethod`                      | <p>How must the guest present the ticket or voucher when they arrive at the venue. Possible values are:</p><p><code>MANIFEST</code> The guest name will be written down and they just need to show up</p><p><code>DIGITAL</code> The tickets/voucher must be scanned but can be on mobile</p><p><code>PRINT</code> The tickets/voucher must be printed and presented on arrival</p>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| `capabilities`                          | Capabilities define API extensions that this product supports. Capabilities can be enabled using a special HTTP header that's described in the next section.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| `capabilities[].id`                     | The capability id which identifies it                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| `capabilities[].revision`               | An integer which will increment each time the specification for this capability is updated.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `capabilities[].required`               | Whether this product cannot be sold without this capability being used.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| `capabilities[].dependencies`           | An array of other capability ids that this capability depends on.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `capabilities[].docs`                   | A url to the documentation for this capability is.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `capabilities[].default`                | Whether this capability is enabled by default.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `options`                               | An array of all options for this product. All products must have at least one option.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| `options[].id`                          | The id that identifies this option, it is only unique within the product                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| `options[].default`                     | If there is only one option this value is `true` to indicate it is the default and therefore doesn't need to be displayed.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `options[].internalName`                | Like product internalName except for each option                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `options[].reference`                   | Like product reference except for each option                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `options[].restrictions`                | <p>An object containing a fixed list of restrictions. Keys and values are:</p><p><code>minUnits</code> The minimum number of tickets that can be purchased in a single booking (null = 0)</p><p><code>maxUnits</code> The maximum number of tickets that can be purchased in a single booking (null = unlimited)</p><p><code>options\[].availabilityLocalStartTimes</code></p>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `options[].availabilityLocalStartTimes` | This will be an array of all possible start times that can be returned during availability. For example an all day attraction may just have a single value like `["00:00"]` but a tour with multiple departure times may have:`["09:00", "14:00", "17:00"]`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `options[].cancellationCutoff`          | This is how long before the tour the booking can be still be cancelled. We also provide `booking.cancellable` (boolean) which we recommend you use instead to know if the booking can be cancelled. e.g. (1 Hour)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `options[].cancellationCutoffAmount`    | The numeric amount for the cutoff (e.g. 1)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `options[].cancellationCutoffUnit`      | The cutoff unit (e.g. hour). Possible values are: `hour`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| `options[].requiredContactFields[]`     | <p>An array of the contact fields required to confirm a booking. These just apply to the lead traveller on the booking and not for every ticket. Possible values are:<br><code>-fullName</code><br><code>-emailAddress</code><br><code>-phoneNumber</code><br><code>-country</code><br><code>-notes</code><br><code>-locales</code></p>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| `options[].units`                       | The list of ticket types (units) available for sale                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| `options[].units[].id`                  | The id of the unit, this will be unique to the option                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| `options[].units[].internalName`        | Like product/option internalName but for units                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `options[].units[].reference`           | Like product/option reference but for units                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `options[].units[].type`                | <p>This is the ticket type of the unit, values are:</p><p><code>ADULT</code> <code>YOUTH</code> <code>CHILD</code> <code>INFANT</code> <code>FAMILY</code> <code>SENIOR</code> <code>STUDENT</code> <code>MILITARY</code> <code>OTHER</code>The "other" type typically is used for an add-on, e.g. Bottle of Champaign, or a rental product like a bicycle.</p>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| `options[].units[].restrictions`        | <p>An object containing restrictions about this unit. Possible keys and values are:</p><p><code>minAge</code> An integer indicating the minimum age for the person this unit is for.</p><p><code>maxAge</code> An integer indicating the maximum age for the person this unit is for.</p><p><code>idRequired</code> A boolean value indicating whether the person this unit is for must show ID on arrival.</p><p><code>minQuantity</code> The minimum quantity of this unit required per booking (null = no minimum) <code>maxQuantity</code> The maximum quantity of this unit required per booking (null = no limit)</p><p><code>paxCount</code> The number of people this unit allows. Typically this is 1 but for a family ticket for example, it could be 4 or 5. <code>accompaniedBy</code> An array of unit ids one of which must accompany this unit if it is purchased.</p> |

If your server wants to query specific information about a product at a later stage, either to refresh your inventory or check for updates, you can call the following endpoint:

## Get Product

<mark style="color:blue;">`GET`</mark> `https://octo.peek.com/integrations/octo/products/:id`

#### Path Parameters

| Name                               | Type   | Description    |
| ---------------------------------- | ------ | -------------- |
| <mark style="color:red;">\*</mark> | String | The product id |

{% tabs %}
{% tab title="200: OK " %}

```javascript
{
  "id": "av_123",
  "internalName": "Rent-a-Kayak",
  "reference": "BRC-KAYAK",
  "locale": "en",
  "timeZone": "America/Los_Angeles",
  "allowFreesale": true,
  "availabilityType": "START_TIME",
  "deliveryFormats": ["QRCODE"],
  "deliveryMethods": ["VOUCHER"],
  "redemptionMethod": "DIGITAL",
  "capabilities": [
    {
      "id": "octo/pricing",
      "revision": 1,
      "required": true,
      "dependencies": []
    },
    {
      "id": "octo/webhooks",
      "revision": 1,
      "required": false,
      "dependencies": []
    }
  ],
  "options": [
    {
      "id": "av_123",
      "default": true,
      "internalName": "Rent-a-Kayak",
      "reference": null,
      "restrictions": {},
      "units": [
        {
          "id": "ea5fbd4c-9c2a-42f5-80c5-251a9f04da04",
          "internalName": "1-Seater Kayak",
          "reference": "1seat",
          "type": "ADULT",
          "restrictions": {
            "minAge": 18,
            "maxAge": 99,
            "idRequired": false,
            "minQuantity": 1,
            "maxQuantity": null,
            "paxCount": 1,
            "accompaniedBy": []
          }
        },
        {
          "id": "582fd9d7-43fd-4685-a9b2-35b102eaec3a",
          "internalName": "2-Seater Kayak",
          "reference": "2seat",
          "type": "ADULT",
          "restrictions": {
            "minAge": 18,
            "maxAge": 99,
            "idRequired": false,
            "minQuantity": 2,
            "maxQuantity": null,
            "paxCount": 1,
            "accompaniedBy": []
          }
        }
      ]
    }
  ]
}
```

{% endtab %}
{% endtabs %}


# Availability

Getting availability for a product

The first step when making a sale is to check for availability. Note if `allowFreesale` is set to true on the product then this step is optional but it is advised you check it anyway if you can to check for closures.

Peek Pro has two main availability calls:

`POST /availability/calendar` this endpoint is highly optimized and will return a single object per day. It's designed to be queried for large date ranges and the result is used to populate an availability calendar.

`POST /octo/availability` this endpoint is slightly slower as it will return an object for each individual departure time (or day). You have to perform this step to retrieve an `availabilityId` in order to confirm a sale, so if you just want to use this endpoint and skip the calendar endpoint then that's perfectly ok.

## Availability Calendar

<mark style="color:green;">`POST`</mark> `https://octo.peek.com/integrations/octo/availability/calendar`

The availability calendar endpoint for quick retrieval of availability over a date range

#### Request Body

| Name                                                | Type    | Description                                         |
| --------------------------------------------------- | ------- | --------------------------------------------------- |
| productId<mark style="color:red;">\*</mark>         | String  | The product id                                      |
| optionId                                            | String  | The option id                                       |
| localDateStart<mark style="color:red;">\*</mark>    | String  | Start date to query for (YYYY-MM-DD)                |
| localDateEnd<mark style="color:red;">\*</mark>      | String  | End date to query for (YYYY-MM-DD)                  |
| units                                               | Array   | A list of product option units and their quantities |
| units\[].id<mark style="color:red;">\*</mark>       | String  | The unit id                                         |
| units\[].quantity<mark style="color:red;">\*</mark> | Integer | The quantity of the unit                            |

{% tabs %}
{% tab title="200: OK " %}

```javascript
[
  {
    
    "localDate": "2020-07-01",
    "status": "AVAILABLE",
    "available": true,
    "capacity": 24,
    "openingHours": [
      { "from": "09:00", "to": "12:00" },
      { "from": "15:00", "to": "18:00" }
    ]
  },
  {
    "localDate": "2020-07-02",
    "status": "CLOSED",
    "available": false,
    "capacity": null,
    "openingHours": []
  }
]

```

{% endtab %}
{% endtabs %}

The availability calendar can optionally take an array of units if you already know what they are and will automatically show availabilities as sold out if they have insufficient space.

{% code title="POST /availability/calendar" %}

```javascript
{
  "productId": "av_123",
  "optionId": "av_123",
  "localDateStart": "2020-07-01",
  "localDateEnd": "2020-07-03",
  "units": [
    { "id": "ecbdb23e-9840-4d15-b6f4-254a9ea401b2", "quantity": 2 },
    { "id": "480d0c3e-80a1-4bf2-a39b-aa06332739df", "quantity": 1 }
  ]
}
```

{% endcode %}

The response will be an array of objects, one for each day between the range given in `localDateStart` and `localDateEnd`. Each object is defined as:

| Field                 | Description                                                                                                                                                                                                                                                                                                                                                                                  |
| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `localDate`           | The date (in format YYYY-MM-DD)                                                                                                                                                                                                                                                                                                                                                              |
| `status`              | <p>The status of that date. Possible values are:</p><p><code>AVAILABLE</code> There are availabilities available on this date for sale.</p><p><code>SOLD\_OUT</code> This date was available but is now fully sold out.</p><p><code>LIMITED</code> This date is available but has less than 50% capacity left.</p><p><code>CLOSED</code> This date is closed and not available for sale.</p> |
| `available`           | A boolean value (true or false) indicating whether you're able to sell tickets. This is basically just an alias for: `status == 'AVAILABLE' \|\| status == 'LIMITED'`                                                                                                                                                                                                                        |
| `capacity`            | The total capacity on this day. We cannot give exact vacancies on the calendar endpoint as this endpoint is cached for speed and is only meant to give an indication.                                                                                                                                                                                                                        |
| `openingHours`        | A list of opening hours that the product is open on this day.                                                                                                                                                                                                                                                                                                                                |
| `openingHours[].from` | When this product opens (HH:MM)                                                                                                                                                                                                                                                                                                                                                              |
| `openingHours[].to`   | When this product closes (HH:MM)                                                                                                                                                                                                                                                                                                                                                             |

## Availability Check

<mark style="color:green;">`POST`</mark> `https://octo.peek.com/integrations/octo/availability`

Get final availability for a given product. If in doubt between the calendar endpoint and this one, you should use this endpoint.

#### Request Body

| Name                                                | Type    | Description                                         |
| --------------------------------------------------- | ------- | --------------------------------------------------- |
| productId<mark style="color:red;">\*</mark>         | String  | The product id                                      |
| optionId                                            | String  | The option id                                       |
| localDateStart<mark style="color:red;">\*</mark>    | String  | Start date to query for (YYYY-MM-DD)                |
| localDateEnd<mark style="color:red;">\*</mark>      | String  | End date to query for (YYYY-MM-DD)                  |
| units                                               | Array   | A list of product option units and their quantities |
| units\[].id<mark style="color:red;">\*</mark>       | String  | End date to query for (YYYY-MM-DD)                  |
| units\[].quantity<mark style="color:red;">\*</mark> | Integer | The quantity of the unit                            |

{% tabs %}
{% tab title="200: OK " %}

```javascript
[
  {
    "id": "20200701113000_720_5214a9d6-5271-4958-a306-14a07e4084c6",
    "localDateTimeStart": "2020-07-01T11:30:00-08:00",
    "localDateTimeEnd": "2020-07-01T23:30:00-08:00",
    "utcCutoffAt": "2020-07-01T16:30:00Z",
    "allDay": false,
    "status": "AVAILABLE",
    "available": true,
    "vacancies": 24,
    "capacity": 24,
    "maxUnits": 24,
    "openingHours": []
  },
  {
    "id": "20200701120000_720_5214a9d6-5271-4958-a306-14a07e4084c6",
    "localDateTimeStart": "2020-07-01T12:00:00-08:00",
    "localDateTimeEnd": "2020-07-02T00:00:00-08:00",
    "utcCutoffAt": "2020-07-01T17:00:00Z",
    "allDay": false,
    "status": "AVAILABLE",
    "available": true,
    "vacancies": 24,
    "capacity": 24,
    "maxUnits": 24,
    "openingHours": []
  },
  {
    "id": "20200701143000_720_5214a9d6-5271-4958-a306-14a07e4084c6",
    "localDateTimeStart": "2020-07-01T14:30:00-08:00",
    "localDateTimeEnd": "2020-07-02T02:30:00-08:00",
    "utcCutoffAt": "2020-07-01T19:30:00Z",
    "allDay": false,
    "status": "AVAILABLE",
    "available": true,
    "vacancies": 24,
    "capacity": 24,
    "maxUnits": 24,
    "openingHours": []
  },
  {
    "id": "20200701150000_720_5214a9d6-5271-4958-a306-14a07e4084c6",,
    "localDateTimeStart": "2020-07-01T15:00:00-08:00",
    "localDateTimeEnd": "2020-07-02T03:00:00-08:00",
    "utcCutoffAt": "2020-07-01T20:00:00Z",
    "allDay": false,
    "status": "AVAILABLE",
    "available": true,
    "vacancies": 24,
    "capacity": 24,
    "maxUnits": 24,
    "openingHours": []
  }
]
```

{% endtab %}
{% endtabs %}

The availability calendar can optionally take an array of units if you already know what they are and will automatically show availabilities as sold out if they have insufficient space.

{% code title="POST /availability" %}

```javascript
{
  "productId": "av_123",
  "optionId": "av_123",
  "localDateStart": "2020-07-01",
  "localDateEnd": "2020-07-03",
  "units": [
    { "id": "ecbdb23e-9840-4d15-b6f4-254a9ea401b2", "quantity": 2 },
    { "id": "480d0c3e-80a1-4bf2-a39b-aa06332739df", "quantity": 1 }
  ]
}
```

{% endcode %}

The response will be an array of availability objects which are defined below:

| Field                | Description                                                                                                                                                                                                                                                                                                                                                    |
| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`                 | The availability id, you'll need this when booking                                                                                                                                                                                                                                                                                                             |
| `localDateTimeStart` | The start time for this availability. This will be in the local time zone to the product.                                                                                                                                                                                                                                                                      |
| `localDateTimeEnd`   | The end time for this availability. This will be in the local time zone to the product.                                                                                                                                                                                                                                                                        |
| `allDay`             | A boolean field indicating whether this is an all day availability and not a fixed departure time. If this value is true then there will be no other availability object on the same day.                                                                                                                                                                      |
| `status`             | <p>The status of that date. Possible values are:</p><p><code>AVAILABLE</code> This availability is available for sale</p><p><code>FREESALE</code> This availability has no capacity and is available.</p><p><code>SOLD\_OUT</code> This availability is not</p><p><code>LIMITED</code> This availability is available but has less than 50% capacity left.</p> |

Depending on the value of `product.availabilityType` the response will keep the same structure but will generally look slightly different. We've provided examples of that below:

{% tabs %}
{% tab title="OPENING\_HOURS" %}
Products with this availability type are typically Museums, Attractions or Hop on Hop off tours where the guest just picks a date they wish to travel and can show up at any point whilst the product is open.

This is a typical response from a product with `OPENING_HOURS` availability type:

```javascript
[
  {
    "id": "20200701120000_1440_ecbdb23e-9840-4d15-b6f4-254a9ea401b2",
    "localDateTimeStart": "2020-07-01T00:00:00-08:00",
    "localDateTimeEnd": "2020-07-01T23:59:59-08:00",
    "utcCutoffAt": "2020-07-01T05:00:00Z",
    "allDay": true,
    "status": "AVAILABLE",
    "available": true,
    "vacancies": null,
    "capacity": null,
    "maxUnits": null,
    "openingHours": [
      { "from": "09:00", "to": "12:00" },
      { "from": "15:00", "to": "18:00" }
    ]
  },
  {
    "id": "20200702120000_1440_5214a9d6-5271-4958-a306-14a07e4084c6",
    "localDateTimeStart": "2020-07-02T12:00:00-08:00",
    "localDateTimeEnd": "2020-07-02T23:59:59-08:00",
    "utcCutoffAt": "2020-07-02T05:00:00Z",
    "allDay": true,
    "status": "AVAILABLE",
    "available": true,
    "vacancies": null,
    "capacity": null,
    "maxUnits": null,
    "openingHours": [
      { "from": "09:00", "to": "12:00" },
      { "from": "15:00", "to": "18:00" }
    ]
  },
  {
    "id": "20200703120000_1440_5214a9d6-5271-4958-a306-14a07e4084c6",
    "localDateTimeStart": "2020-07-03T12:00:00-08:00",
    "localDateTimeEnd": "2020-07-03T23:59:59-08:00",
    "utcCutoffAt": "2020-07-03T05:00:00Z",
    "allDay": true,
    "status": "AVAILABLE",
    "available": true,
    "vacancies": null,
    "capacity": null,
    "maxUnits": null,
    "openingHours": [
      { "from": "09:00", "to": "12:00" },
      { "from": "15:00", "to": "18:00" }
    ]
  }
]
```

Notice how vacancies, capacity and max units are all null indicating unlimited, and the allDay flag is set true. You should just render this as a calendar with no further times to chose from once the guest has chosen the date.
{% endtab %}

{% tab title="START\_TIME" %}
Products with this availability type are typically walking tours, day trips and other activities where the guest has to book onto a specific departure time. There may be just one or multiple throughout the day.

This is a typical response from a product with `START_TIME` availability type:

```javascript
[
  {
    "id": "20200701113000_720_5214a9d6-5271-4958-a306-14a07e4084c6",
    "localDateTimeStart": "2020-07-01T11:30:00-08:00",
    "localDateTimeEnd": "2020-07-01T23:30:00-08:00",
    "utcCutoffAt": "2020-07-01T16:30:00Z",
    "allDay": false,
    "status": "AVAILABLE",
    "available": true,
    "vacancies": 24,
    "capacity": 24,
    "maxUnits": 24,
    "openingHours": []
  },
  {
    "id": "20200701120000_720_5214a9d6-5271-4958-a306-14a07e4084c6",
    "localDateTimeStart": "2020-07-01T12:00:00-08:00",
    "localDateTimeEnd": "2020-07-02T00:00:00-08:00",
    "utcCutoffAt": "2020-07-01T17:00:00Z",
    "allDay": false,
    "status": "AVAILABLE",
    "available": true,
    "vacancies": 24,
    "capacity": 24,
    "maxUnits": 24,
    "openingHours": []
  },
  {
    "id": "20200701143000_720_5214a9d6-5271-4958-a306-14a07e4084c6",
    "localDateTimeStart": "2020-07-01T14:30:00-08:00",
    "localDateTimeEnd": "2020-07-02T02:30:00-08:00",
    "utcCutoffAt": "2020-07-01T19:30:00Z",
    "allDay": false,
    "status": "AVAILABLE",
    "available": true,
    "vacancies": 24,
    "capacity": 24,
    "maxUnits": 24,
    "openingHours": []
  },
  {
    "id": "20200701150000_720_5214a9d6-5271-4958-a306-14a07e4084c6",,
    "localDateTimeStart": "2020-07-01T15:00:00-08:00",
    "localDateTimeEnd": "2020-07-02T03:00:00-08:00",
    "utcCutoffAt": "2020-07-01T20:00:00Z",
    "allDay": false,
    "status": "AVAILABLE",
    "available": true,
    "vacancies": 24,
    "capacity": 24,
    "maxUnits": 24,
    "openingHours": []
  }
]
```

These are all availabilities for the same day. Once the guest has chosen the date (in this example `2020-07-01` then they must then pick a departure time. Again in this example the departure times would be:

* 11:00 AM
* 12:00 PM
* 2:30 PM
* 3:00 PM
  {% endtab %}
  {% endtabs %}

{% hint style="info" %}
Unlike the calendar endpoint, the availability check endpoint will not return an availability object if the product is closed. If there are no availabilities for a given date you should just mark it as closed in your interface.
{% endhint %}


# Booking

Reserving availability and making a booking

The steps to making a booking are as follows:

1. **Check Availability** Check the availability in the previous section and retrieve an availability ID.
2. **Booking Reservation** Create a booking that reserves the availability while you collect payment and contact information from the customer.&#x20;
3. **Booking Confirmation** The final step, once payment has been taken and you want to finalize the booking.

## Booking Reservation

<mark style="color:green;">`POST`</mark> `https://octo.peek.com/integrations/octo/bookings`

The first step is to reserve the availability by creating the booking.

#### Request Body

| Name                                                  | Type    | Description                                                                                                              |
| ----------------------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------ |
| uuid                                                  | String  | A unique UUID to identify the booking. Setting this value acts as an idempotency key, preventing you from double booking |
| expirationMinutes                                     | Integer | How many minutes to reserve the availability, otherwise defaults to the supplier default amount                          |
| productId<mark style="color:red;">\*</mark>           | String  | The product id                                                                                                           |
| optionId                                              | String  | The option id                                                                                                            |
| availabilityId<mark style="color:red;">\*</mark>      | String  | The availability ID                                                                                                      |
| unitItems<mark style="color:red;">\*</mark>           | Array   | An array of unit items                                                                                                   |
| unitItems\[].unitId<mark style="color:red;">\*</mark> | String  | The unit item unit ID                                                                                                    |
| unitItems\[].uuid                                     | String  | A unique UUID to identify the unit, same as the booking uuid except per unit                                             |
| resellerReference                                     | String  | Your reference for this booking. Also known as a Voucher Number                                                          |
| contact                                               | Object  | Contact information                                                                                                      |

{% tabs %}
{% tab title="200: OK " %}

```javascript
{
  "uuid": "89fe0192-ddcd-430a-b285-e1396a4725d2",
  "testMode": true,
  "resellerReference": null,
  "supplierReference": "X749G9",
  "status": "ON_HOLD",
  "utcExpiresAt": "2020-06-07T17:06:37Z",
  "utcConfirmedAt": null,
  "productId": "av_123",
  "optionId": "av_123",
  "cancellable": true,
  "cancellation": null,
  "freesale": false,
  "notes": "optional notes on the booking",
  "availability": {
    "id": "20200701143000_720_5214a9d6-5271-4958-a306-14a07e4084c6",
    "localDateTimeStart": "2020-07-01T14:30:00-08:00",
    "localDateTimeEnd": "2020-07-02T02:30:00-08:00",
    "allDay": true,
    "openingHours": []
  },
  "contact": {
    "fullName": null,
    "emailAddress": null,
    "phoneNumber": null,
    "locales": [],
    "country": null
  },
  "deliveryMethods": [
    "VOUCHER"
  ],
  "voucher": {
    "redemptionMethod": "DIGITAL",
    "utcRedeemedAt": null,
    "deliveryOptions": []
  },
  "unitItems": [
    {
      "uuid": "eeddd74e-88e6-4dab-84e9-14f7af18935f",
      "resellerReference": null,
      "supplierReference": "408H44",
      "unitId": "ecbdb23e-9840-4d15-b6f4-254a9ea401b2"
    },
    {
      "uuid": "ec1e2622-1359-437b-83f8-15182759d605",
      "resellerReference": null,
      "supplierReference": "BSDYM4",
      "unitId": "ecbdb23e-9840-4d15-b6f4-254a9ea401b2"
    },
    {
      "uuid": "de9855fd-8176-4551-9ba9-ae8c997cb2bb",
      "resellerReference": null,
      "supplierReference": "E5K92G",
      "unitId": "480d0c3e-80a1-4bf2-a39b-aa06332739df"
    }
  ]
}
```

{% endtab %}
{% endtabs %}

The request above was made with the following request body:

```javascript
{
  "productId": "av_123",
  "optionId": "av_123",
  "availabilityId": "20200701143000_720_5214a9d6-5271-4958-a306-14a07e4084c6",
  "notes": "Optional notes for the booking",
  "unitItems": [
    { "unitId": "ecbdb23e-9840-4d15-b6f4-254a9ea401b2" },
    { "unitId": "ecbdb23e-9840-4d15-b6f4-254a9ea401b2" },
    { "unitId": "480d0c3e-80a1-4bf2-a39b-aa06332739df" }
  ]
}
```

The UUID on the request body and on each unit is optional but recommended if you're requesting from a source of poor network connectivity. If the connection fails or you do not receive a response, you can repeat the same request with the same UUID and it will respond with the same booking object without duplicating the booking.

The booking object is described as:

| Field                                        | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| -------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `uuid`                                       | A unique UUID used to identify booking. Make sure you save this value as you will need it to perform any future actions against this booking.                                                                                                                                                                                                                                                                                                                           |
| `testMode`                                   | Whether this booking is in test mode.                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| `resellerReference`                          | Your reference (as the reseller). You set this value in the second confirmation request                                                                                                                                                                                                                                                                                                                                                                                 |
| `supplierReference`                          | The Peek Pro reference for this booking. Use this to help the supplier find this booking.                                                                                                                                                                                                                                                                                                                                                                               |
| `status`                                     | <p>The status of the booking. Possible values are:</p><p><code>ON\_HOLD</code> The booking is pending confirmation, this is the default value when you first create the booking.</p><p><code>EXPIRED</code> If the booking is not confirmed before the expiration hold expires, it goes into an expired state.</p><p><code>CONFIRMED</code> Once the confirmation call is made the booking is ready to be used. <code>CANCELLED</code> If the booking is cancelled.</p> |
| `utcExpiresAt`                               | An ISO8601 date time in UTC for when this booking is due to expire if the status is `ON_HOLD`                                                                                                                                                                                                                                                                                                                                                                           |
| `utcConfirmedAt`                             | An ISO8601 date time in UTC when the booking was confirmed.                                                                                                                                                                                                                                                                                                                                                                                                             |
| `productId`                                  | The product ID for this booking                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `optionId`                                   | The option ID for this booking                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| `cancellable`                                | A boolean field indicating whether this booking can be cancelled.                                                                                                                                                                                                                                                                                                                                                                                                       |
| `cancellation`                               | An object with information about why and when the booking was cancelled. This is `null` if the booking is not cancelled.                                                                                                                                                                                                                                                                                                                                                |
| `freesale`                                   | Whether the booking was made as freesale (without checking availability first).                                                                                                                                                                                                                                                                                                                                                                                         |
| `notes`                                      | Public notes on the booking.                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `cancellation.reason`                        | A text value describing why the cancellation happened.                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `cancellation.refund`                        | Whether the booking was refunded as part of the cancellation. Possible values are `FULL`, `PARTIAL` or `NONE`                                                                                                                                                                                                                                                                                                                                                           |
| `cancellation.utcCancelledAt`                | An ISO8601 date time in UTC indicating when the booking was cancelled.                                                                                                                                                                                                                                                                                                                                                                                                  |
| `availability`                               | The availability object that was booked.                                                                                                                                                                                                                                                                                                                                                                                                                                |
| `availability.id`                            | The availability id that was used in the request.                                                                                                                                                                                                                                                                                                                                                                                                                       |
| `availability.localDateTimeStart`            | The `localDateTimeStart` value from the original availability object.                                                                                                                                                                                                                                                                                                                                                                                                   |
| `availability.localDateTimeEnd`              | The `localDateTimeEnd` value from the original availability object.                                                                                                                                                                                                                                                                                                                                                                                                     |
| `availability.allDay`                        | A boolean value indicating whether the availability is all day.                                                                                                                                                                                                                                                                                                                                                                                                         |
| `availability.openingHours`                  | The opening hours from the original availability object.                                                                                                                                                                                                                                                                                                                                                                                                                |
| `contact`                                    | The customer contact details. These values are set in the booking confirmation step.                                                                                                                                                                                                                                                                                                                                                                                    |
| `contact.fullName`                           | The full name of the guest                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| <p><code>contact.emailAddress</code><br></p> | The email of the guest                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `contact.phoneNumber`                        | The phone number of the guest                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `contact.locales`                            | An array of locale values, equivalent to `navigator.languages` in a browsers environment.                                                                                                                                                                                                                                                                                                                                                                               |
| `deliveryMethods`                            | <p>An array of delivery methods available for this booking. Possible values are:</p><p><code>VOUCHER</code> The voucher object is populated which is a single ticket for the whole booking.</p><p><code>TICKET</code> The ticket object is populated on each unit item which is a ticket for each individual person.</p>                                                                                                                                                |
| `voucher`                                    | This value will be set if `deliveryMethods` array has `VOUCHER` as one of the values.                                                                                                                                                                                                                                                                                                                                                                                   |
| `voucher.redemptionMethod`                   | <p>How the voucher can be redeemed. Possible values are:</p><p><code>MANIFEST</code> The guest name will be written down and they just need to show up</p><p><code>DIGITAL</code> The tickets/voucher must be scanned but can be on mobile</p><p><code>PRINT</code> The tickets/voucher must be printed and presented on arrival</p>                                                                                                                                    |
| `voucher.utcRdeemedAt`                       | The ISO8601 date in UTC indicating when the voucher was used at the attraction.                                                                                                                                                                                                                                                                                                                                                                                         |
| `voucher.deliveryOptions`                    | This is an array of delivery options for the voucher each object. You should use one of these to give the tickets to the guest.                                                                                                                                                                                                                                                                                                                                         |
| `voucher.deliveryOptions[].deliveryFormat`   | <p>The format for the delivery option possible values are:</p><p><code>QRCODE</code> You should generate the QR Code yourself on a ticket.</p><p><code>PDF\_URL</code> Where you use the Peek Pro generated tickets as a PDF.</p>                                                                                                                                                                                                                                       |
| `voucher.deliveryOptions[].deliveryValue`    | <p>Depending on the value of <code>deliveryFormat</code> this value is either:</p><p><code>QRCODE</code> This value is a string to encode in a QR Code.</p><p><code>PDF\_URL</code> This value is a URL linking to a Peek-generated voucher PDF.</p>                                                                                                                                                                                                                    |
| `unitItems`                                  | This is an array of unit items generated when making the booking.                                                                                                                                                                                                                                                                                                                                                                                                       |
| `unitItems[].uuid`                           | A unique UUID per unit item that you can use to help track it.                                                                                                                                                                                                                                                                                                                                                                                                          |
| `unitItems[].resellerReference`              | Your reference (as a reseller) for this unit item.                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `unitItems[].supplierReference`              | The Peek Pro reference for this unit item.                                                                                                                                                                                                                                                                                                                                                                                                                              |
| `unitItems[].unitId`                         | The unit id used for this unit item                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `unitItems[].ticket`                         | If `deliveryMethods` has `TICKET` as one of its values this object will be set. The data structure will be identical to the `voucher` object.                                                                                                                                                                                                                                                                                                                           |

The booking object schema described above will be returned on every endpoint in this section. Only the values may change.

## Booking Update

<mark style="color:purple;">`PATCH`</mark> `https://octo.peek.com/integrations/octo/bookings/:uuid`

This endpoint allows you to update an existing booking. The request parameters are the same as the booking reservation endpoint.

{% tabs %}
{% tab title="200: OK " %}

```javascript
{
  "uuid": "89fe0192-ddcd-430a-b285-e1396a4725d2",
  "testMode": true,
  "resellerReference": null,
  "supplierReference": "X749G9",
  "status": "ON_HOLD",
  "utcExpiresAt": "2020-06-07T17:06:37Z",
  "utcConfirmedAt": null,
  "productId": "av_123",
  "optionId": "av_123",
  "cancellable": true,
  "cancellation": null,
  "freesale": false,
  "notes": "optional notes on the booking",
  "availability": {
    "id": "20200701143000_720_5214a9d6-5271-4958-a306-14a07e4084c6",
    "localDateTimeStart": "2020-07-01T14:30:00-05:00",
    "localDateTimeEnd": "2020-07-02T02:30:00-05:00",
    "allDay": true,
    "openingHours": []
  },
  "contact": {
    "fullName": null,
    "emailAddress": null,
    "phoneNumber": null,
    "locales": [],
    "country": null
  },
  "deliveryMethods": [
    "VOUCHER"
  ],
  "voucher": {
    "redemptionMethod": "DIGITAL",
    "utcRedeemedAt": null,
    "deliveryOptions": []
  },
  "unitItems": [
    {
      "uuid": "eeddd74e-88e6-4dab-84e9-14f7af18935f",
      "resellerReference": null,
      "supplierReference": "408H44",
      "unitId": "ecbdb23e-9840-4d15-b6f4-254a9ea401b2"
    },
    {
      "uuid": "ec1e2622-1359-437b-83f8-15182759d605",
      "resellerReference": null,
      "supplierReference": "BSDYM4",
      "unitId": "ecbdb23e-9840-4d15-b6f4-254a9ea401b2"
    },
    {
      "uuid": "de9855fd-8176-4551-9ba9-ae8c997cb2bb",
      "resellerReference": null,
      "supplierReference": "E5K92G",
      "unitId": "480d0c3e-80a1-4bf2-a39b-aa06332739df"
    }
  ]
}
```

{% endtab %}
{% endtabs %}

You can update a booking before and after it has been confirmed as long as it hasn't been redeemed or within the cancellation cutoff window. To know if the booking can be updated check the `booking.cancellable` field. If the booking can be cancelled, it can also be updated. It's generally preferred to update a booking rather than cancelling it and rebooking.

## Booking Confirmation

<mark style="color:green;">`POST`</mark> `https://octo.peek.com/integrations/octo/bookings/:uuid/confirm`

This endpoint confirms the booking so it's ready to be used.

#### Path Parameters

| Name                                   | Type   | Description             |
| -------------------------------------- | ------ | ----------------------- |
| uuid<mark style="color:red;">\*</mark> | String | The UUID of the booking |

#### Request Body

| Name                                                   | Type   | Description                                                                                       |
| ------------------------------------------------------ | ------ | ------------------------------------------------------------------------------------------------- |
| resellerReference                                      | String | Your reference for this booking. Also known as a Voucher Number.                                  |
| contact<mark style="color:red;">\*</mark>              | Object | Contact information                                                                               |
| contact.fullName<mark style="color:red;">\*</mark>     | String | The customer's full name                                                                          |
| contact.emailAddress<mark style="color:red;">\*</mark> | String | The customer's email                                                                              |
| contact.phoneNumber                                    | String | The customer's phone number                                                                       |
| contact.locales                                        | Array  | An array of customer's locales. You can get this from `navigator.languages` in a browser context. |
| contact.country                                        | String | The customer's country code                                                                       |

{% tabs %}
{% tab title="200: OK " %}

```javascript
{
  "uuid": "89fe0192-ddcd-430a-b285-e1396a4725d2",
  "testMode": true,
  "resellerReference": "VOUCHER-0123",
  "supplierReference": "X749G9",
  "status": "CONFIRMED",
  "utcExpiresAt": null,
  "utcConfirmedAt": "2020-06-07T18:36:29Z",
  "productId": "av_123",
  "optionId": "av_123",
  "cancellable": true,
  "cancellation": null,
  "freesale": false,
  "notes": "Optional notes on the booking",
  "availability": {
    "id": "20200701143000_720_5214a9d6-5271-4958-a306-14a07e4084c6",
    "localDateTimeStart": "2020-07-01T14:30:00-08:00",
    "localDateTimeEnd": "2020-07-02T02:30:00-08:00",
    "allDay": true,
    "openingHours": []
  },
  "contact": {
    "fullName": "Oliver Morgan",
    "emailAddress": "ollym@me.com",
    "phoneNumber": "+447840739436"
  },
  "deliveryMethods": [
    "VOUCHER"
  ],
  "voucher": {
    "redemptionMethod": "DIGITAL",
    "utcRedeemedAt": null,
    "deliveryOptions": [
      {
        "deliveryFormat": "QRCODE",
        "deliveryValue": "http://short.peek.stack/public-html/app-redirect/booking/b_qw47z/pos/"
      }
    ]
  },
  "unitItems": [
    {
      "uuid": "eeddd74e-88e6-4dab-84e9-14f7af18935f",
      "resellerReference": null,
      "supplierReference": "408H44",
      "unitId": "480d0c3e-80a1-4bf2-a39b-aa06332739df"
    },
    {
      "uuid": "ec1e2622-1359-437b-83f8-15182759d605",
      "resellerReference": null,
      "supplierReference": "BSDYM4",
      "unitId": "ecbdb23e-9840-4d15-b6f4-254a9ea401b2"
    },
    {
      "uuid": "de9855fd-8176-4551-9ba9-ae8c997cb2bb",
      "resellerReference": null,
      "supplierReference": "E5K92G",
      "unitId": "ecbdb23e-9840-4d15-b6f4-254a9ea401b2"
    }
  ]
}
```

{% endtab %}
{% endtabs %}

An example of the confirmation request above looks like this:

```javascript
{
  "resellerReference": "VOUCHER-0123",
  "contact": {
    "fullName": "Oliver Morgan",
    "emailAddress": "ollym@me.com",
    "phoneNumber": "+447840739436"
  }
}
```

Once the booking is confirmed, the delivery options of both the voucher and/or ticket are populated. An example of the values is shown below:

```javascript
//...inside either "voucher" and/or "ticket"

"redemptionMethod": "DIGITAL",
"utcRedeemedAt": null,
"deliveryOptions": [
  {
    "deliveryFormat": "QRCODE",
    "deliveryValue": "http://short.peek.stack/public-html/app-redirect/booking/b_qw47z/pos/"
  }
]
```

If `booking.deliveryMethods` contains both TICKET and VOUCHER then both those values will be set. You can then offer the guest whether they'd like their tickets per-person (`booking.unitItems[].ticket`) or one for the whole booking (`booking.voucher`). If you're unable to offer the choice then it's suggested you default to one falling back to the other if that's not available.

## Booking Cancellation

<mark style="color:green;">`POST`</mark> `https://octo.peek.com/integrations/octo/bookings/:uuid/cancel`

If the booking is confirmed this endpoint will cancel it, otherwise it will release the availability that was put on hold.

#### Path Parameters

| Name                                   | Type   | Description             |
| -------------------------------------- | ------ | ----------------------- |
| uuid<mark style="color:red;">\*</mark> | String | The UUID of the booking |

#### Request Body

| Name   | Type   | Description                           |
| ------ | ------ | ------------------------------------- |
| reason | String | The reason for cancelling the booking |

{% tabs %}
{% tab title="200: OK " %}

```javascript
{
  "uuid": "89fe0192-ddcd-430a-b285-e1396a4725d2",
  "testMode": true,
  "resellerReference": "VOUCHER-0123",
  "supplierReference": "X749G9",
  "status": "CANCELLED",
  "utcExpiresAt": null,
  "utcConfirmedAt": "2020-06-07T18:36:29Z",
  "productId": "av_123",
  "optionId": "av_123",
  "cancellable": true,
  "cancellation": {
    "refund": "FULL",
    "reason": "Customer requested",
    "utcCancelledAt": "2020-06-07T18:36:29Z"
  },
  "freesale": false,
  "notes": "Optional notes on the booking",
  "availability": {
    "id": "20200701143000_720_5214a9d6-5271-4958-a306-14a07e4084c6",
    "localDateTimeStart": "2020-07-01T14:30:00-08:00",
    "localDateTimeEnd": "2020-07-02T02:30:00-08:00",
    "allDay": true,
    "openingHours": []
  },
  "contact": {
    "fullName": "Oliver Morgan",
    "emailAddress": "ollym@me.com",
    "phoneNumber": "+447840739436"
  },
  "deliveryMethods": [
    "VOUCHER"
  ],
  "voucher": {
    "redemptionMethod": "DIGITAL",
    "utcRedeemedAt": null,
    "deliveryOptions": [
      {
        "deliveryFormat": "QRCODE",
        "deliveryValue": "http://short.peek.stack/public-html/app-redirect/booking/b_qw47z/pos/"
      }
    ]
  },
  "unitItems": [
    {
      "uuid": "eeddd74e-88e6-4dab-84e9-14f7af18935f",
      "resellerReference": null,
      "supplierReference": "408H44",
      "unitId": "480d0c3e-80a1-4bf2-a39b-aa06332739df"
    },
    {
      "uuid": "ec1e2622-1359-437b-83f8-15182759d605",
      "resellerReference": null,
      "supplierReference": "BSDYM4",
      "unitId": "ecbdb23e-9840-4d15-b6f4-254a9ea401b2"
    },
    {
      "uuid": "de9855fd-8176-4551-9ba9-ae8c997cb2bb",
      "resellerReference": null,
      "supplierReference": "E5K92G",
      "unitId": "ecbdb23e-9840-4d15-b6f4-254a9ea401b2"
    }
  ]
}
```

{% endtab %}
{% endtabs %}

Note you can only cancel a booking if `booking.cancellable` is true.

## Extend Reservation

<mark style="color:green;">`POST`</mark> `https://octo.peek.com/integrations/octo/bookings/:uuid/extend`

Use this method to hold the availability for a booking longer if the status is \`ON\_HOLD\`.

#### Path Parameters

| Name                                   | Type   | Description                  |
| -------------------------------------- | ------ | ---------------------------- |
| uuid<mark style="color:red;">\*</mark> | String | UUID of the original booking |

#### Request Body

| Name                                                | Type    | Description                                                             |
| --------------------------------------------------- | ------- | ----------------------------------------------------------------------- |
| expirationMinutes<mark style="color:red;">\*</mark> | Integer | How many minutes from now do you want to have the booking reserved for. |

{% tabs %}
{% tab title="200: OK " %}

```javascript
{
  "uuid": "89fe0192-ddcd-430a-b285-e1396a4725d2",
  "testMode": true,
  "resellerReference": null,
  "supplierReference": "X749G9",
  "status": "ON_HOLD",
  "utcExpiresAt": "2020-06-07T17:06:37Z",
  "utcConfirmedAt": null,
  "productId": "av_123",
  "optionId": "av_123",
  "cancellable": true,
  "cancellation": null,
  "freesale": false,
  "availability": {
    "id": "20200701143000_720_5214a9d6-5271-4958-a306-14a07e4084c6",
    "localDateTimeStart": "2020-07-01T14:30:00-08:00",
    "localDateTimeEnd": "2020-07-02T02:30:00-08:00",
    "allDay": true,
    "openingHours": []
  },
  "contact": null,
  "deliveryMethods": [
    "VOUCHER"
  ],
  "voucher": {
    "redemptionMethod": "DIGITAL",
    "utcRedeemedAt": null,
    "deliveryOptions": []
  },
  "unitItems": [
    {
      "uuid": "eeddd74e-88e6-4dab-84e9-14f7af18935f",
      "resellerReference": null,
      "supplierReference": "408H44",
      "unitId": "480d0c3e-80a1-4bf2-a39b-aa06332739df"
    },
    {
      "uuid": "ec1e2622-1359-437b-83f8-15182759d605",
      "resellerReference": null,
      "supplierReference": "BSDYM4",
      "unitId": "ecbdb23e-9840-4d15-b6f4-254a9ea401b2"
    },
    {
      "uuid": "de9855fd-8176-4551-9ba9-ae8c997cb2bb",
      "resellerReference": null,
      "supplierReference": "E5K92G",
      "unitId": "ecbdb23e-9840-4d15-b6f4-254a9ea401b2"
    }
  ]
}
```

{% endtab %}
{% endtabs %}

## Get Booking

<mark style="color:blue;">`POST`</mark> `https://octo.peek.com/integrations/octo/bookings/:uuid`

Fetch the status of an existing booking

#### Path Parameters

| Name                                   | Type   | Description                      |
| -------------------------------------- | ------ | -------------------------------- |
| uuid<mark style="color:red;">\*</mark> | String | The uuid of the original booking |

{% tabs %}
{% tab title="200: OK " %}

```javascript
{
  "uuid": "89fe0192-ddcd-430a-b285-e1396a4725d2",
  "testMode": true,
  "resellerReference": "VOUCHER-0123",
  "supplierReference": "X749G9",
  "status": "CONFIRMED",
  "utcExpiresAt": null,
  "utcConfirmedAt": "2020-06-07T18:36:29Z",
  "productId": "av_123",
  "optionId": "av_123",
  "cancellable": true,
  "cancellation": null,
  "freesale": false,
  "notes": "Optional notes on the booking",
  "availability": {
    "id": "20200701143000_720_5214a9d6-5271-4958-a306-14a07e4084c6",
    "localDateTimeStart": "2020-07-01T14:30:00-08:00",
    "localDateTimeEnd": "2020-07-02T02:30:00-08:00",
    "allDay": true,
    "openingHours": []
  },
  "contact": {
    "fullName": "Oliver Morgan",
    "emailAddress": "ollym@me.com",
    "phoneNumber": "+447840739436"
  },
  "deliveryMethods": [
    "VOUCHER"
  ],
  "voucher": {
    "redemptionMethod": "DIGITAL",
    "utcRedeemedAt": null,
    "deliveryOptions": [
      {
        "deliveryFormat": "QRCODE",
        "deliveryValue": "http://short.peek.stack/public-html/app-redirect/booking/b_qw47z/pos/"
      }
    ]
  },
  "unitItems": [
    {
      "uuid": "eeddd74e-88e6-4dab-84e9-14f7af18935f",
      "resellerReference": null,
      "supplierReference": "408H44",
      "unitId": "480d0c3e-80a1-4bf2-a39b-aa06332739df"
    },
    {
      "uuid": "ec1e2622-1359-437b-83f8-15182759d605",
      "resellerReference": null,
      "supplierReference": "BSDYM4",
      "unitId": "ecbdb23e-9840-4d15-b6f4-254a9ea401b2"
    },
    {
      "uuid": "de9855fd-8176-4551-9ba9-ae8c997cb2bb",
      "resellerReference": null,
      "supplierReference": "E5K92G",
      "unitId": "ecbdb23e-9840-4d15-b6f4-254a9ea401b2"
    }
  ]
}
```

{% endtab %}
{% endtabs %}

This endpoint will fetch the booking with the provided UUID from the system.

## List Bookings

<mark style="color:blue;">`GET`</mark> `https://octo.peek.com/integrations/octo/bookings`

List bookings in the system given certain parameters

#### Query Parameters

| Name              | Type   | Description                            |
| ----------------- | ------ | -------------------------------------- |
| resellerReference | String | The reseller reference on the booking  |
| supplierReference | String | The reference provided by the supplier |
| localDate         | String | All bookings made for a specific date  |
| localDateStart    | String | First date of a date range search      |
| localDateEnd      | String | Last date of a date range search       |
| productId         | String | The product id to filter by            |
| optionId          | String | The option id to filter by             |

{% tabs %}
{% tab title="200: OK " %}

```javascript
[
  {
    "uuid": "89fe0192-ddcd-430a-b285-e1396a4725d2",
    "testMode": true,
    "resellerReference": "VOUCHER-0123",
    "supplierReference": "X749G9",
    "status": "CONFIRMED",
    "utcExpiresAt": null,
    "utcConfirmedAt": "2020-06-07T18:36:29Z",
    "productId": "av_123",
    "optionId": "av_123",
    "cancellable": true,
    "cancellation": null,
    "freesale": false,
    "notes": "Optional notes on the booking",
    "availability": {
      "id": "20200701143000_720_5214a9d6-5271-4958-a306-14a07e4084c6",
      "localDateTimeStart": "2020-07-01T14:30:00-08:00",
      "localDateTimeEnd": "2020-07-02T02:30:00-08:00",
      "allDay": true,
      "openingHours": []
    },
    "contact": {
      "fullName": "Oliver Morgan",
      "emailAddress": "ollym@me.com",
      "phoneNumber": "+447840739436"
    },
    "deliveryMethods": [
      "VOUCHER"
    ],
    "voucher": {
      "redemptionMethod": "DIGITAL",
      "utcRedeemedAt": null,
      "deliveryOptions": [
        {
          "deliveryFormat": "QRCODE",
          "deliveryValue": "http://short.peek.stack/public-html/app-redirect/booking/b_qw47z/pos/"
        }
      ]
    },
    "unitItems": [
      {
        "uuid": "eeddd74e-88e6-4dab-84e9-14f7af18935f",
        "resellerReference": null,
        "supplierReference": "408H44",
          "unitId": "480d0c3e-80a1-4bf2-a39b-aa06332739df"
      },
      {
        "uuid": "ec1e2622-1359-437b-83f8-15182759d605",
        "resellerReference": null,
        "supplierReference": "BSDYM4",
        "unitId": "ecbdb23e-9840-4d15-b6f4-254a9ea401b2"
      },
      {
        "uuid": "de9855fd-8176-4551-9ba9-ae8c997cb2bb",
        "resellerReference": null,
        "supplierReference": "E5K92G",
        "unitId": "ecbdb23e-9840-4d15-b6f4-254a9ea401b2"
      }
    ]
  },
  //... other bookings
]
```

{% endtab %}
{% endtabs %}


# Pricing

Provides pricing information to various endpoints

This capability supports dynamic pricing where the price of the product can be changed day by day and even at different start times. Make sure your system is able to support this level of pricing before you integrate with it.

## Product Pricing

<mark style="color:blue;">`GET`</mark> `https://octo.peek.com/integrations/octo/products/:id`

Returns top-level pricing by unit on each product.

#### Path Parameters

| Name | Type   | Description                                        |
| ---- | ------ | -------------------------------------------------- |
| id   | String | Returns top-level pricing by unit on each product. |

{% tabs %}
{% tab title="200: OK " %}

```javascript
{
  "id": "av_123",
  "internalName": "Rent-a-Kayak",
  "reference": "BRC-KAYAK",
  "locale": "en",
  "timeZone": "America/Los_Angeles",
  "allowFreesale": true,
  "availabilityType": "START_TIME",
  "deliveryFormats": ["QRCODE"],
  "deliveryMethods": ["VOUCHER"],
  "redemptionMethod": "DIGITAL",
  "capabilities": [
    {
      "id": "octo/pricing",
      "revision": 1,
      "required": true,
      "dependencies": []
    },
    {
      "id": "octo/webhooks",
      "revision": 1,
      "required": false,
      "dependencies": []
    }
  ],
  "defaultCurrency": "USD",
  "availableCurrencies": ["USD"],
  "pricingPer": "UNIT",
  "options": [
    {
      "id": "av_123",
      "default": true,
      "internalName": "Rent-a-Kayak",
      "reference": null,
      "restrictions": {},
      "units": [
        {
          "id": "ea5fbd4c-9c2a-42f5-80c5-251a9f04da04",
          "internalName": "1-Seater Kayak",
          "reference": "1seat",
          "type": "ADULT",
          "restrictions": {
            "minAge": 18,
            "maxAge": 99,
            "idRequired": false,
            "minQuantity": 1,
            "maxQuantity": null,
            "paxCount": 1,
            "accompaniedBy": []
          },
          "pricingFrom": [
            {
              "original": 5999,
              "retail": 5999,
              "net": null,
              "currency": "USD",
              "currencyPrecision": 2
            }
          ],
        },
        {
          "id": "582fd9d7-43fd-4685-a9b2-35b102eaec3a",
          "internalName": "2-Seater Kayak",
          "reference": "2seat",
          "type": "ADULT",
          "restrictions": {
            "minAge": 18,
            "maxAge": 99,
            "idRequired": false,
            "minQuantity": 2,
            "maxQuantity": null,
            "paxCount": 1,
            "accompaniedBy": []
          },
          "pricingFrom": [
            {
              "original": 9999,
              "retail": 9999,
              "net": null,
              "currency": "USD",
              "currencyPrecision": 2 
            }
          ]
        }
      ]
    }
  ]
}
```

{% endtab %}
{% endtabs %}

On the response the only changes from the original schema is on the Product object:

```javascript
{
  // ...rest of Product object
  "defaultCurrency": "USD",
  "availableCurrencies": ["USD", "EUR", "GBP"],
  "pricingPer": "UNIT" // "UNIT" or "BOOKING"
}
```

The `defaultCurrency` is the default currency for this product, if you omit the `currency` parameter on future endpoints this is the value Peek Pro will fallback to. `availableCurrencies` are all the possible currencies that we accept for this product.

`pricingPer` indicates whether the pricing is per unit (most common), or per booking. Pricing which is per booking is common for private charters or group booking products where the price is the same regardless of how many tickets are purchased.

Next, if `pricingPer = "UNIT"`, on each Unit (adult, child, etc.) we add the following:

```javascript
{
  // ...rest of the Unit object
  "pricingFrom": [
    {
      "original": 4500,
      "retail": 4500,
      "net": 3500,
      "currency": "USD",
      "currencyPrecision": 2,
      "includedTaxes": [
        {
          "name": "VAT 10",
          "retail": 800,
          "net": 500
        }
      ]
    },
    {
      "original": 4000,
      "retail": 4000,
      "net": 3000,
      "currency": "GBP",
      "currencyPrecision": 2,
      "includedTaxes": [
        {
          "name": "VAT 10",
          "retail": 700,
          "net": 400
        }
      ]
    }
    // ...etc...
  ]
}
```

If `pricingPer = "BOOKING"` then these fields will be on the Product itself instead of the Unit as the pricing applies once to the booking regardless of how many units (tickets) are purchased.

We'll produce one `pricingFrom` object for each currency in `availableCurrencies` . The meaning of each pricing field is given below:

| Field               | Description                                                                                                                                                                                                                                                |
| ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `original`          | The original price for this product which will be the same or higher than the sale amount. Use this to show a discount has been applied e.g. ~~$10~~ **$8.50**                                                                                             |
| `retail`            | The sale price you should charge your customers.                                                                                                                                                                                                           |
| `net`               | The wholesale rate the supplier will charge you for this sale.                                                                                                                                                                                             |
| `currency`          | The currency.                                                                                                                                                                                                                                              |
| `currencyPrecision` | All pricing is given in integers to avoid floating point rounding issues. e.g. USD = 2 and JPY = 0. To convert a price to decimal you should do: `price / (10 ** currencyPrecision)` where \*\* is to the power of e.g. `Math.pow(10, currencyPrecision)`. |
| `includedTaxes`     | Any taxes included in the retail and/or net price.                                                                                                                                                                                                         |

{% hint style="warning" %}
Throughout this capability we'll use a convention where we'll end the object key with `From` to indicate this is indicative and not the final price. Make sure you communicate this also to the customer.
{% endhint %}

## Pricing Calendar

<mark style="color:green;">`POST`</mark> `https://octo.peek.com/integrations/octo/availability/calendar`

The documentation above only shows the additions this capability adds to the availability calendar endpoint. See the documentation in [Availability](/booking-flow/availability#availability-calendar) to see the full request parameters and response object.

Using the availability calendar endpoint for pricing is designed to make it easy to generate a pricing calendar for example on Google Travel:

![](https://603390319-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FCthZkTSjFuKEeDXpfq8K%2Fuploads%2FBjoHEy0s2jRwzIShctXO%2F68747470733a2f2f692e696d6775722e636f6d2f793039325676392e706e67.png?alt=media\&token=faeeed4f-bd58-4ffc-a2f8-7c764c396eda)

Each availability object is given a new `unitPricingFrom` field with an array of unit prices in the currency for example:

{% tabs %}
{% tab title="pricingPer = UNIT" %}

```javascript
{
  "localDate": "2020-07-01",
  "status": "AVAILABLE",
  "capacity": 24,
  "openingHours": []
  "unitPricingFrom": [
    {
      "unitId": "ecbdb23e-9840-4d15-b6f4-254a9ea401b2",
      "original": 4500,
      "retail": 4500,
      "net": 3500,
      "currency": "USD",
      "currencyPrecision": 2,
      "includedTaxes": [
        {
          "name": "VAT 10",
          "retail": 700,
          "net": 400
        }
      ]
    },
    {
      "unitId": "480d0c3e-80a1-4bf2-a39b-aa06332739df",
      "original": 4200,
      "retail": 4200,
      "net": 3200,
      "currency": "USD",
      "currencyPrecision": 2,
      "includedTaxes": [
        {
          "name": "VAT 10",
          "retail": 800,
          "net": 500
        }
      ]
    }
  ]
}
```

{% endtab %}

{% tab title="pricingPer = BOOKING" %}

```javascript
{
  "localDate": "2020-07-01",
  "status": "AVAILABLE",
  "capacity": 24,
  "openingHours": []
  "pricingFrom": [
    {
      "original": 4500,
      "retail": 4500,
      "net": 3500,
      "currency": "USD",
      "currencyPrecision": 2,
      "includedTaxes": [
        {
          "name": "VAT 10",
          "retail": 700,
          "net": 400
        }
      ]
    },
    {
      "original": 4200,
      "retail": 4200,
      "net": 3200,
      "currency": "USD",
      "currencyPrecision": 2,
      "includedTaxes": [
        {
          "name": "VAT 10",
          "retail": 800,
          "net": 500
        }
      ]
    }
  ]
}
```

{% endtab %}
{% endtabs %}

If you pass the `units` to the request then we'll give the total pricing for the selection under the `pricingFrom` field, which is also included by default if `pricingPer = BOOKING` as the number of units isn't needed to know what the price of the booking is. For example:

{% tabs %}
{% tab title="Request" %}

```javascript
{
  "productId": "av_123",
  "optionId": "av_123",
  "localDateStart": "2020-07-01",
  "localDateEnd": "2020-07-02",
  "units": [
    {
      "id": "ecbdb23e-9840-4d15-b6f4-254a9ea401b2",
      "quantity": 2
    },
    {
      "id": "480d0c3e-80a1-4bf2-a39b-aa06332739df",
      "quantity": 1
    }
  ]
}
```

{% endtab %}

{% tab title="Response (pricingPer = UNIT)" %}

```javascript
[
  {
    "localDate": "2020-07-01",
    "status": "AVAILABLE",
    "capacity": 24,
    "openingHours": [],
    "unitPricingFrom": [
      {
        "original": 3995,
        "retail": 3995,
        "net": 2996,
        "currency": "USD",
        "currencyPrecision": 2,
        "unitId": "adult",
        "includedTaxes": [
          {
            "name": "VAT 10",
            "retail": 400,
            "net": 250
          }
        ]
      },
      {
        "original": 1995,
        "retail": 1995,
        "net": 1496,
        "currency": "USD",
        "currencyPrecision": 2,
        "unitId": "child",
        "includedTaxes": [
          {
            "name": "VAT 10",
            "retail": 200,
            "net": 50
          }
        ]
      }
    ],
    "pricingFrom": {
      "original": 9985,
      "retail": 9985,
      "net": 7488,
      "currency": "USD",
      "currencyPrecision": 2,
      "includedTaxes": [
        {
          "name": "VAT 10",
          "retail": 800,
          "net": 500
        }
      ]
    }
  }
]
```

{% endtab %}

{% tab title="Response (pricingPer = BOOKING)" %}

```javascript
[
  {
    "localDate": "2020-07-01",
    "status": "AVAILABLE",
    "capacity": 24,
    "openingHours": [],
    "pricingFrom": {
      "original": 9985,
      "retail": 9985,
      "net": 7488,
      "currency": "USD",
      "currencyPrecision": 2,
      "includedTaxes": [
        {
          "name": "VAT 10",
          "retail": 800,
          "net": 500
        }
      ]
    }
  }
]
```

{% endtab %}
{% endtabs %}

Having the `pricingFrom` value calculated for you makes it much easier to display a single price on each date on the calendar (assuming the guest has chosen how many units they want before you display the calendar).

If pricingPer = BOOKING then unitPricingFrom will not be provided.

## Pricing Check

<mark style="color:green;">`POST`</mark> `https://octo.peek.com/integrations/octo/availability`

Returns a final quote of the price before making a booking.

{% tabs %}
{% tab title="200: OK " %}

```javascript
{
    // Response
}
```

{% endtab %}
{% endtabs %}

This endpoint is the availability check endpoint which has been extended to add pricing. We only document the added parameters here, to see the full documentation for the original availability check you can find it in [Availability](/booking-flow/availability#availability-check).

If we were to repeat the request above in the calendar section this is what the response would look like instead:

{% tabs %}
{% tab title="Request" %}

```javascript
{
  "productId": "av_132",
  "optionId": "av_123",
  "localDateStart": "2020-07-01",
  "localDateEnd": "2020-07-02",
  "units": [
    {
      "id": "ecbdb23e-9840-4d15-b6f4-254a9ea401b2",
      "quantity": 2
    },
    {
      "id": "480d0c3e-80a1-4bf2-a39b-aa06332739df",
      "quantity": 1
    }
  ]
}
```

{% endtab %}

{% tab title="Response (pricingPer = UNIT)" %}

```javascript
[
  {
    "id": "20200701113000_720_ecbdb23e-9840-4d15-b6f4-254a9ea401b2",
    "localDateTimeStart": "2020-07-01T11:30:00-08:00",
    "localDateTimeEnd": "2020-07-01T23:30:00-08:00",
    "utcCutoffAt": "2020-07-01T16:30:00Z",
    "allDay": false,
    "status": "AVAILABLE",
    "vacancies": 24,
    "capacity": 24,
    "maxUnits": 24,
    "openingHours": [],
    "unitPricing": [
      {
        "original": 3995,
        "retail": 3995,
        "net": 2996,
        "currency": "USD",
        "currencyPrecision": 2,
        "unitId": "adult",
        "includedTaxes": [
          {
            "name": "VAT 10",
            "retail": 400,
            "net": 250
          }
        ]
      },
      {
        "original": 1995,
        "retail": 1995,
        "net": 1496,
        "currency": "USD",
        "currencyPrecision": 2,
        "unitId": "child",
        "includedTaxes": [
          {
            "name": "VAT 10",
            "retail": 200,
            "net": 50
          }
        ]
      }
    ],
    "pricing": {
      "original": 9985,
      "retail": 9985,
      "net": 7488,
      "currency": "USD",
      "currencyPrecision": 2,
      "includedTaxes": [
        {
          "name": "VAT 10",
          "retail": 800,
          "net": 500
        }
      ]
    }
  },
  {
    "id": "20200701120000_720_480d0c3e-80a1-4bf2-a39b-aa06332739df",
    "localDateTimeStart": "2020-07-01T12:00:00-08:00",
    "localDateTimeEnd": "2020-07-02T00:00:00-08:00",
    "utcCutoffAt": "2020-07-01T17:00:00Z",
    "allDay": false,
    "status": "AVAILABLE",
    "vacancies": 24,
    "capacity": 24,
    "maxUnits": 24,
    "openingHours": [],
    "unitPricing": [
      {
        "original": 3995,
        "retail": 3995,
        "net": 2996,
        "currency": "USD",
        "currencyPrecision": 2,
        "unitId": "adult",
        "includedTaxes": [
          {
            "name": "VAT 10",
            "retail": 400,
            "net": 250
          }
        ]
      },
      {
        "original": 1995,
        "retail": 1995,
        "net": 1496,
        "currency": "USD",
        "currencyPrecision": 2,
        "unitId": "child",
        "includedTaxes": [
          {
            "name": "VAT 10",
            "retail": 200,
            "net": 50
          }
        ]
      }
    ],
    "pricing": {
      "original": 9985,
      "retail": 9985,
      "net": 7488,
      "currency": "USD",
      "currencyPrecision": 2,
      "includedTaxes": [
        {
          "name": "VAT 10",
          "retail": 800,
          "net": 500
        }
      ]
    }
  }
]
```

{% endtab %}

{% tab title="Response (pricingPer = BOOKING)" %}

```javascript
[
  {
    "id": "20200701113000_720_ecbdb23e-9840-4d15-b6f4-254a9ea401b2",
    "localDateTimeStart": "2020-07-01T11:30:00-05:00",
    "localDateTimeEnd": "2020-07-01T23:30:00-05:00",
    "allDay": false,
    "status": "AVAILABLE",
    "vacancies": 24,
    "capacity": 24,
    "maxUnits": 24,
    "openingHours": [],
    "pricing": {
      "original": 9985,
      "retail": 9985,
      "net": 7488,
      "currency": "USD",
      "currencyPrecision": 2,
      "includedTaxes": [
        {
          "name": "VAT 10",
          "retail": 800,
          "net": 500
        }
      ]
    }
  },
  {
    "id": "2020-07-01T12:00:00-20200701120000_720_480d0c3e-80a1-4bf2-a39b-aa06332739df",
    "localDateTimeStart": "2020-07-01T12:00:00-08:00",
    "localDateTimeEnd": "2020-07-02T00:00:00-08:00",
    "allDay": false,
    "status": "AVAILABLE",
    "vacancies": 24,
    "capacity": 24,
    "maxUnits": 24,
    "openingHours": [],
    "pricing": {
      "original": 9985,
      "retail": 9985,
      "net": 7488,
      "currency": "USD",
      "currencyPrecision": 2,
      "includedTaxes": [
        {
          "name": "VAT 10",
          "retail": 800,
          "net": 500
        }
      ]
    }
  }
]
```

{% endtab %}
{% endtabs %}

Notice how the response fields are `unitPricing` and `pricing` (without the From suffix). That is because this is the final price, and this is what the booking will be once confirmed.

## Booking Reservation

<mark style="color:green;">`POST`</mark> `https://octo.peek.com/integrations/octo/bookings`

The booking reservation call

{% tabs %}
{% tab title="200: OK " %}

```javascript
{
  "uuid": "89fe0192-ddcd-430a-b285-e1396a4725d2",
  "testMode": true,
  "resellerReference": null,
  "supplierReference": "X749G9",
  "status": "ON_HOLD",
  "utcExpiresAt": "2020-06-07T17:06:37Z",
  "utcConfirmedAt": null,
  "productId": "av_123",
  "optionId": "av_123",
  "cancellable": true,
  "cancellation": null,
  "freesale": false,
  "notes": "optional notes on the booking",
  "availability": {
    "id": "20200701143000_720_5214a9d6-5271-4958-a306-14a07e4084c6",
    "localDateTimeStart": "2020-07-01T14:30:00-08:00",
    "localDateTimeEnd": "2020-07-02T02:30:00-08:00",
    "allDay": true,
    "openingHours": []
  },
  "contact": {
    "fullName": null,
    "emailAddress": null,
    "phoneNumber": null,
    "locales": [],
    "country": null
  },
  "deliveryMethods": [
    "VOUCHER"
  ],
  "voucher": {
    "redemptionMethod": "DIGITAL",
    "utcRedeemedAt": null,
    "deliveryOptions": []
  },
  "pricing": {
    "original": 8800,
    "retail": 8800,
    "net": 5500,
    "currency": "EUR",
    "currencyPrecision": 2,
    "includedTaxes": []
  },
  "unitItems": [
    {
      "uuid": "eeddd74e-88e6-4dab-84e9-14f7af18935f",
      "resellerReference": null,
      "supplierReference": "408H44",
      "unitId": "ecbdb23e-9840-4d15-b6f4-254a9ea401b2"
    },
    {
      "uuid": "ec1e2622-1359-437b-83f8-15182759d605",
      "resellerReference": null,
      "supplierReference": "BSDYM4",
      "unitId": "ecbdb23e-9840-4d15-b6f4-254a9ea401b2"
    },
    {
      "uuid": "de9855fd-8176-4551-9ba9-ae8c997cb2bb",
      "resellerReference": null,
      "supplierReference": "E5K92G",
      "unitId": "480d0c3e-80a1-4bf2-a39b-aa06332739df"
    }
  ]
}
```

{% endtab %}
{% endtabs %}

This capability extends the booking schema to add a `pricing` field which gives you the final price of the booking as well as any included taxes. The final price includes tax, and should be what you display to the guest as the amount they need to pay.

```javascript
  "pricing": {
    "original": 8800,
    "retail": 8800,
    "net": 5500,
    "currency": "EUR",
    "currencyPrecision": 2,
    "includedTaxes": []
  }
```

We include the net amount as well as any taxes included in the net price.


# Webhooks

Get notifications sent to you when something changes

This capability allows you to create webhooks which will notify a given URL whenever an action happens in Peek Pro, e.g. Booking Update or Booking Cancellation.

## Create Webhook

<mark style="color:green;">`POST`</mark> `https://octo.peek.com/integrations/octo/webhooks`

Create a new webhook

#### Request Body

| Name                                    | Type   | Description                                   |
| --------------------------------------- | ------ | --------------------------------------------- |
| url<mark style="color:red;">\*</mark>   | String | The URL to call when the webhook is triggered |
| event<mark style="color:red;">\*</mark> | String | The event that will trigger the webhook       |

{% tabs %}
{% tab title="200: OK " %}

```javascript
{
  "id": "octohook_123",
  "event": "booking_update",
  "url": "https://example.com/webhooks/availability_update"
}
```

{% endtab %}
{% endtabs %}

| Field   | Description                                                                                                                                                                                                                                     |
| ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `url`   | <p>A fully formed URL. If you want to include basic authentication credentials that is supported also. For example:</p><ul><li><code><https://user:pass@example.com/webook></code></li><li><code><https://example.com/webhook></code></li></ul> |
| `event` | <p>The event that will trigger the webhook. Possible values are:</p><p><code>booking\_update</code> triggered when an existing booking is confirmed, updated or cancelled.</p>                                                                  |

An example response will look like this:

```javascript
{
  "id": "octohook_123",
  "event": "booking_update",
  "url": "https://example.com/webhooks/booking_update"
}
```

We recommend for testing you can use [ngrok](https://ngrok.com/) to create an endpoint which connects to your localhost. You can then make test bookings with the same credentials and see the webhook requests arrive.

When an event is triggered the webhook will perform a `POST` HTTP request to the specified URL, the request body will look like this depending on the event type:

{% tabs %}
{% tab title="booking\_update" %}

```javascript
{
  "webhook": {
    "id": "octohook_123",
    "event": "booking_update",
    "url": "https://example.com/webhooks/booking_update"
  },
  "booking": {
    "uuid": "89fe0192-ddcd-430a-b285-e1396a4725d2",
    "testMode": true,
    "resellerReference": null,
    "supplierReference": "X749G9",
    "status": "ON_HOLD",
    "utcExpiresAt": "2020-06-07T17:06:37Z",
    "utcConfirmedAt": null,
    "productId": "av_123",
    "optionId": "av_123",
    "cancellable": true,
    "cancellation": null,
    "freesale": false,
    "notes": "optional notes on the booking",
    "availability": {
      "id": "20200701143000_720_5214a9d6-5271-4958-a306-14a07e4084c6",
      "localDateTimeStart": "2020-07-01T14:30:00-08:00",
      "localDateTimeEnd": "2020-07-02T02:30:00-08:00",
      "allDay": true,
      "openingHours": []
    },
    "contact": {
      "fullName": null,
      "emailAddress": null,
      "phoneNumber": null,
      "locales": [],
      "country": null
    },
    "deliveryMethods": [
      "VOUCHER"
    ],
    "voucher": {
      "redemptionMethod": "DIGITAL",
      "utcRedeemedAt": null,
      "deliveryOptions": []
    },
    "unitItems": [
      {
        "uuid": "eeddd74e-88e6-4dab-84e9-14f7af18935f",
        "resellerReference": null,
        "supplierReference": "408H44",
        "unitId": "ecbdb23e-9840-4d15-b6f4-254a9ea401b2"
      },
      {
        "uuid": "ec1e2622-1359-437b-83f8-15182759d605",
        "resellerReference": null,
        "supplierReference": "BSDYM4",
        "unitId": "ecbdb23e-9840-4d15-b6f4-254a9ea401b2"
      },
      {
        "uuid": "de9855fd-8176-4551-9ba9-ae8c997cb2bb",
        "resellerReference": null,
        "supplierReference": "E5K92G",
        "unitId": "480d0c3e-80a1-4bf2-a39b-aa06332739df"
      }
    ]
  }
}
```

{% endtab %}
{% endtabs %}

This endpoint will return a list of all existing webhooks.

## List Webhooks

<mark style="color:blue;">`GET`</mark> `https://octo.peek.com/integrations/octo/webhooks`

List all webhooks

{% tabs %}
{% tab title="200: OK " %}

```javascript
[
  {
    "id": "octohook_123",
    "event": "booking_update",
    "url": "https://example.com/webhooks/booking_update"
  }
]
```

{% endtab %}
{% endtabs %}

## Delete Webhooks

<mark style="color:red;">`DELETE`</mark> `https://octo.peek.com/integrations/octo/webhooks/:id`

Delete an existing webhook

#### Path Parameters

| Name                                 | Type   | Description    |
| ------------------------------------ | ------ | -------------- |
| id<mark style="color:red;">\*</mark> | String | The webhook id |

{% tabs %}
{% tab title="200: OK " %}

```javascript
{
  "id": "octohook_123",
  "event": "booking_update",
  "url": "https://example.com/webhooks/booking_update"
  }
]
```

{% endtab %}
{% endtabs %}


