Issue a key, pick a contract, and build against the two-phase booking you already understand.
Short answer
Go to API keys and issue one, copying the secret immediately because it is shown once. Then choose a contract: OCTO if you have integrated an OCTO supplier before, Distribution v2 if you are coming from a BeMyGuest-shaped integration. Both serve the same inventory at the same rates through the same two-phase booking you already use in the panel.
Issue a key
API keys, then Issue an API key. Choose sandbox while you build, and which products the key exports. The secret appears once, so store it before you navigate away.
Choose a contract
OCTO or Distribution v2. Pick the one closest to an integration you have already built.
List products and read one back
Prove authentication and the shape of the data before building anything on top of it.
Book with a sandbox key and let it expire
Watch the hold appear and release on your sandbox wallet's ledger. The booking is flagged as a test and never reaches the operator.
Handle webhooks idempotently
You will receive some events twice. Key on the booking reference.
Everything you learned in the panel transfers. The API is the same system with a different door.
We expose the same inventory through two API shapes, and this is a convenience rather than a difference in what is for sale. Same products, same rates, same availability, same wallet.
| Contract | Choose it if | Shape |
|---|---|---|
| OCTO | You have integrated an OCTO supplier before, or you are building fresh | Supplier, product, option, unit, availability, booking. Capability negotiation by header. |
| Distribution v2 | You already consume a BeMyGuest-shaped API | Product, product type, ticket types, dated price lists. |
If neither is familiar, take OCTO. It is an open industry standard, so the work you do reaches other suppliers too rather than being specific to us.
API keys, then Issue an API key. Name it for what will use it.
The secret is shown once under a heading that says Copy this now. We keep a hash and genuinely cannot recover it. Lose it and you revoke and reissue, which takes seconds.
Pick sandbox while you are building. A sandbox key has a vt_test prefix and books the same catalogue at the same rates, but everything it creates is flagged as a test and stays off operators' manifests and settlement. It pays from a sandbox wallet of play money that is filled to $1,000,000 and topped up whenever it runs low, so your real balance is never touched; Wallet, then Sandbox, shows its ledger. Going live is issuing a second key with a vt_live prefix and swapping it in; no URLs or payloads change.
Sandbox bookings hold real seats
The flag keeps them away from the operator's paperwork, not away from their capacity. A confirmed test booking sits on a real departure until something cancels it, so let your reservations expire instead of confirming them, and clean up any you do confirm.
Every key is set to export one of three things: all products, our own operators' products, or the products we resell from partner platforms. Choose when you issue the key, and change it at any time with Change in the Products column. The key never sees anything else: not in the catalogue, not by id, not to book.
Our own operators' products can be narrowed further, to all operators, one operator, or several you pick from a list. A key narrowed to some operators is told which by whoami on OCTO and config on v2, and the supplier list shows those alone. Operators who join later are added only to keys set to all operators.
Two storefronts, two keys
Selling one operator's tours on a dedicated site and everything on your main one is two keys with two settings, rather than filtering in your own code.
OCTO sends optional feature sets only when you ask for them, through a header listing the capabilities you support. Pricing, content, questions, pickups and cancellation are each their own capability.
Ask for what you can actually render. Requesting everything and discarding most of it makes payloads larger and your integration slower for no benefit, and it makes your own logs harder to read when something goes wrong.
Identical to the panel, which is the point.
Send an idempotency key on every create
Networks time out after the server has already acted. Without an idempotency key your retry creates a second booking and holds a second set of funds. With one, the retry returns the original booking. This is the single highest-value thing in an integration and it takes an afternoon.
Availability is live. Do not cache it for a day and sell against the cache.
A workable pattern for most agencies: cache the catalogue and content for hours, since descriptions and photos rarely move, and query availability and prices in real time at the moment someone is choosing a date. That keeps your pages fast without ever selling a seat that is gone.
Subscribe so cancellations and operator-side changes reach you rather than waiting to be discovered.
Two rules, and they are the same two that make every webhook integration work.
The full reference, with every endpoint and payload, is on the developer hub. This page is the orientation.
OCTO unless you already consume a BeMyGuest-shaped API, in which case Distribution v2 will be less work. The inventory and rates are identical either way.
Yes. Issue a sandbox key rather than a production one and it books the real catalogue, so you exercise the code path you will ship. Those bookings are flagged as tests and never reach an operator's manifest or settlement. They are paid from your sandbox wallet, not your real balance, but they do hold real seats, so let reservations expire rather than confirming them.
Yes. One wallet, one set of bookings, both surfaces reading the same records.
Generous enough that a well-behaved integration never meets them. Cache content, query availability live, and you will be fine.
Yes. Set it to our operators' products, then choose one operator or several. It sees nothing else, and you can change the choice later without issuing a new key.
No. Same rates as the panel. The channel does not change the price.