Panion Docs

API

Quick book API (restricted)

A restricted API for approved integration clients to sell Panion tours at a desk and book them after payment.

Restricted access.

The Quick book API is not public. Only Panion-approved integration partners can use it, with a key Panion issues. Requests without such a key are refused. To ask for access, contact Panion at hello@panion.travel.

The Quick book API lets an approved integration client sell Panion tours at a desk or counter: list the tours its terminal can sell, quote a sale, take payment with the payment provider, then book. Panion derives the operators and tours from the terminal; the client never names a partner or merchant.

Main path: GET /tours, GET /tours/{activityId}/slots, POST /quote (holds nothing), take payment following the cart line's payment instructions with the sale reference as the payment's reference, then POST /book. Holding seats with POST /reserve is optional, for scarce departures.

Money is integer minor units with an ISO 4217 currency. Departure times are local wall-clock times with an IANA time zone.

Base URL: https://www.panion.travel/api/quickbook/v1. Machine-readable: https://www.panion.travel/api/quickbook/v1/openapi.json (OpenAPI 3.1).

Endpoints:

  • GET /api/quickbook/v1/tours: List the tours this terminal can sell on a day.
  • GET /api/quickbook/v1/tours/{activityId}/slots: Start times and guest prices for a tour on a day.
  • POST /api/quickbook/v1/quote: Quote a sale and get the cart line.
  • POST /api/quickbook/v1/reserve: Optional: hold the seats of a quoted sale while the guest pays.
  • DELETE /api/quickbook/v1/reserve/{holdRef}: Optional: release a hold.
  • POST /api/quickbook/v1/book: Book a paid sale.
  • GET /api/quickbook/v1/sales/{reference}: Status of a sale.
  • GET /api/quickbook/v1/sales/{reference}/ticket: Reprint the ticket of a confirmed sale.

Authentication

Every call sends the key as Authorization: Bearer pqb_live_... (test keys: pqb_test_...) and the id of the payment terminal in the Quickbook-Terminal header. Panion issues the key and binds it to at least one terminal; a call naming a terminal the key is not bound to is refused. Never put the key in a URL: a key in the query string is refused.

Errors

Errors answer with a JSON body {"error": {"code", "clerkMessage", "reference"?}}, an X-Request-Id header and Cache-Control: no-store. Branch on code; show clerkMessage to the person at the desk.

  • 409 sold_out: Not enough seats left on this departure.
  • 409 price_changed: The live price differs from the quote, and the quote is past validUntil. From quote: a guest type the tour does not sell (read the slots again).
  • 503 provider_unavailable: The tour operator's booking system did not answer. Try again in a moment.
  • 410 hold_expired: The seat hold ran out.
  • 422 hold_not_supported: This tour's booking system cannot hold seats. Carry on without reserve: take payment and call book.
  • 403 terminal_not_registered: The terminal in the Quickbook-Terminal header is not registered, not active or not bound to this key. A missing or malformed header answers 400 with this code.
  • 403 tour_not_sellable_here: This terminal cannot charge for this tour's operator, so it cannot sell it.
  • 422 phone_required: This tour needs the guest's phone number.
  • 422 phone_rejected: The tour operator did not accept the phone number.
  • 422 payment_not_found: Panion cannot find this payment at the payment provider. Nothing was booked.
  • 409 payment_mismatch: The payment does not match the sale (amount, currency, merchant, reference or terminal). Nothing was booked, nothing is refunded automatically, and Panion is alerted.
  • 409 duplicate_payment: The sale is already paid with a different payment. The second payment is refunded.
  • 409 provider_refused: The tour operator refused the booking.
  • 401 unauthorized: The Quick book key is missing, not valid, expired or revoked, or was sent in the URL. Answers with WWW-Authenticate: Bearer realm="panion-quickbook".
  • 429 rate_limited: Too many requests from this terminal: 60 writes, 60 books and 300 reads per minute. Retry-After says when to try again.
  • 400 invalid_request: The body or query does not validate (a missing field, a bad date or number).
  • 404 not_found: No such sale or hold for this terminal: the reference is unknown or belongs to another terminal.

When book fails after the guest has paid, it answers 200 with status: "failed", the reason (one of the codes above), moneyReturned and a clerkMessage: the payment is refunded automatically.

Sale statuses (GET /sales/{reference}): quoted, held, expired, booking, confirmed, failed.

Limits

Rate limits per terminal per minute: 60 writes (quote, reserve, release), 60 books (book, its own budget so quotes never crowd out a paid sale) and 300 reads (tours, slots, sales). Past a limit: 429 rate_limited with Retry-After.

Endpoints

The OpenAPI 3.1 document is at /api/quickbook/v1/openapi.json.

On this page