Contact

Your site shows it. Kai takes it.

The calendar and the booking form are drawn by your site, in your own design. Kai holds the guest register, the statutory disclosure of terms, the cancellation rules and the card payment.

01 Four endpoints

GET /api/calendar
Availability and prices
POST /api/quote
Quote (total, and the cancellation tiers)
POST /api/book
Booking (accepts Idempotency-Key)
GET /api/booking/:id
Look up a booking

These go through the same path as the screens. The pricing and inventory rules are not kept in two places. If they were, fixing only one would quietly create a case where the screen refuses but the API accepts — and because it moves money and inventory, nobody would notice until an invoice went out.

02 We never flatten “not available” into one answer

Every refusal carries a reason, and the dates it applies to.

available
Can be sold
occupied
Sold out. Normal
unpriced
No price entered. Sellable once the property fixes it
ambiguous
Two plans of equal priority both match
closed
Deliberately closed
overbooked
Double booking. Not rounded down to zero

Some off-the-shelf booking systems return “no availability” for a missing price and for a full house alike. The caller cannot tell them apart, so a price the property forgot to enter looks to the guest like a full house. We keep them separate, so your site can say “please enter a price” instead.

03 How it fits together

For now we assume you call it from your server. We do not send CORS headers, so it cannot be called from the browser directly. Sites with a backend — WordPress, for example — are what this is for.

The only moment the visitor leaves your site is when they enter their card. That is the same experience as any other payment page, and moving to a separate domain tends to reassure people rather than worry them. Kai's side has selectable templates, so the colours and the typeface match.

Whether to allow direct calls from a static site is still under consideration. If you need it, please say so when you get in touch.

04 Every refusal comes with something you can do

A reason on its own does not tell the caller what to do next. Kai sorts every reason into one of six classes.

input
What you sent is wrong. Fix it and send again
state
Sending it again will never work. Full, unpriced, expired, and so on
retry
It was only busy. One more try will go through
auth
A permissions problem
payment
A problem on the payment side
internal
A problem on our side

We do not mix retry and state. Mixing them means retrying, forever, a request that can never succeed. Branch on the class, not on the wording.

POST /api/book accepts Idempotency-Key. The header name follows the payment providers. Sending it twice does not create two bookings.

05 The guest register cannot be handed to your site

We do not offer a “payments only” arrangement. There are three reasons.

  • The register feeds the pricing. Child rates are banded by age, so without it the quote cannot be calculated at all — before we even get to the law.
  • The way it goes wrong is unusual, and it looks correct. A passport number is required not from “foreign nationals” but from foreign nationals with no address in Japan. Get that backwards and the screen still works perfectly, while the law is being broken.
  • The three-year retention, and the record of who looked at what, both disappear. They go when the site is next rebuilt.