Capability Documentation

JetSetGo OCTO API — Reseller & OTA Distribution Integration

JetSetGo exposes its catalogue, availability and booking machinery to resellers through the OCTO standard — the tours and activities industry's open API specification. One route family, two negotiated modes:

Mode Capability header Status
Strict OCTO Core Header present, no token Production. Use for products published on Strict-enabled profiles.
JetSetGo Expanded OCTO jetsetgo/expanded-booking-v1 Preview. Wire contract and routes exist; no product translation is certified yet, and requests needing one fail closed.

Strict OCTO Core is the supported integration path today, deployed and validated in production across real operator catalogues: discovery, availability with exact cutoff projection, held bookings, confirmation through the operator's existing payment terms, retrieval, listing, contact updates and cancellation.

Base URL and contract pin

All operations are served under:

https://api.jetsetgo.world/octo

The implementation follows the official OCTO Core contract at a pinned revision. Do not infer support for an optional OCTO capability merely because the standard defines it — the current Strict release is Core-only, and unknown fields or unsupported parameters fail rather than being ignored. Send no trailing slashes: /octo/products is valid, /octo/products/ returns an OCTO error rather than redirecting.

Authentication

JetSetGo issues a tenant-local API key for each unattended integration. Send it as a Bearer credential, with the OCTO capabilities header present on every request:

Authorization: Bearer jsg_<tenant>_<secret>
Octo-Capabilities:

For JSON requests also send Content-Type: application/json.

Rules worth internalising early:

  • Octo-Capabilities must be present on every request. For Strict Core it carries no token. Some HTTP libraries strip empty headers; sending a comma-only value is normalised to the empty Core set.
  • The key derives tenant, client, channel and exact key ownership. Request payloads cannot override any of them.
  • Keys are not interchangeable: a replacement key for the same client and channel does not automatically gain access to bookings owned by the old key. Preserve the exact key used to create bookings while those bookings need lifecycle management.
  • Mutations require JSON. Unsupported query parameters or body fields are errors, not feature-detection hints.

Keys are provisioned, rotated and revoked through JetSetGo — there is no self-service endpoint.

What the Strict release supports

Supported today:

  • Non-package products represented by valid published OCTO profiles; one-way profiles only.
  • Supplier, Product, Option and Unit discovery.
  • Calendar Availability and Detailed Availability, with the exact booking cutoff instant projected in utcCutoffAt.
  • Create producing a normal ON_HOLD booking.
  • Confirm through the integration's existing on-account treatment.
  • Get and selector-based List of your own bookings.
  • Booking-level contact Update.
  • Cancellation with an empty body.
  • Safe rejection of Extend.

Deliberately outside the current release: return profiles; packages and standalone add-on products; the optional OCTO pricing capability and currency request field; supplier-side card collection; caller-selected hold expiry or booking notes on Create; caller-supplied unit-item UUIDs; reseller references; per-unit contacts; changing Product, Option, Availability or Units after Create; and successful Extend.

Profiles are fail-closed. A draft, archived, invalid, Strict-disabled, return or not-fully-representable profile simply does not appear in the catalogue. An existing booking stays readable from persisted facts even if its profile is later unpublished.

Treat every identifier as opaque

Field Meaning
productId The published OCTO profile UUID. Two profiles over one underlying product are two OCTO Products.
optionId A current, representable fare identity. Always take it from the selected Product.
unitId A deterministic Unit identity derived from certified semantics. Always take it from the Product Option.
Availability id An opaque, mapping-backed identity for one configured selection.
Booking uuid The booking UUID returned by Create.
Unit Item uuid Server-generated booked-ticket identity. Never supply one during Create.

Never parse these values, substitute underlying numeric ids, or reuse an identifier from another Product.

The end-to-end flow

1. Discover

GET  /octo/supplier
GET  /octo/products
GET  /octo/products/{productId}

Read each Product's options, each Option's units, and requiredContactFields. Do not cache profile availability or assume an unpublished Product remains discoverable.

2. Check availability

Calendar gives a date-level view:

POST /octo/availability/calendar

Detailed Availability, called immediately before Create, uses exactly one selector form — a local date range, or a recheck of previously returned availability ids. Mixing the two forms is rejected before any runtime work:

POST /octo/availability

An available row looks like:

{
  "id": "<opaque-availability-id>",
  "localDateTimeStart": "2026-09-06T08:30:00",
  "localDateTimeEnd": "2026-09-06T09:30:00",
  "available": true,
  "status": "AVAILABLE",
  "utcCutoffAt": "2026-09-05T17:00:00Z",
  "openingHours": []
}

utcCutoffAt is the exact instant after which the booking engine will not accept this selection — a read-only projection of the operator's real cutoff, not an approximation. Capacity counts are emitted only when they can be reported truthfully; unprovable states are omitted rather than guessed. Availability creates no inventory hold: it builds an ordinary working cart that Create re-authorises and commits, and unused carts follow normal cleanup.

3. Create an ON_HOLD booking

POST /octo/bookings
{
  "uuid": "11111111-1111-4111-8111-111111111111",
  "productId": "<product-id>",
  "optionId": "<option-id>",
  "availabilityId": "<id-from-detailed-availability>",
  "unitItems": [
    { "unitId": "<adult-unit-id>" },
    { "unitId": "<small-car-unit-id>" }
  ]
}

The entries in unitItems are the requested quantities and must exactly match the units used for the selected availability.

Supplying the top-level uuid is strongly recommended — it is the Create idempotency identity:

  • the same UUID with an equivalent request returns the same booking;
  • reuse with changed Product, Option, Availability or Units conflicts;
  • another API key cannot use the UUID to access or replay the booking;
  • without a supplied UUID, a lost response has no protocol-level replay identity and must not be blindly retried.

Do not send hold-expiry minutes, notes or unit-item UUIDs in this release.

4. Confirm

POST /octo/bookings/{bookingUuid}/confirm
{
  "contact": {
    "firstName": "Test",
    "lastName": "Traveller",
    "emailAddress": "traveller@example.com",
    "phoneNumber": "5550100999"
  }
}

Supply exactly the booking-level contact fields the Product Option requires — currently first name, last name, email address and phone number. Confirm records the server-derived remaining on-account amount and returns CONFIRMED only after the underlying booking is active. Retrying an already-confirmed booking is observation-only and never creates another payment. The integration key must belong to an active agent client with valid payment terms and exactly one eligible on-account payment type; losing that configuration before confirm fails safely, with no partial write.

5. Retrieve, list, update, cancel

GET   /octo/bookings/{bookingUuid}
GET   /octo/bookings?localDate=2026-09-06
GET   /octo/bookings?localDateStart=2026-09-06&localDateEnd=2026-09-08
PATCH /octo/bookings/{bookingUuid}
POST  /octo/bookings/{bookingUuid}/cancel

List requires at least one supported selector (travel date, date range, or supplier reference) with optional product filters, and returns only bookings owned by the exact authenticated key. One historical booking that cannot be represented does not suppress other representable results.

Update (PATCH) supports a non-empty booking-level contact object and nothing else — product, option, availability, units, notes, expiry and receipt changes are unsupported. Cancel takes an empty JSON object, invokes the operator's real cancellation behaviour, and reports the observed state; it invents no separate refund operation. Extend always returns 400 UNPROCESSABLE_ENTITY and performs no write, because no truthful hold-extension operation exists behind it.

Errors and retry safety

Errors use OCTO error bodies with error, errorMessage and locators where the contract permits them:

Error Meaning
BAD_REQUEST Malformed JSON, missing header, wrong selector combination or unsupported body shape.
UNAUTHORIZED Missing, unknown, inactive or expired API key.
FORBIDDEN The authenticated integration may not use this operation.
INVALID_PRODUCT_ID / INVALID_OPTION_ID / INVALID_UNIT_ID Malformed identifier, not in the current Product, or not visible to this integration.
INVALID_AVAILABILITY_ID Stale, completed, foreign or mismatched availability identity.
INVALID_BOOKING_UUID Unknown to this exact key, or a Create UUID was reused incompatibly.
UNPROCESSABLE_ENTITY Valid syntax, unsupported behaviour.
INTERNAL_SERVER_ERROR The outcome could not be proved safely.

Retry rules:

  • Reads (supplier, products, calendar, availability, get, list) may be repeated, remembering that availability can change between calls.
  • Create may be replayed only with the same supplied UUID and an equivalent request.
  • After an uncertain Confirm response, GET the booking first. If it is already CONFIRMED, stop.
  • Never treat a timeout or a 500 as proof that a write did not occur.

Error responses deliberately do not reveal whether another API key owns a presented availability, booking UUID or Create UUID.

JetSetGo Expanded OCTO — protocol preview

Expanded OCTO is negotiated with Octo-Capabilities: jetsetgo/expanded-booking-v1 and exists to expose the booking decisions OCTO Core cannot express: vehicle details and consumption, rooms and cabins, multi-night stays, scoped questions, parking, add-ons. It adds two routes under the same base path:

POST /octo/jetsetgo/context-start
POST /octo/jetsetgo/context-answer

It also defines capability-gated attachments to Calendar, Detailed Availability and Create. The intended sequence mirrors a conversational booking: start an authorised context, render each action from its published answer schema, submit one answer at a time until required actions are complete, then pass the context into availability and Create and continue with the unchanged OCTO lifecycle afterwards.

Current status, stated plainly: no product translation has completed certification, so every Expanded request that needs one fails closed instead of guessing. This section documents the protocol so integrators can plan; it is not an invitation to build a production Expanded client yet. Capability changes arrive only as explicit versioned contract updates — never infer new support from observed behaviour.

Implementation checklist

  • Obtain a dedicated client-bound API key through JetSetGo.
  • Preserve the exact creating key while its bookings need lifecycle management.
  • Always send Octo-Capabilities; send the JSON content type where required.
  • Discover Product, Option and Unit identifiers; never construct them.
  • Check Detailed Availability immediately before Create.
  • Use a fresh canonical UUID for each intended booking; retain the exact Create request for safe replay.
  • Build Unit Items from the exact availability quantities.
  • Supply all required contact fields at Confirm.
  • Treat unknown fields and unsupported capabilities as errors, not feature detection.
  • Store the returned booking UUID and supplier reference.
  • Do not log API keys or full traveller payloads.

The platform domains behind this surface are documented in the MCP module reference: the sellable product catalogue that Published profiles represent, schedules whose services drive availability, cancellation policies invoked by Cancel, and booking channels, the configuration layer an integration key connects through.

For the other surfaces JetSetGo exposes — including an MCP server built for AI agents that mirrors much of this journey conversationally — see AI integrations and APIs. To control which inventory resellers can sell in the first place, see channel management.

See it on your operation

A 30-minute call. We show you the platform with your routes, your fleet, your numbers. No slideshow, no high-pressure sales.

Book a Demo