Travelity OCTO API (1.0.0)

Download OpenAPI specification:

The OCTO 1.0 supplier API Travelity hosts for its resale partners.

Travelity hosts this API for resellers who speak OCTO - the Open Connectivity for Tours, Activities and Attractions standard. It is the supplier side of the protocol: you call us, we answer with our operators' inventory and take bookings against it.

Conformance target: OCTO 1.0. Where the published core specification is silent or where shipping implementations disagree with it, this document describes what Travelity actually sends and accepts. Those places are called out explicitly below. Everything here is generated from, and continuously tested against, the running service.

Getting access

Credentials are issued per supplier connection by Travelity - one Bearer key identifies exactly one operator's inventory on exactly one mount. To set up a connection, or to replace a key that was lost or compromised, contact Travelity at vahagns@bravecrew.io.

Send it on every request:

Authorization: Bearer <your api key>

The two failures are distinguished:

  • 401 UNAUTHORIZED - nothing to authenticate with: no Authorization header, a scheme other than Bearer, or an empty token.
  • 403 FORBIDDEN - a token was presented but matched no active connection on this mount. A key issued for one mount answers 403 on another mount's prefix; it is not a shared credential.

401 is also what an unauthenticated request to an unknown path under the prefix gets - the credential is checked before the route.

Capabilities

OCTO capabilities are negotiated per request. Travelity supports exactly one: octo/pricing. Ask for it with a header:

Octo-Capabilities: octo/pricing

or, if your client cannot set headers, with the _capabilities query parameter. The header wins when both are present. Parsing is case-insensitive and comma-separated, so OCTO/Pricing matches and unknown ids are ignored rather than rejected.

Every successful response carries an Octo-Capabilities response header naming what actually activated - the empty string when nothing did. That header is how you confirm pricing is on; it is set from the same resolution that gates the pricing fields, so a capability can never activate without being acknowledged.

Without octo/pricing, every pricing field is absent - not null, not zero. No other capability (octo/content, octo/pickups, octo/offers, octo/questions, octo/notifications) is implemented.

Products and options

One OCTO product is one Travelity option. productId is the option's identifier in our system, and it is what you will see in every payload and send in every request.

Each product carries exactly one option, with id: "DEFAULT". Travelity models what OCTO calls options as separate products, so there is nothing to choose between. Every request that takes an optionId requires it and it must equal DEFAULT; anything else is INVALID_OPTION_ID and the response names the value you sent.

Products are START_TIME products: they publish departures, never opening hours. allowFreesale is false on every product - a booking always requires an availabilityId obtained from POST /availability first.

Every product listed here confirms instantly. An operator's on-request options, where a person decides whether to accept each request, are not offered on this channel at all. Neither is a private option without a maximum party size: this channel reports a private departure in participants, and that number is what states how many a vehicle holds.

Which maxUnits to trust

Two fields carry a party ceiling, and they answer different questions:

  • Option.restrictions.maxUnits is the operator's per-booking party ceiling, null when none is set. It is a static property of the option and says nothing about any one departure.
  • Availability.maxUnits is authoritative. It is the live per-departure number and is a promise: every value it can name is one that POST /bookings will accept. It is the smaller of the operator's ceiling and what the departure still has free, and on a bracketed rule it never exceeds the highest priced bracket.

On a private option the two are the same number while a vehicle is free, because one booking takes the whole vehicle: Availability.maxUnits is the vehicle's party size, and 0 once none is free.

Option.restrictions.minUnits is the option's minimum party size, null when the operator set no floor, and it is enforced - see Participant bounds.

Availability

POST /availability takes exactly one of three request forms:

  1. localDate - a single day.
  2. localDateStart + localDateEnd - an inclusive range.
  3. availabilityIds - specific departures you already hold ids for.

Sending none, or more than one, is BAD_REQUEST. A range wider than one year (366 days) is BAD_REQUEST. Dates are strict YYYY-MM-DD.

The availability id

An availabilityId is an ISO 8601 local datetime, not an opaque row id:

2026-07-01T09:00:00+04:00

It is the departure's local date and start time with the operator's UTC offset. Do not build one by string concatenation: the product's availabilityLocalStartTimes are normalised to HH:MM ("09:00") while the id carries seconds ("...T09:00:00+04:00"). Ids come from POST /availability, which is the only place they are minted.

What is, and is not, returned

  • A sold-out departure is returned with vacancies: 0 and status: "SOLD_OUT".
  • A departure already inside its booking cutoff is returned, also at vacancies: 0. The row still exists; you simply cannot sell it.
  • A closed departure is omitted entirely.
  • A date the operator has not priced for your channel and currency is omitted entirely - see the next section.

capacity is the departure's own maximum; vacancies is what is genuinely sellable right now. Both are counted in participants, on every option. status is SOLD_OUT at zero vacancies, LIMITED at or below half of capacity, and AVAILABLE otherwise. A departure that runs past midnight has a localDateTimeEnd on the following local date - it never wraps back before its own start.

On a private option one booking takes a whole vehicle, so a sale of any size drops vacancies by the vehicle's party size, and maxUnits is that party size while a vehicle is free and 0 once none is.

POST /availability/calendar collapses the same departures into one entry per local date, summing vacancies and capacity across the day. It is deliberately narrower than POST /availability: no id, no allDay, no maxUnits, no utcCutoffAt. Use it to paint a month; use POST /availability to quote and to obtain ids. Both range dates are required.

Dates we cannot price are not offered

A date this channel cannot put a price on is not returned, and is refused if you name one anyway. Three causes:

Cause Offered? If you reserve against it
No pricing rule covers the date for your channel and currency No UNPROCESSABLE_ENTITY
The operator prices that date per group in brackets (a shape OCTO's unit-item contract cannot express) No UNPROCESSABLE_ENTITY
A tiered rule whose brackets do not reach your party size Yes, but maxUnits is capped to the top bracket and unitPricing is absent for that party UNPROCESSABLE_ENTITY

The practical consequence: you can sell exactly as far ahead as the operator has priced. An operator who has published prices for the next 90 days offers you 90 days here, however much further ahead their schedule runs. Extending the horizon is a pricing change on their side, not a scheduling one.

Pricing

Everything in this section needs the octo/pricing capability negotiated. Without it none of these fields appear at all.

All amounts are integers in the currency's minor unit, with currencyPrecision telling you where the decimal point goes - 2 for most currencies, 0 for JPY, KRW, VND and the other zero-decimal currencies. 10000 at precision 2 is 100.00.

The currency is the one configured on your connection, never the operator's own default. Every product reports it as defaultCurrency, and availableCurrencies always contains exactly that one value. You may send currency on a reservation as an assertion; if it does not match the connection currency the reservation is BAD_REQUEST rather than silently re-quoted.

Every pricing object carries the same three tiers. original and retail always carry the same value: the booking's price in your connection's currency. Nothing you call through this API changes it after reservation. net is null - no wholesale rate is negotiated on this channel. includedTaxes is always []; taxes are not itemised on this channel.

Where pricing appears:

  • Products - defaultCurrency, availableCurrencies, pricingPer, and a pricingFrom on each unit that has a price. A unit with no published price carries no pricingFrom at all, rather than one reading zero.
  • Availability - unitPricing[] when the departure resolves per-unit prices, plus a total pricing object only when your request carried units, since a total needs quantities. A per-group product sends unitPricing: [] with the group total in pricing.
  • Calendar - unitPricingFrom[] and pricingFrom{}, taken from the day's first departure. A calendar gives a "from" price for a date, not a quote for a departure.
  • Bookings - a total pricing on the booking, and a per-item pricing on each unit item.

pricingPer is BOOKING for a product the operator prices per group, and UNIT for everything else. A BOOKING-priced product emits no unitItems[].pricing at all - the group total on the booking is the whole price. It follows how the operator's option is priced, per participant or per group, and does not change from date to date: a product does not price per head on one day and per party on the next.

Tiered prices are resolved before they reach you. OCTO has no bracket concept, so a bracketed rule is flattened to per-unit prices: with units in your request the bracket matching that party is used, so a quote and the reservation that follows it agree; without units the first bracket stands in as a "from" price.

Booking lifecycle

POST /bookings          -> ON_HOLD     (capacity is taken here)
POST /bookings/{uuid}/confirm -> CONFIRMED (tickets are issued here)
POST /bookings/{uuid}/cancel  -> CANCELLED

Holds

A reservation holds capacity for expirationMinutes, clamped into [5, 60]. Out-of-range values are clamped, never rejected - a 0 becomes a 5-minute hold rather than an error. POST /bookings/{uuid}/extend moves the expiry, always measured from now and using the same clamp, so expirationMinutes means one thing everywhere in this API. Only an unexpired hold can be extended.

Booking uuid and idempotency

Send a uuid on a reservation and it becomes the booking's identifier and its idempotency key. Repeating a reservation with the same uuid replays the booking that already exists instead of taking capacity twice - including for two requests racing each other, one of which will replay the other's booking. The key is scoped to the operator behind your key: two different operators may use the same uuid without colliding.

Omit uuid and the booking's own identifier is returned as uuid. Either way, the value you get back is the one to use in every later path.

unitItems[].uuid works the same way: supply one per head and it is echoed on every later read; omit it and we mint one. Unit items keep their ids and their order from the hold through confirmation and cancellation.

Participant bounds

The operator's minimum and maximum party size are enforced when you reserve. The check is on the participant count, not on seats consumed - which matters for a private departure, where a party of any size takes the whole vehicle and the capacity check alone would never notice a party too large for it.

A party outside the bounds is UNPROCESSABLE_ENTITY carrying restrictions: { minUnits, maxUnits } - the same shape the option advertised its bounds in, so you can retry inside them. This is what makes Availability.maxUnits and Option.restrictions.minUnits guarantees rather than hints.

Confirmation

contact is optional on our side, although OCTO 1.0 marks it required. A confirm with no contact - or an empty one - is accepted; the booking then reads back with an all-null contact. Only fullName / firstName / lastName, emailAddress and phoneNumber are stored; country, postalCode, locales and notes are accepted and discarded, and read back as null or []. Per-unit-item contacts are accepted and discarded in the same way.

Confirming is idempotent: a repeat confirm issues no second set of tickets. A repeat carrying a different resellerReference replaces the stored one - the reference is yours and the latest one wins - while one that repeats it, or omits it, changes nothing.

notes behaves the same way. The booking carries the notes sent at reservation; a confirmation that sends notes replaces them, one that omits them leaves them unchanged, and an empty string clears them.

Amendments are not supported

PATCH /bookings/{uuid} always fails. A changed party, date or option is a different sale: cancel and rebook. The booking is loaded first, so an unknown uuid still answers INVALID_BOOKING_UUID rather than an unsupported-operation error, and a known one answers UNPROCESSABLE_ENTITY. Any request body you send is discarded.

Test bookings

testMode is optional on a reservation and echoed on every later read. Test bookings are real bookings - they consume capacity, issue tickets and are visible to the operator like any other booking. There is no auto-cleanup; cancel them when you are done certifying.

Booking status, and how EXPIRED is derived

Status Meaning
ON_HOLD A live reservation, within its expiry
CONFIRMED A sale
EXPIRED A hold that ran out of time
CANCELLED Something somebody cancelled

A hold reads EXPIRED as soon as its expiry passes, and it still reads EXPIRED afterwards. A hold you cancel while it is still live reads CANCELLED, as does any cancelled confirmed booking. An EXPIRED booking is never cancellable.

Cancellation

The cancellation policy does not gate the call. The only guard is the departure date: a booking whose departure day has already passed in the operator's timezone is UNPROCESSABLE_ENTITY, unless you send force: true. Same-day cancellations are allowed. A late cancellation is priced by its refund tier, not refused.

  • cancellable is true while the booking is ON_HOLD or CONFIRMED and its departure day has not passed. EXPIRED and CANCELLED are always false.
  • cancellation.refund is the tier that applied at the moment of cancellation, not at read time - so a booking cancelled well inside a full-refund window keeps reading FULL after its departure passes. A booking that never reached CONFIRMED paid nothing and reads FULL.
  • Cancelling an already-cancelled booking is a successful no-op that returns the booking.

Option.cancellationCutoff, cancellationCutoffAmount and cancellationCutoffUnit come from the operator's cancellation policy: the earliest hours-before-departure at which the policy still refunds something, i.e. the boundary past which it pays nothing. No policy, or no refundable tier, reports 0 / hour. A whole-day figure is rendered in days (24 becomes 1 day). This is not the booking cutoff the departure advertises for sales - that one is Availability.utcCutoffAt.

Errors

Unlike some supplier APIs, this one uses real HTTP status codes. Every business rejection is HTTP 400 with a body of exactly:

{ "error": "INVALID_PRODUCT_ID", "errorMessage": "...", "productId": "..." }

errorMessage is always a single string, never an array. The third property, when present, names what was wrong.

The complete catalogue is the ten codes OCTO 1.0 defines, and nothing else:

HTTP error Extra
400 INVALID_PRODUCT_ID productId
400 INVALID_OPTION_ID optionId
400 INVALID_UNIT_ID unitId
400 INVALID_AVAILABILITY_ID availabilityId
400 INVALID_BOOKING_UUID uuid
400 UNPROCESSABLE_ENTITY restrictions, for a participant-bounds failure only
400 BAD_REQUEST -
401 UNAUTHORIZED -
403 FORBIDDEN -
500 INTERNAL_SERVER_ERROR -

An authenticated request to an unknown path under the prefix answers 404 with error: "BAD_REQUEST" - the OCTO body shape, with the HTTP status that tells you the route does not exist.

Which error you get first

A reservation is validated in a fixed order, so a request wrong in more than one way gets the most specific answer:

  1. the product, option and availability id must resolve - INVALID_PRODUCT_ID, INVALID_OPTION_ID, INVALID_AVAILABILITY_ID;
  2. every unitId must belong to the option - INVALID_UNIT_ID;
  3. the party must sit inside the option's bounds - UNPROCESSABLE_ENTITY with restrictions;
  4. the date must be priceable for that party - UNPROCESSABLE_ENTITY;
  5. the departure must have room - UNPROCESSABLE_ENTITY.

Nothing is written before all five pass. A refused reservation consumes no capacity.

Two 500s that are not the same

A 500 carrying {"error": "INTERNAL_SERVER_ERROR", "errorMessage": "Unexpected error"} is a failure on our side; retry after a short delay. A 500 with any other body shape is a transient platform error; retry, and contact Travelity if it persists.

Supplier

Who you are connected to.

Get supplier details

The operator behind this connection. contact is the operator's support contact, not a booking contact; every field in it is nullable and only email has a value today. endpoint is this mount's own base URL.

Authorizations:
bearerAuth
query Parameters
_capabilities
string
Example: _capabilities=octo/pricing

The same list as the Octo-Capabilities header, for clients that cannot set headers. Ignored when the header is present.

header Parameters
Octo-Capabilities
string
Example: octo/pricing

Capabilities to activate, comma-separated and case-insensitive. Only octo/pricing is supported; unknown ids are ignored. Takes precedence over _capabilities.

Responses

Response samples

Content type
application/json
{
  • "id": "3f1a9e2c-7d45-4b8a-9c61-0e2d4f6a8b10",
  • "name": "Yerevan Walking Tours",
  • "contact": {
    }
}

Products

The inventory this connection may sell.

List every product on this connection

Every active product this connection may sell. Pricing fields appear only with octo/pricing negotiated.

Authorizations:
bearerAuth
query Parameters
_capabilities
string
Example: _capabilities=octo/pricing

The same list as the Octo-Capabilities header, for clients that cannot set headers. Ignored when the header is present.

header Parameters
Octo-Capabilities
string
Example: octo/pricing

Capabilities to activate, comma-separated and case-insensitive. Only octo/pricing is supported; unknown ids are ignored. Takes precedence over _capabilities.

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Get one product

Authorizations:
bearerAuth
path Parameters
productId
required
string
Example: 9f8b1d24-5c3e-4a71-b0d2-6e5f7a8c9012

The product id, as returned by GET /products.

query Parameters
_capabilities
string
Example: _capabilities=octo/pricing

The same list as the Octo-Capabilities header, for clients that cannot set headers. Ignored when the header is present.

header Parameters
Octo-Capabilities
string
Example: octo/pricing

Capabilities to activate, comma-separated and case-insensitive. Only octo/pricing is supported; unknown ids are ignored. Takes precedence over _capabilities.

Responses

Response samples

Content type
application/json
{
  • "id": "9f8b1d24-5c3e-4a71-b0d2-6e5f7a8c9012",
  • "internalName": "Old Yerevan Walking Tour - Morning Departure",
  • "reference": null,
  • "locale": "en",
  • "timeZone": "Asia/Yerevan",
  • "allowFreesale": false,
  • "instantConfirmation": true,
  • "instantDelivery": true,
  • "availabilityRequired": true,
  • "availabilityType": "START_TIME",
  • "deliveryFormats": [
    ],
  • "deliveryMethods": [
    ],
  • "redemptionMethod": "DIGITAL",
  • "defaultCurrency": "EUR",
  • "availableCurrencies": [
    ],
  • "pricingPer": "UNIT",
  • "options": [
    ]
}

Availability

Departures, their remaining capacity and their prices.

Check availability for a date, a range, or specific departures

Send exactly one of localDate, localDateStart + localDateEnd, or availabilityIds. Include units to receive a total pricing object and, on a bracketed rule, the prices for that specific party.

Closed departures and dates the operator has not priced are omitted. A departure inside its booking cutoff is returned at vacancies: 0.

Authorizations:
bearerAuth
query Parameters
_capabilities
string
Example: _capabilities=octo/pricing

The same list as the Octo-Capabilities header, for clients that cannot set headers. Ignored when the header is present.

header Parameters
Octo-Capabilities
string
Example: octo/pricing

Capabilities to activate, comma-separated and case-insensitive. Only octo/pricing is supported; unknown ids are ignored. Takes precedence over _capabilities.

Request Body schema: application/json
required
productId
required
string
optionId
required
string
Value: "DEFAULT"
localDate
string^\d{4}-\d{2}-\d{2}$

A single local date.

localDateStart
string^\d{4}-\d{2}-\d{2}$

First date of an inclusive range. Requires localDateEnd.

localDateEnd
string^\d{4}-\d{2}-\d{2}$

Last date of an inclusive range. At most a year after localDateStart.

availabilityIds
Array of strings non-empty

Specific departures, by the ids a previous call returned.

Array of objects (AvailabilityUnit)

The party you intend to book. Supplying it returns a total pricing object and, on a bracketed rule, the prices for that exact party.

Responses

Request samples

Content type
application/json
{
  • "productId": "9f8b1d24-5c3e-4a71-b0d2-6e5f7a8c9012",
  • "optionId": "DEFAULT",
  • "localDate": "2026-07-01",
  • "units": [
    ]
}

Response samples

Content type
application/json
[
  • {
    }
]

One entry per local date over a range

For painting a calendar. vacancies and capacity are the day's sums across every departure, and the prices are the day's first departure - a "from" figure, not a quote. Both range dates are required, and the range may not exceed a year.

A date shown as open always has a real, priced departure behind it that POST /availability will return an id for.

Authorizations:
bearerAuth
query Parameters
_capabilities
string
Example: _capabilities=octo/pricing

The same list as the Octo-Capabilities header, for clients that cannot set headers. Ignored when the header is present.

header Parameters
Octo-Capabilities
string
Example: octo/pricing

Capabilities to activate, comma-separated and case-insensitive. Only octo/pricing is supported; unknown ids are ignored. Takes precedence over _capabilities.

Request Body schema: application/json
required
productId
required
string
optionId
required
string
Value: "DEFAULT"
localDateStart
required
string^\d{4}-\d{2}-\d{2}$
localDateEnd
required
string^\d{4}-\d{2}-\d{2}$

At most a year after localDateStart.

Array of objects (AvailabilityUnit)

Responses

Request samples

Content type
application/json
{
  • "productId": "9f8b1d24-5c3e-4a71-b0d2-6e5f7a8c9012",
  • "optionId": "DEFAULT",
  • "localDateStart": "2026-07-01",
  • "localDateEnd": "2026-07-31",
  • "units": [
    ]
}

Response samples

Content type
application/json
[
  • {
    }
]

Bookings

Reserve, confirm, read, extend and cancel.

Reserve a departure (creates an ON_HOLD booking)

Takes capacity and returns an ON_HOLD booking. Send one unitItems entry per head - the array's length is the party size.

Supply uuid to make the call idempotent: a repeat returns the same booking without taking capacity twice.

Nothing is written unless the whole request is acceptable; a refusal consumes no capacity.

Authorizations:
bearerAuth
query Parameters
_capabilities
string
Example: _capabilities=octo/pricing

The same list as the Octo-Capabilities header, for clients that cannot set headers. Ignored when the header is present.

header Parameters
Octo-Capabilities
string
Example: octo/pricing

Capabilities to activate, comma-separated and case-insensitive. Only octo/pricing is supported; unknown ids are ignored. Takes precedence over _capabilities.

Request Body schema: application/json
required
productId
required
string
optionId
required
string
Value: "DEFAULT"
availabilityId
required
string

A departure id from POST /availability.

required
Array of objects (ReservationUnitItem) non-empty

One entry per head. Two adults and a child is three entries.

uuid
string <uuid>

Your identifier for this booking, and its idempotency key - repeating it replays the existing booking instead of taking capacity twice. Scoped to your connection's operator.

expirationMinutes
integer

How long to hold. Clamped into [5, 60] rather than rejected, so 0 becomes a five-minute hold. Defaults to the maximum.

notes
string

Free text kept with the booking and echoed on every read. A later confirmation may replace it.

currency
string

Optional assertion. Must equal your connection's currency; a mismatch is BAD_REQUEST rather than a silent re-quote.

testMode
boolean

Marks the booking as a test. It still consumes capacity and issues tickets - cancel it when you are done.

Responses

Request samples

Content type
application/json
{
  • "productId": "9f8b1d24-5c3e-4a71-b0d2-6e5f7a8c9012",
  • "optionId": "DEFAULT",
  • "availabilityId": "2026-07-01T09:00:00+04:00",
  • "unitItems": [
    ],
  • "uuid": "b0a1c2d3-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
  • "expirationMinutes": 60,
  • "notes": "Please meet at the Cascade steps.",
  • "currency": "EUR",
  • "testMode": false
}

Response samples

Content type
application/json
{
  • "id": "7a6b5c4d-3e2f-4a1b-8c9d-0e1f2a3b4c5d",
  • "uuid": "b0a1c2d3-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
  • "testMode": false,
  • "resellerReference": null,
  • "supplierReference": "YOUR-MOUNT-1782292532418",
  • "status": "ON_HOLD",
  • "utcCreatedAt": "2026-06-24T09:15:32.418Z",
  • "utcUpdatedAt": "2026-06-24T09:15:32.418Z",
  • "utcExpiresAt": "2026-06-24T10:15:32.418Z",
  • "utcRedeemedAt": null,
  • "utcConfirmedAt": null,
  • "productId": "9f8b1d24-5c3e-4a71-b0d2-6e5f7a8c9012",
  • "product": {
    },
  • "optionId": "DEFAULT",
  • "option": {
    },
  • "cancellable": true,
  • "cancellation": null,
  • "freesale": false,
  • "availabilityId": "2026-07-01T09:00:00+04:00",
  • "availability": {
    },
  • "contact": {
    },
  • "notes": "Please meet at the Cascade steps.",
  • "deliveryMethods": [
    ],
  • "voucher": null,
  • "unitItems": [
    ],
  • "pricing": {
    }
}

Find bookings by filter

At least one filter is required - resellerReference, supplierReference, localDate, localDateStart or productId. localDateEnd on its own does not count: it bounds a range whose start is missing.

Results are always scoped to your connection. A product mapped to two resellers still lists each booking once.

OCTO 1.0 lists productId and optionId as narrowing parameters; here productId on its own also satisfies the filter requirement.

Authorizations:
bearerAuth
query Parameters
resellerReference
string
Example: resellerReference=VOUCHER-88213

The reference you supplied at confirmation.

supplierReference
string
Example: supplierReference=YOUR-MOUNT-1782292532418

Our order number, as returned in supplierReference.

localDate
string^\d{4}-\d{2}-\d{2}$
Example: localDate=2026-07-01

All bookings departing on this local date.

localDateStart
string^\d{4}-\d{2}-\d{2}$
Example: localDateStart=2026-07-01

First local date of a range.

localDateEnd
string^\d{4}-\d{2}-\d{2}$
Example: localDateEnd=2026-07-31

Last local date of a range. Not a filter on its own.

productId
string
Example: productId=9f8b1d24-5c3e-4a71-b0d2-6e5f7a8c9012

Restrict to one product.

optionId
string
Example: optionId=DEFAULT

Must be DEFAULT when sent.

Value: "DEFAULT"
_capabilities
string
Example: _capabilities=octo/pricing

The same list as the Octo-Capabilities header, for clients that cannot set headers. Ignored when the header is present.

header Parameters
Octo-Capabilities
string
Example: octo/pricing

Capabilities to activate, comma-separated and case-insensitive. Only octo/pricing is supported; unknown ids are ignored. Takes precedence over _capabilities.

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Read one booking

Authorizations:
bearerAuth
path Parameters
uuid
required
string <uuid>
Example: b0a1c2d3-4e5f-4a6b-8c7d-9e0f1a2b3c4d

The booking's uuid - the one you supplied at reservation, or the value the reservation returned if you supplied none. Not the id field.

query Parameters
_capabilities
string
Example: _capabilities=octo/pricing

The same list as the Octo-Capabilities header, for clients that cannot set headers. Ignored when the header is present.

header Parameters
Octo-Capabilities
string
Example: octo/pricing

Capabilities to activate, comma-separated and case-insensitive. Only octo/pricing is supported; unknown ids are ignored. Takes precedence over _capabilities.

Responses

Response samples

Content type
application/json
{
  • "id": "7a6b5c4d-3e2f-4a1b-8c9d-0e1f2a3b4c5d",
  • "uuid": "b0a1c2d3-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
  • "testMode": false,
  • "resellerReference": "VOUCHER-88213",
  • "supplierReference": "YOUR-MOUNT-1782292532418",
  • "status": "CONFIRMED",
  • "utcCreatedAt": "2026-06-24T09:15:32.418Z",
  • "utcUpdatedAt": "2026-06-24T09:22:07.903Z",
  • "utcExpiresAt": null,
  • "utcRedeemedAt": null,
  • "utcConfirmedAt": "2026-06-24T09:22:07.903Z",
  • "productId": "9f8b1d24-5c3e-4a71-b0d2-6e5f7a8c9012",
  • "product": {
    },
  • "optionId": "DEFAULT",
  • "option": {
    },
  • "cancellable": true,
  • "cancellation": null,
  • "freesale": false,
  • "availabilityId": "2026-07-01T09:00:00+04:00",
  • "availability": {
    },
  • "contact": {
    },
  • "notes": "Please meet at the Cascade steps.",
  • "deliveryMethods": [
    ],
  • "voucher": null,
  • "unitItems": [
    ],
  • "pricing": {
    }
}

Amend a booking - not supported

This operation always fails. Travelity prices and seats a sale at creation, so a changed party, date or option is a different sale: cancel and rebook.

The booking is resolved first, so an unknown uuid answers INVALID_BOOKING_UUID and a known one answers UNPROCESSABLE_ENTITY. Any body you send is discarded. It is documented here because OCTO 1.0 defines it and a conformance suite will call it.

Authorizations:
bearerAuth
path Parameters
uuid
required
string <uuid>
Example: b0a1c2d3-4e5f-4a6b-8c7d-9e0f1a2b3c4d

The booking's uuid - the one you supplied at reservation, or the value the reservation returned if you supplied none. Not the id field.

query Parameters
_capabilities
string
Example: _capabilities=octo/pricing

The same list as the Octo-Capabilities header, for clients that cannot set headers. Ignored when the header is present.

header Parameters
Octo-Capabilities
string
Example: octo/pricing

Capabilities to activate, comma-separated and case-insensitive. Only octo/pricing is supported; unknown ids are ignored. Takes precedence over _capabilities.

Request Body schema: application/json
optional
object (BookingAmendmentRequest)

Declared for OCTO conformance. Travelity does not support amendments, so any content is discarded and the call always fails.

Responses

Request samples

Content type
application/json
{ }

Response samples

Content type
application/json
Example
{
  • "error": "UNPROCESSABLE_ENTITY",
  • "errorMessage": "Booking amendments are not supported - cancel and rebook"
}

Confirm a held booking

Turns an unexpired hold into a sale and issues one ticket per unit item. Only a hold can be confirmed; anything else - confirmed, cancelled, expired, or a cancellation that raced this call - answers INVALID_BOOKING_UUID.

Confirming twice is safe and issues no second set of tickets.

Authorizations:
bearerAuth
path Parameters
uuid
required
string <uuid>
Example: b0a1c2d3-4e5f-4a6b-8c7d-9e0f1a2b3c4d

The booking's uuid - the one you supplied at reservation, or the value the reservation returned if you supplied none. Not the id field.

query Parameters
_capabilities
string
Example: _capabilities=octo/pricing

The same list as the Octo-Capabilities header, for clients that cannot set headers. Ignored when the header is present.

header Parameters
Octo-Capabilities
string
Example: octo/pricing

Capabilities to activate, comma-separated and case-insensitive. Only octo/pricing is supported; unknown ids are ignored. Takes precedence over _capabilities.

Request Body schema: application/json
optional
object (ConfirmationContact)

Only fullName / firstName / lastName, emailAddress and phoneNumber are stored. The rest are accepted and discarded.

resellerReference
string

Your booking reference. Sending a different one on a repeat confirmation replaces the stored value; repeating or omitting it changes nothing.

notes
string

Replaces the notes sent at reservation. Omitting the field leaves them unchanged; an empty string clears them.

Array of objects (ConfirmationUnitItem)

Accepted for OCTO conformance. Per-item contacts are not stored.

Responses

Request samples

Content type
application/json
{
  • "contact": {
    },
  • "resellerReference": "VOUCHER-88213"
}

Response samples

Content type
application/json
{
  • "id": "7a6b5c4d-3e2f-4a1b-8c9d-0e1f2a3b4c5d",
  • "uuid": "b0a1c2d3-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
  • "testMode": false,
  • "resellerReference": "VOUCHER-88213",
  • "supplierReference": "YOUR-MOUNT-1782292532418",
  • "status": "CONFIRMED",
  • "utcCreatedAt": "2026-06-24T09:15:32.418Z",
  • "utcUpdatedAt": "2026-06-24T09:22:07.903Z",
  • "utcExpiresAt": null,
  • "utcRedeemedAt": null,
  • "utcConfirmedAt": "2026-06-24T09:22:07.903Z",
  • "productId": "9f8b1d24-5c3e-4a71-b0d2-6e5f7a8c9012",
  • "product": {
    },
  • "optionId": "DEFAULT",
  • "option": {
    },
  • "cancellable": true,
  • "cancellation": null,
  • "freesale": false,
  • "availabilityId": "2026-07-01T09:00:00+04:00",
  • "availability": {
    },
  • "contact": {
    },
  • "notes": "Please meet at the Cascade steps.",
  • "deliveryMethods": [
    ],
  • "voucher": null,
  • "unitItems": [
    ],
  • "pricing": {
    }
}

Cancel a booking

Releases the capacity and, for a confirmed booking, retires its tickets. The cancellation policy does not gate this call - a late cancellation is priced by its refund tier, not refused, and same-day cancellations are allowed.

The one guard is a departure day that has already passed; send force: true to cancel one anyway. Cancelling an already-cancelled booking succeeds and returns it unchanged.

Authorizations:
bearerAuth
path Parameters
uuid
required
string <uuid>
Example: b0a1c2d3-4e5f-4a6b-8c7d-9e0f1a2b3c4d

The booking's uuid - the one you supplied at reservation, or the value the reservation returned if you supplied none. Not the id field.

query Parameters
_capabilities
string
Example: _capabilities=octo/pricing

The same list as the Octo-Capabilities header, for clients that cannot set headers. Ignored when the header is present.

header Parameters
Octo-Capabilities
string
Example: octo/pricing

Capabilities to activate, comma-separated and case-insensitive. Only octo/pricing is supported; unknown ids are ignored. Takes precedence over _capabilities.

Request Body schema: application/json
optional
reason
string

Kept on the booking and echoed in cancellation.reason.

force
boolean

Cancel even though the departure day has already passed.

Responses

Request samples

Content type
application/json
{
  • "reason": "Customer changed plans"
}

Response samples

Content type
application/json
{
  • "id": "7a6b5c4d-3e2f-4a1b-8c9d-0e1f2a3b4c5d",
  • "uuid": "b0a1c2d3-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
  • "testMode": false,
  • "resellerReference": "VOUCHER-88213",
  • "supplierReference": "YOUR-MOUNT-1782292532418",
  • "status": "CANCELLED",
  • "utcCreatedAt": "2026-06-24T09:15:32.418Z",
  • "utcUpdatedAt": "2026-06-25T11:04:18.210Z",
  • "utcExpiresAt": null,
  • "utcRedeemedAt": null,
  • "utcConfirmedAt": "2026-06-24T09:22:07.903Z",
  • "productId": "9f8b1d24-5c3e-4a71-b0d2-6e5f7a8c9012",
  • "product": {
    },
  • "optionId": "DEFAULT",
  • "option": {
    },
  • "cancellable": false,
  • "cancellation": {
    },
  • "freesale": false,
  • "availabilityId": "2026-07-01T09:00:00+04:00",
  • "availability": {
    },
  • "contact": {
    },
  • "notes": "Please meet at the Cascade steps.",
  • "deliveryMethods": [
    ],
  • "voucher": null,
  • "unitItems": [
    ],
  • "pricing": {
    }
}

Extend a hold

Moves the hold's expiry, measured from now and clamped into [5, 60] minutes

  • so expirationMinutes: 0 extends by five minutes rather than expiring the hold on the spot. Omitting it extends by the maximum.

Only an unexpired hold can be extended: a confirmed, cancelled or already-expired booking has nothing left to hold and answers INVALID_BOOKING_UUID.

Authorizations:
bearerAuth
path Parameters
uuid
required
string <uuid>
Example: b0a1c2d3-4e5f-4a6b-8c7d-9e0f1a2b3c4d

The booking's uuid - the one you supplied at reservation, or the value the reservation returned if you supplied none. Not the id field.

query Parameters
_capabilities
string
Example: _capabilities=octo/pricing

The same list as the Octo-Capabilities header, for clients that cannot set headers. Ignored when the header is present.

header Parameters
Octo-Capabilities
string
Example: octo/pricing

Capabilities to activate, comma-separated and case-insensitive. Only octo/pricing is supported; unknown ids are ignored. Takes precedence over _capabilities.

Request Body schema: application/json
optional
expirationMinutes
integer

Minutes from now, clamped into [5, 60]. Omitting it extends by the maximum.

Responses

Request samples

Content type
application/json
{
  • "expirationMinutes": 30
}

Response samples

Content type
application/json
{
  • "id": "7a6b5c4d-3e2f-4a1b-8c9d-0e1f2a3b4c5d",
  • "uuid": "b0a1c2d3-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
  • "testMode": false,
  • "resellerReference": null,
  • "supplierReference": "YOUR-MOUNT-1782292532418",
  • "status": "ON_HOLD",
  • "utcCreatedAt": "2026-06-24T09:15:32.418Z",
  • "utcUpdatedAt": "2026-06-24T09:38:45.102Z",
  • "utcExpiresAt": "2026-06-24T10:08:45.102Z",
  • "utcRedeemedAt": null,
  • "utcConfirmedAt": null,
  • "productId": "9f8b1d24-5c3e-4a71-b0d2-6e5f7a8c9012",
  • "product": {
    },
  • "optionId": "DEFAULT",
  • "option": {
    },
  • "cancellable": true,
  • "cancellation": null,
  • "freesale": false,
  • "availabilityId": "2026-07-01T09:00:00+04:00",
  • "availability": {
    },
  • "contact": {
    },
  • "notes": "Please meet at the Cascade steps.",
  • "deliveryMethods": [
    ],
  • "voucher": null,
  • "unitItems": [
    ],
  • "pricing": {
    }
}