Authentication

API keys

The API authenticates the partner, not the traveller. One credential — an API key — identifies your account, decides what you may call, and is the thing every invoice line traces back to.

Sending a key

Pass the key as a bearer token on every request. There is no session, no login call and no token exchange.

HTTP
GET /v1/account HTTP/1.1
Authorization: Bearer vcb_live_7Kq2xY…
Accept: application/json

For the WebSocket at /v1/stream, browsers and most clients cannot set headers on the handshake, so the key travels in the subprotocol instead:

WebSocket handshake
Sec-WebSocket-Protocol: vcb, vcb_live_7Kq2xY…

Keys never leave your servers

A key is a bearer credential for your whole partner account: it can search, book, cancel and spend against your credit. It does not belong in a browser bundle, a mobile app, a mobile config file, a public repository or a support ticket. If one leaks, revoke it in the portal — revocation takes effect in under a second.

Two environments

Live keyTest key
Prefixvcb_live_…vcb_test_…
HostLive base URLSandbox base URL
SuppliersReal bookings, real moneyNever contacted
Search quotaCounted and billableFree, never counted
Forced failuresNot availableSix triggers, see sandbox

The two are not interchangeable: a test key on the live host and a live key on the sandbox host are both rejected with 401. That is deliberate — a deployment that has the wrong key configured should fail on its first call, not on its first real booking.

Scopes

Every key carries an explicit list of scopes, and every endpoint requires one. A key with no scope for a route is rejected before the request reaches any supplier.

Scopes are named <resource>:<action>. The resources follow the product areas — hotels, flights, esim — plus account for your own account and ledger, and webhooks for endpoint management. The actions are read and write:

ActionCovers
readSearching, retrieving offers and rates, reading bookings, reading usage and ledger entries.
writeCreating bookings and orders, cancelling, modifying, and deleting customer records.

The scopes actually granted to a key are shown on the key in the portal, and a rejected call names the one it was missing, so you never have to guess:

403 Forbidden
{
  "error": {
    "type": "missing_scope",
    "message": "This key does not have the hotels:write scope.",
    "requestId": "req_01JD8Z…",
    "docUrl": "…/docs/authentication"
  }
}

Grant the narrowest set that does the job. A key used only by a price-comparison page should not be able to book, and a key used by a nightly reconciliation job should not be able to cancel.

IP allow lists

Each key can be pinned to a list of source addresses or CIDR ranges. A request from anywhere else is refused regardless of how valid the key is. This is the cheapest mitigation there is for a leaked credential, and it costs nothing if your egress addresses are stable.

Leave the list empty and the key is accepted from anywhere. If your egress is dynamic, prefer short-lived keys and rotation over a wide range.

Rotation

Keys are stored as a SHA-256 hash. We cannot show you an existing secret, recover one, or read one out of a log — the plaintext exists exactly once, in the response that created it. Store it in your secret manager at that moment.

  • Rotating a key issues a new secret and gives the old one an expiry in the near future, so both work while you roll out. Deploy the new secret, confirm traffic has moved using the key's last-used timestamp, then let the old one lapse or revoke it early.
  • Revocation is immediate: the gateway caches the key catalogue for 60 seconds but is invalidated on revoke, so a killed key stops working in under a second.
  • Use separate keys per system — checkout, back office, batch jobs. One compromised component then costs you one rotation, not a coordinated one across your estate.
  • Every key operation is written to an audit trail on your partner account, with the portal user who performed it.

Travellers

Your travellers do not have Vacabee accounts and never authenticate with us. You identify them with your own stable identifier in the X-Partner-Customer-Ref header; we keep the mapping so bookings, modifications and cancellations for the same traveller line up.

Use an opaque, stable reference — not an email address, not a name. When a traveller exercises a deletion request, DELETE /v1/customers/{ref} removes the traveller record on our side.

NextIdempotencyWhy every POST needs an Idempotency-Key, and how replay works.