ChatBedsDevelopers
Key cards

Key cards

Connect a hotel's key-card system to ChatBeds. ChatBeds asks it for a guest's key at check-in and cancels the key at check-out, through an https address or the bridge on the desk computer.

A hotel keeps its own key-card system: its locks, encoders, licence and the lock company's hotel-system interface. ChatBeds sends that system key requests. At check-in, at the reception kiosk or the desk, it asks for a key valid until check-out. At any check-out, from the dashboard, WhatsApp or the kiosk, it cancels the key.

This page is for lock companies and connector services, and for whoever sets up a hotel's bridge.

Two ways to connect

Where the key-card system isHow ChatBeds reaches it
An https addressIn the lock company's cloud, or behind a connector serviceChatBeds sends each request to the address, signed
The bridgeOn a server in the hotel's own networkA small ChatBeds program on the desk computer asks for requests and passes them on. Nothing at the hotel is opened to the internet

The hotel chooses one in Settings → Reception → Key cards. There is also a test lock, which answers yes to everything, so a hotel can try the whole check-in first.

The request

Every request has the same shape, whichever way it travels:

A key request
{
  "id": "6b1e4f0e-3c55-4a8e-9f61-1f0b8a9c2d10",
  "action": "make",
  "hotel": "Pearl Hotel",
  "room": "101",
  "guest": "Sara B.",
  "valid_from": "2026-10-12T09:30:00+00:00",
  "valid_until": "2026-10-14T07:00:00+00:00",
  "cards": 1,
  "where": "desk",
  "key_ref": null
}
FieldMeaning
idThe request's id. Send it back with the bridge's answer. Use it to ignore a repeat
actionmake a key, cancel one (key_ref says which), or test the connection without a real key
roomThe room's name in ChatBeds, which is usually its number. Map it to the lock's own room if they differ
guestFirst name and the surname's initial only
valid_from, valid_untilWhen the key works: from now until the check-out time on the departure day, in UTC
cardsHow many cards to make, 1 to 4
wheredesk (the encoder at the desk), dispenser (next to the kiosk) or mobile (a phone key, if the system has them)
key_refFor cancel: the reference your system gave when the key was made

The answer

It worked
{ "ok": true, "key_ref": "VL-0007781" }
It didn't
{ "ok": false, "error": "Encoder 2 is offline" }

Give a key_ref for every key made: ChatBeds sends it back to cancel that key. A short, plain error is shown to the hotel's staff, who then make the key by hand. A failed key never stops a check-in.

An https address

ChatBeds sends POST requests with the JSON body and these headers:

Header
Content-Typeapplication/json
ChatBeds-Signaturet=<unix seconds>,v1=<HMAC-SHA256 of "t.body" with the secret, lowercase hex>, as for webhooks
ChatBeds-Key-IdThe request's id
  • The secret starts with cks_ and is shown once when the hotel connects. Refuse any request whose signature doesn't match, or whose t is more than five minutes old.
  • The answer: send it in the same response, within 15 seconds, with status 200. A 4xx or 5xx counts as failed.
  • The address must be public https, and ChatBeds doesn't follow redirects.

The bridge

The bridge is tools/keycard-bridge/bridge.py from ChatBeds. It needs only Python 3.9 or later. It runs on a computer that can reach the key-card system's server.

On the desk computer
CHATBEDS_BRIDGE_TOKEN=ckb_... python3 bridge.py --handler http --target http://127.0.0.1:8090/keys

The token is shown once when the hotel chooses the bridge. Saving the settings again with a new token stops the old one.

Every two seconds, the bridge:

  1. asks GET /api/v1/keycard-bridge/jobs (with Authorization: Bridge ckb_...) for the waiting requests;
  2. hands each request to its handler;
  3. sends the answer to POST /api/v1/keycard-bridge/jobs/{id}.

A request is handed out once. If its answer doesn't arrive within two minutes, it fails and the desk is told.

HandlerPasses each request to
httpA local address, as JSON: the lock company's interface, or a connector program
commandA program, with the request as JSON on its standard input; it prints the answer as JSON
moduleA Python module in handlers/ with handle(request) -> answer, where a brand's own protocol is written
testNobody: it answers yes

Writing a brand's handler

Each lock company gives its hotel-system interface to its partners. Copy handlers/template.py and write handle from that specification:

  • make gives a new key for the room, valid for the times given. A new key normally stops earlier guests' keys for that room.
  • cancel stops the key with key_ref.
  • test proves the connection.

Never log the guest's name.

Brands

BrandSystemsWhat the hotel asks the lock company
SaltoSalto KS (cloud), Salto SpaceTo enable the hotel-system interface, through the cloud or the key server
dormakabaAmbiance, Saflok, CommunityTo enable the hotel-system interface on its server
ASSA ABLOY (VingCard)Visionline, VostioTo enable the hotel-system interface
OnityOnity's encoders and hotel-system interfaceTo enable the hotel-system interface
OthersAny system with a hotel-system interface, or a multi-brand connectorTo enable the interface, or a connector

ChatBeds writes the message to the lock company for the hotel, in Settings → Reception → Key cards. The lock company usually charges for its interface.

Building something?

On this page