# Pricing

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

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.

This capability extends product routes documented in [Products](https://docs.ventrata.com/octo-core/products):

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

This pricing extension is returned on both `GET /products` and `GET /products/:productId`.

On the response, pricing adds the following fields on the Product object:

`defaultCurrency` is the fallback currency. `availableCurrencies` are all valid currencies for this product. `includeTax` indicates whether product prices already include tax. `hidePricingFrom` indicates whether from-prices should be hidden in UI contexts.

`pricingPer` indicates whether pricing is per unit (most common) or per booking.

If `pricingPer = "UNIT"`, each option unit/item includes `pricingFrom`.

If `pricingPer = "BOOKING"`, each option includes `pricingFrom` instead.

If `currency` is omitted, pricing arrays include one object per value in `availableCurrencies`. If `currency` is set (or set to `default`), pricing arrays contain a single object.

{% hint style="warning" %}
Throughout this capability, fields ending with `From` are indicative prices and not final prices. Make sure this is communicated clearly to customers.
{% endhint %}

This capability extends availability calendar routes documented in [Availability](https://docs.ventrata.com/octo-core/availability#availability-calendar):

* `POST /availability/calendar`
* `GET /availability/calendar`

This pricing extension is available on both `GET /availability/calendar` and `POST /availability/calendar`.

The documentation above only shows the additions this capability adds to the availability calendar endpoint. See the documentation [here](https://docs.ventrata.com/octo-core/availability#availability-calendar) to see the full request parameters and response object.

`units` supports nested fields:

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

![Pricing calendar example](https://221588849-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M7bgGIyO7QYNOfUMfxh%2F-M9FJR76XCztVEaXvWcm%2F-M9FNv2YSMk-oIninjcb%2F68747470733a2f2f692e696d6775722e636f6d2f793039325676392e706e67.png?alt=media\&token=6be1bad1-7ba4-45eb-98c3-ef9a12a42dcd)

Each availability object is given:

* `unitPricingFrom`: an array of unit/item prices, each with `unitId` and `unitType`
* `pricingFrom`: a total pricing object for the availability (for `pricingPer = UNIT`, this is only meaningful once `units` are passed)

If you pass `units`, `pricingFrom` returns the total pricing for that selection. For `pricingPer = BOOKING`, `pricingFrom` is still returned without unit selection because booking pricing is not ticket-count driven.

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).

For `pricingPer = BOOKING`, `unitPricingFrom` may still be present for item-style units (type `OTHER`) and can be an empty array.

This capability extends availability check routes documented in [Availability](https://docs.ventrata.com/octo-core/availability#availability-check):

* `POST /availability`
* `GET /availability`

This pricing extension is available on both `GET /availability` and `POST /availability`.

`unitPricing` rows include `unitId` and `unitType`, plus the shared pricing object fields described earlier.

`units` uses the same schema shown in the availability calendar section (`id`, `quantity`, optional `weightValue` and `weightUnit`). Availability `extras` use objects with `id` and `quantity`.

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 [here](https://docs.ventrata.com/octo-core/availability#availability-check).

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.

Batch variants (`POST /availability/batch` and `POST /availability/calendar/batch`) return the same pricing extensions because they proxy these same endpoints.

This capability extends booking write routes documented in [Bookings](https://docs.ventrata.com/octo-core/bookings#endpoints):

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

This capability extends booking responses to add a final `pricing` object. The final price includes tax and is the amount to show/pay.

This pricing payload is returned anywhere a booking object is serialized (booking write/read/cancel/extend routes in [Bookings](https://docs.ventrata.com/octo-core/bookings#endpoints)).

If request `pricing` is provided, it must match the server-calculated booking totals.

Base booking schema: [Bookings](https://docs.ventrata.com/octo-core/bookings#endpoints).

If a partner has enforced price-matching and no matching `pricing` object is sent, the request fails with `PRICING_MATCH_REQUIRED`.

Write endpoints that build/update booking/order/gift records also accept `currency`. You can pass `default` to use the preferred currency automatically.

Booking payloads can include pricing at these paths:

* `pricing`
* `availability.pricing`
* `availability.unitPricing[]`
* `option.pricing` (for `pricingPer = BOOKING`)
* `option.units[].pricing` and `option.units[].pricingFrom` (depending on unit type/selection state)
* `unitItems[].pricing`
* `unitItems[].unit.pricing`

Additional pricing serialization using the same pricing object schema:

* Order responses include `pricing` on order write/read/cancel/extend routes (see [Multi-Booking Cart](https://docs.ventrata.com/capabilities/cart)).
* Gift responses include `pricing` on gift write/read/cancel/extend routes (see [Gift Vouchers](https://docs.ventrata.com/capabilities/gift-vouchers)).
* Destination objects serialized by `octo/content` include `defaultCurrency` and `availableCurrencies`.

## Schema Additions (JSON)

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

### `Availability`

```json
{
  "// ...rest of availability object": "...",
  "pricing": {
    "original": 22000,
    "retail": 20000,
    "net": 18000,
    "currency": "USD",
    "currencyPrecision": 2,
    "includedTaxes": [
      {
        "name": "Sales Tax",
        "shortDescription": "Local sales tax",
        "original": 2000,
        "retail": 1800,
        "net": 1600
      }
    ]
  },
  "pricingFrom": {
    "original": 22000,
    "retail": 20000,
    "net": 18000,
    "currency": "USD",
    "currencyPrecision": 2,
    "includedTaxes": [
      {
        "name": "Sales Tax",
        "shortDescription": "Local sales tax",
        "original": 2000,
        "retail": 1800,
        "net": 1600
      }
    ]
  },
  "unitPricing": [
    {
      "unitId": "unit_adult",
      "unitType": "ADULT",
      "original": 12000,
      "retail": 10000,
      "net": 9000,
      "currency": "USD",
      "currencyPrecision": 2,
      "includedTaxes": [
        {
          "name": "Sales Tax",
          "shortDescription": "Local sales tax",
          "original": 1200,
          "retail": 1000,
          "net": 900
        }
      ]
    }
  ],
  "unitPricingFrom": [
    {
      "unitId": "unit_adult",
      "unitType": "ADULT",
      "original": 12000,
      "retail": 10000,
      "net": 9000,
      "currency": "USD",
      "currencyPrecision": 2,
      "includedTaxes": [
        {
          "name": "Sales Tax",
          "shortDescription": "Local sales tax",
          "original": 1200,
          "retail": 1000,
          "net": 900
        }
      ]
    }
  ],
  "extraPricing": [
    {
      "extraId": "extra_fast_track",
      "original": 2000,
      "retail": 1800,
      "net": 1600,
      "currency": "USD",
      "currencyPrecision": 2,
      "includedTaxes": [
        {
          "name": "Sales Tax",
          "shortDescription": "Local sales tax",
          "original": 200,
          "retail": 180,
          "net": 160
        }
      ]
    }
  ],
  "extraPricingFrom": [
    {
      "extraId": "extra_fast_track",
      "original": 2000,
      "retail": 1800,
      "net": 1600,
      "currency": "USD",
      "currencyPrecision": 2,
      "includedTaxes": [
        {
          "name": "Sales Tax",
          "shortDescription": "Local sales tax",
          "original": 200,
          "retail": 180,
          "net": 160
        }
      ]
    }
  ]
}
```

### `AvailabilityBatchRow`

```json
{
  "// ...rest of availability batch row object": "...",
  "pricing": {
    "original": 22000,
    "retail": 20000,
    "net": 18000,
    "currency": "USD",
    "currencyPrecision": 2,
    "includedTaxes": [
      {
        "name": "Sales Tax",
        "shortDescription": "Local sales tax",
        "original": 2000,
        "retail": 1800,
        "net": 1600
      }
    ]
  },
  "pricingFrom": {
    "original": 22000,
    "retail": 20000,
    "net": 18000,
    "currency": "USD",
    "currencyPrecision": 2,
    "includedTaxes": [
      {
        "name": "Sales Tax",
        "shortDescription": "Local sales tax",
        "original": 2000,
        "retail": 1800,
        "net": 1600
      }
    ]
  },
  "unitPricing": [
    {
      "unitId": "unit_adult",
      "unitType": "ADULT",
      "original": 12000,
      "retail": 10000,
      "net": 9000,
      "currency": "USD",
      "currencyPrecision": 2,
      "includedTaxes": [
        {
          "name": "Sales Tax",
          "shortDescription": "Local sales tax",
          "original": 1200,
          "retail": 1000,
          "net": 900
        }
      ]
    }
  ],
  "unitPricingFrom": [
    {
      "unitId": "unit_adult",
      "unitType": "ADULT",
      "original": 12000,
      "retail": 10000,
      "net": 9000,
      "currency": "USD",
      "currencyPrecision": 2,
      "includedTaxes": [
        {
          "name": "Sales Tax",
          "shortDescription": "Local sales tax",
          "original": 1200,
          "retail": 1000,
          "net": 900
        }
      ]
    }
  ],
  "extraPricing": [
    {
      "extraId": "extra_fast_track",
      "original": 2000,
      "retail": 1800,
      "net": 1600,
      "currency": "USD",
      "currencyPrecision": 2,
      "includedTaxes": [
        {
          "name": "Sales Tax",
          "shortDescription": "Local sales tax",
          "original": 200,
          "retail": 180,
          "net": 160
        }
      ]
    }
  ],
  "extraPricingFrom": [
    {
      "extraId": "extra_fast_track",
      "original": 2000,
      "retail": 1800,
      "net": 1600,
      "currency": "USD",
      "currencyPrecision": 2,
      "includedTaxes": [
        {
          "name": "Sales Tax",
          "shortDescription": "Local sales tax",
          "original": 200,
          "retail": 180,
          "net": 160
        }
      ]
    }
  ]
}
```

### `AvailabilityCalendar`

```json
{
  "// ...rest of availability calendar object": "...",
  "pricingFrom": {
    "original": 22000,
    "retail": 20000,
    "net": 18000,
    "currency": "USD",
    "currencyPrecision": 2,
    "includedTaxes": [
      {
        "name": "Sales Tax",
        "shortDescription": "Local sales tax",
        "original": 2000,
        "retail": 1800,
        "net": 1600
      }
    ]
  },
  "unitPricingFrom": [
    {
      "unitId": "unit_adult",
      "unitType": "ADULT",
      "original": 12000,
      "retail": 10000,
      "net": 9000,
      "currency": "USD",
      "currencyPrecision": 2,
      "includedTaxes": [
        {
          "name": "Sales Tax",
          "shortDescription": "Local sales tax",
          "original": 1200,
          "retail": 1000,
          "net": 900
        }
      ]
    }
  ],
  "extraPricingFrom": [
    {
      "extraId": "extra_fast_track",
      "original": 2000,
      "retail": 1800,
      "net": 1600,
      "currency": "USD",
      "currencyPrecision": 2,
      "includedTaxes": [
        {
          "name": "Sales Tax",
          "shortDescription": "Local sales tax",
          "original": 200,
          "retail": 180,
          "net": 160
        }
      ]
    }
  ]
}
```

### `AvailabilityCalendarBatchRow`

```json
{
  "// ...rest of availability calendar batch row object": "...",
  "pricingFrom": {
    "original": 22000,
    "retail": 20000,
    "net": 18000,
    "currency": "USD",
    "currencyPrecision": 2,
    "includedTaxes": [
      {
        "name": "Sales Tax",
        "shortDescription": "Local sales tax",
        "original": 2000,
        "retail": 1800,
        "net": 1600
      }
    ]
  },
  "unitPricingFrom": [
    {
      "unitId": "unit_adult",
      "unitType": "ADULT",
      "original": 12000,
      "retail": 10000,
      "net": 9000,
      "currency": "USD",
      "currencyPrecision": 2,
      "includedTaxes": [
        {
          "name": "Sales Tax",
          "shortDescription": "Local sales tax",
          "original": 1200,
          "retail": 1000,
          "net": 900
        }
      ]
    }
  ],
  "extraPricingFrom": [
    {
      "extraId": "extra_fast_track",
      "original": 2000,
      "retail": 1800,
      "net": 1600,
      "currency": "USD",
      "currencyPrecision": 2,
      "includedTaxes": [
        {
          "name": "Sales Tax",
          "shortDescription": "Local sales tax",
          "original": 200,
          "retail": 180,
          "net": 160
        }
      ]
    }
  ]
}
```

### `Booking`

```json
{
  "// ...rest of booking object": "...",
  "pricing": {
    "original": 22000,
    "retail": 20000,
    "net": 18000,
    "currency": "USD",
    "currencyPrecision": 2,
    "includedTaxes": [
      {
        "name": "Sales Tax",
        "shortDescription": "Local sales tax",
        "original": 2000,
        "retail": 1800,
        "net": 1600
      }
    ]
  }
}
```

### `BookingUnitItem`

```json
{
  "// ...rest of booking unit item object": "...",
  "pricing": {
    "original": 22000,
    "retail": 20000,
    "net": 18000,
    "currency": "USD",
    "currencyPrecision": 2,
    "includedTaxes": [
      {
        "name": "Sales Tax",
        "shortDescription": "Local sales tax",
        "original": 2000,
        "retail": 1800,
        "net": 1600
      }
    ]
  }
}
```

### `Error`

```json
{
  "// ...rest of error object": "...",
  "availableCurrencies": [
    "USD",
    "EUR"
  ],
  "pricing": {
    "original": 22000,
    "retail": 20000,
    "net": 18000,
    "currency": "USD",
    "currencyPrecision": 2,
    "includedTaxes": [
      {
        "name": "Sales Tax",
        "shortDescription": "Local sales tax",
        "original": 2000,
        "retail": 1800,
        "net": 1600
      }
    ]
  }
}
```

### `ExtraPricing`

```json
{
  "// ...rest of extra pricing object": "...",
  "includedTaxes": [
    {
      "name": "Sales Tax",
      "original": 2000,
      "retail": 1800,
      "shortDescription": "Local sales tax",
      "net": 1600
    }
  ]
}
```

### `Gift`

```json
{
  "// ...rest of gift object": "...",
  "pricing": {
    "original": 22000,
    "retail": 20000,
    "net": 18000,
    "currency": "USD",
    "currencyPrecision": 2,
    "includedTaxes": [
      {
        "name": "Sales Tax",
        "shortDescription": "Local sales tax",
        "original": 2000,
        "retail": 1800,
        "net": 1600
      }
    ]
  }
}
```

### `Money`

```json
{
  "// ...rest of money object": "...",
  "includedTaxes": [
    {
      "name": "Sales Tax",
      "original": 2000,
      "retail": 1800,
      "shortDescription": "Local sales tax",
      "net": 1600
    }
  ]
}
```

### `Option`

```json
{
  "// ...rest of option object": "...",
  "pricingFrom": {
    "original": 22000,
    "retail": 20000,
    "net": 18000,
    "currency": "USD",
    "currencyPrecision": 2,
    "includedTaxes": [
      {
        "name": "Sales Tax",
        "shortDescription": "Local sales tax",
        "original": 2000,
        "retail": 1800,
        "net": 1600
      }
    ]
  },
  "pricing": {
    "original": 22000,
    "retail": 20000,
    "net": 18000,
    "currency": "USD",
    "currencyPrecision": 2,
    "includedTaxes": [
      {
        "name": "Sales Tax",
        "shortDescription": "Local sales tax",
        "original": 2000,
        "retail": 1800,
        "net": 1600
      }
    ]
  }
}
```

### `Order`

```json
{
  "// ...rest of order object": "...",
  "pricing": {
    "original": 22000,
    "retail": 20000,
    "net": 18000,
    "currency": "USD",
    "currencyPrecision": 2,
    "includedTaxes": [
      {
        "name": "Sales Tax",
        "shortDescription": "Local sales tax",
        "original": 2000,
        "retail": 1800,
        "net": 1600
      }
    ]
  }
}
```

### `PackageAvailability`

```json
{
  "// ...rest of package availability object": "...",
  "pricing": {
    "original": 22000,
    "retail": 20000,
    "net": 18000,
    "currency": "USD",
    "currencyPrecision": 2,
    "includedTaxes": [
      {
        "name": "Sales Tax",
        "shortDescription": "Local sales tax",
        "original": 2000,
        "retail": 1800,
        "net": 1600
      }
    ]
  },
  "pricingFrom": {
    "original": 22000,
    "retail": 20000,
    "net": 18000,
    "currency": "USD",
    "currencyPrecision": 2,
    "includedTaxes": [
      {
        "name": "Sales Tax",
        "shortDescription": "Local sales tax",
        "original": 2000,
        "retail": 1800,
        "net": 1600
      }
    ]
  },
  "unitPricing": [
    {
      "unitId": "unit_adult",
      "unitType": "ADULT",
      "original": 12000,
      "retail": 10000,
      "net": 9000,
      "currency": "USD",
      "currencyPrecision": 2,
      "includedTaxes": [
        {
          "name": "Sales Tax",
          "shortDescription": "Local sales tax",
          "original": 1200,
          "retail": 1000,
          "net": 900
        }
      ]
    }
  ],
  "unitPricingFrom": [
    {
      "unitId": "unit_adult",
      "unitType": "ADULT",
      "original": 12000,
      "retail": 10000,
      "net": 9000,
      "currency": "USD",
      "currencyPrecision": 2,
      "includedTaxes": [
        {
          "name": "Sales Tax",
          "shortDescription": "Local sales tax",
          "original": 1200,
          "retail": 1000,
          "net": 900
        }
      ]
    }
  ],
  "extraPricing": [
    {
      "extraId": "extra_fast_track",
      "original": 2000,
      "retail": 1800,
      "net": 1600,
      "currency": "USD",
      "currencyPrecision": 2,
      "includedTaxes": [
        {
          "name": "Sales Tax",
          "shortDescription": "Local sales tax",
          "original": 200,
          "retail": 180,
          "net": 160
        }
      ]
    }
  ],
  "extraPricingFrom": [
    {
      "extraId": "extra_fast_track",
      "original": 2000,
      "retail": 1800,
      "net": 1600,
      "currency": "USD",
      "currencyPrecision": 2,
      "includedTaxes": [
        {
          "name": "Sales Tax",
          "shortDescription": "Local sales tax",
          "original": 200,
          "retail": 180,
          "net": 160
        }
      ]
    }
  ]
}
```

### `Pricing`

```json
{
  "// ...rest of pricing object": "...",
  "includedTaxes": [
    {
      "name": "Sales Tax",
      "original": 2000,
      "retail": 1800,
      "shortDescription": "Local sales tax",
      "net": 1600
    }
  ]
}
```

### `Product`

```json
{
  "// ...rest of product object": "...",
  "availableCurrencies": [
    "USD",
    "EUR"
  ],
  "defaultCurrency": "USD",
  "includeTax": true,
  "includedTaxes": [
    {
      "name": "Sales Tax",
      "shortDescription": "Local sales tax",
      "original": 2000,
      "retail": 1800,
      "net": 1600
    }
  ],
  "hidePricingFrom": true,
  "pricingPer": "UNIT",
  "pricingMultiplier": 10.0
}
```

### `Unit`

```json
{
  "// ...rest of unit object": "...",
  "pricingFrom": {
    "original": 22000,
    "retail": 20000,
    "net": 18000,
    "currency": "USD",
    "currencyPrecision": 2,
    "includedTaxes": [
      {
        "name": "Sales Tax",
        "shortDescription": "Local sales tax",
        "original": 2000,
        "retail": 1800,
        "net": 1600
      }
    ]
  },
  "pricing": {
    "original": 22000,
    "retail": 20000,
    "net": 18000,
    "currency": "USD",
    "currencyPrecision": 2,
    "includedTaxes": [
      {
        "name": "Sales Tax",
        "shortDescription": "Local sales tax",
        "original": 2000,
        "retail": 1800,
        "net": 1600
      }
    ]
  }
}
```

### `UnitPricing`

```json
{
  "// ...rest of unit pricing object": "...",
  "includedTaxes": [
    {
      "name": "Sales Tax",
      "original": 2000,
      "retail": 1800,
      "shortDescription": "Local sales tax",
      "net": 1600
    }
  ]
}
```
