The booking API for agents.

Rooms, vehicles, equipment, appointments — anything with a calendar and a count. Tendzin holds the availability, keeps it correct when everything writes at once, and hands it over plain HTTP to a client that can get its own credential and never needs to ask a human for one.

one request to an account and a token
curl -X POST https://virginia.tendzin.com/account/new \
  -H 'accept: application/json'
The primitive

A range, a count, and a total.

That is the whole model. A resource is a stretch of time at day or minute granularity. Every point in it carries how many are taken and how many exist. A booking is an increment, a cancellation is a decrement, and a change in capacity is a flatten — which sets the total to a new number without disturbing what is already booked against it.

Because the operations are deltas rather than writes, two agents booking the same week at the same moment produce two bookings — not one, and not a lost update.

GET /range/day/{id}/inventories

count

total − count

M

T

W

T

F

S

S

M

T

W

T

F

S

S

M

T

W

T

F

S

S

One resource, twenty-one days. Every day carries a count and a total, and a booking is an increment on a range rather than a row you have to write for each date in it.

What goes in it

If it can be counted and it happens at a time, it fits.

Tendzin does not know what a hotel is. It knows about ranges and numbers, which is why the same API runs a twelve-room guesthouse, a van fleet and a clinic's appointment book without any of them being a special case.

Hotels and rooms

Twelve rooms, three room types, a calendar for each. Availability is a count held against a total, so an overbooking is a number leaving its range — not a race you hoped to win.

Hire and rental

Vans, bikes, cameras, plant. Day granularity when a hire is measured in nights, minute granularity when the same van goes out twice before lunch.

Appointments and staff

One resource per practitioner, per chair, per bay. Ask for the stretches that still have room and you get bookable windows back, not a list of slots to reassemble.

Equipment and shared space

Meeting rooms, test rigs, studio time, charge points. What you are booking does not have to be a room. It only has to be countable.

Tickets and capacity

Tours, classes, tables, sessions. When capacity changes you flatten the total to its new number, and everything already booked against it stays booked.

Calendars and syndication

Feed a channel manager, a marketplace and your own front end from one set of numbers, instead of reconciling three that disagree by Tuesday.
Built for agents

An API that does not assume there is a person on the other end.

Most booking systems were built for a browser and grew an API later. It shows: sign-up needs an inbox, credentials need a dashboard, and errors are sentences. Tendzin starts from the other end.

Sign-up is a request

POST /account/new answers with a working token. No email, no form, no waiting on a person to approve something at 3am — which is when your agent is usually working.

Two credentials, on purpose

The token authorizes use of the service. A second factor authorizes changes to the credentials themselves. A token that leaks can act as you — and cannot mint another, or stop you revoking it.

Writes are events on a range

Booking eleven nights is one increment against one range, not eleven rows you hope all landed. Send a tendzin-transaction-id and a retry after a timeout is safe.

Errors carry codes

Every failure is the same shape with a code to branch on — invalid_token, unknown_token, rate_limited. Nothing has to pattern-match on English prose that may be reworded.

Answers shaped for a decision

Ask for contiguous inventories with total-minus-count-gte=1 and you get the runs of time that can still take a booking. The stitching happens server-side.
Three requests in

Sign up, open some inventory, take a booking.

No SDK required. The whole surface is a handful of routes that speak JSON, and everything below runs as-is once you have replaced the token. Four nodes answer those routes — sydney.tendzin.com, virginia.tendzin.com, eemshaven.tendzin.com and singapore.tendzin.com — and an account belongs to whichever one you signed up against, so pick the near one and keep the hostname.

01 — get a credential

bash
curl -X POST https://virginia.tendzin.com/account/new \
  -H 'accept: application/json'

02 — create a resource and open it

bash
# a resource is a calendar with a count and a total
curl -X POST https://virginia.tendzin.com/range/day \
  -H "authorization: Bearer $TOKEN" \
  -H 'accept: application/json'

# open twelve rooms across the season
curl -X PATCH https://virginia.tendzin.com/range/day/$ID \
  -H "authorization: Bearer $TOKEN" \
  -H 'accept: application/json' \
  -H 'content-type: application/json; charset=utf-8' \
  -d '{"events":[{"column":"total","operation":"flatten","delta":12,
        "range":{"lower":"2026-09-01","upper":"2027-03-31"}}]}'

03 — find availability and book it

bash
# what is still bookable, from today onwards
curl -G https://virginia.tendzin.com/range/day/$ID/contiguous-inventories \
  -H "authorization: Bearer $TOKEN" -H 'accept: application/json' \
  -d upper-range-gte=2026-09-01 -d total-minus-count-gte=1

# take one room for three nights — both ends are included, so the
# last night is the 16th, not the checkout date
curl -X PATCH https://virginia.tendzin.com/range/day/$ID \
  -H "authorization: Bearer $TOKEN" \
  -H "tendzin-transaction-id: $(uuidgen)" \
  -H 'accept: application/json' \
  -H 'content-type: application/json; charset=utf-8' \
  -d '{"events":[{"column":"count","operation":"increment","delta":1,
        "range":{"lower":"2026-09-14","upper":"2026-09-16"}}]}'