Skip to content
yaReserva

Search the site

Go to

Searches the 78 features, the 36 guides, the documentation and the frequently asked questions.

Book

Integration

Door locks

For whoever builds the bridge between yaReserva and a hotel’s lock system. Here we are the caller: you expose three endpoints and verify our signature.

How it works

yaReserva does not run locks. What it does is notify the hotel’s bridge at three moments, and the bridge talks to Salto KS, TTLock, Dormakaba/Saflok, Assa Abloy Vostio or whichever system is installed.

MomentWhat we ask for
Check-inIssue a key for the room, valid until check-out time.
Room moveRevoke the key for the room being left and issue one for the new room.
Check-outRevoke the booking’s live keys.

The front desk can also issue an extra key or revoke one from the booking screen.

Rule: If your bridge fails, the front desk carries on

Check-in, check-out and room moves go ahead even when there is no key. The front desk sees a warning and can retry from the booking. A bridge that is down cannot leave a guest waiting at the counter.

Setting up the connection

The hotel creates the connection in its panel, under Settings → Locks. It picks a property, the “Webhook bridge” type and your bridge’s base URL, which must be https and resolve to a public IP. There it receives, once and only once, the credential pair.

ValueExampleUse
keyIdyrlock_3f9a1c0b7d2e4a6f8b0c1d2ePublic. Travels in every request we make to you.
secretyrlock_sk_9c1f… (64 hex)Secret. Used to verify the signature. Never travels inside the requests.

Rule: The secret is shown only once

The panel shows it when the connection is created and when it is rotated, and never again. The hotel can rotate it whenever it wants; the previous one stops working immediately, so your bridge must be able to change it without a deploy.

Next, the hotel maps each room to the id of its lock in the provider’s system, the “lockId”. That is what we send you so you know which door to open.

Note: There is also the Manual type

It calls nobody. The front desk encodes the card on its own encoder and yaReserva simply notes who has a key and until when. It is for hotels whose lock system has no way to integrate.

How to verify our requests

All three calls are POST with Content-Type: application/json to your base URL plus a path. They all carry the same headers.

http code
X-YR-Lock-Key:       <keyId>
X-YR-Lock-Timestamp: <segundos Unix, UTC>
X-YR-Lock-Signature: sha256=<hex(HMAC-SHA256(secret, timestamp + "." + cuerpo))>
User-Agent:          yaReserva-Locks/1
  1. Look up the secret by X-YR-Lock-Key.
  2. Reject if the timestamp differs from your clock by more than five minutes. Sync with NTP.
  3. Compute the HMAC over the exact bytes of the body you received, without re-serializing the JSON, and compare in constant time.
  4. Answer 401 if anything is off, without processing anything.
Verification in Node.js
const crypto = require('crypto');

function verificar(req, rawBody, secret) {
  const ts = req.headers['x-yr-lock-timestamp'];
  if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false;
  const esperada =
    'sha256=' +
    crypto.createHmac('sha256', secret).update(`${ts}.`).update(rawBody).digest('hex');
  const recibida = req.headers['x-yr-lock-signature'] || '';
  return (
    recibida.length === esperada.length &&
    crypto.timingSafeEqual(Buffer.from(recibida), Buffer.from(esperada))
  );
}
To test your bridge by hand
SECRET=yrlock_sk_...
BODY='{"keyId":"yrlock_3f9a1c0b7d2e4a6f8b0c1d2e"}'
TS=$(date +%s)
SIG=$(printf '%s.%s' "$TS" "$BODY" | openssl dgst -sha256 -hmac "$SECRET" -hex | sed 's/^.* //')

curl -X POST https://puente.hotel.mx/locks/ping \
  -H "Content-Type: application/json" \
  -H "X-YR-Lock-Key: yrlock_3f9a1c0b7d2e4a6f8b0c1d2e" \
  -H "X-YR-Lock-Timestamp: $TS" \
  -H "X-YR-Lock-Signature: sha256=$SIG" \
  --data-binary "$BODY"

Careful: Keep the raw body before parsing it

Most frameworks parse the JSON and throw the original bytes away. If you sign over the re-serialized object, the signature stops matching the moment key order or a space changes. Configure your server to keep the raw body on these routes.

Issue a key

POST{base}/issue

We call it at check-in, on a room move, and when the front desk asks for an extra key.

What we send you

NameTypeRequiredDescription
referenceUUIDYesOur id for the key. Use it as the idempotency key: if it arrives twice, return the same key instead of issuing another.
lockIdstringYesWhatever the hotel put in that room’s mapping.
roomNumberstringYesThe room number, for your records.
guest.namestringYesThe guest’s name.
guest.emailstringNoMay be absent. It is there to send a mobile key and must not be kept for anything else.
guest.phonestringNoSame as the email: may be absent, and only for the mobile key.
validFromISO 8601YesWhen it starts working. In UTC, RFC 3339.
validUntilISO 8601YesNever goes past the departure day at the hotel’s check-out time, in its own time zone.

Request

json code
{
  "reference": "7b0c5d2e-1f3a-4c6b-9d8e-2a1b3c4d5e6f",
  "lockId": "SALTO-204",
  "roomNumber": "204",
  "guest": { "name": "Ana Ruiz", "email": "ana@correo.mx", "phone": "+525512345678" },
  "validFrom": "2026-11-20T21:04:00Z",
  "validUntil": "2026-11-22T18:00:00Z"
}

Response

What we expect back: 200 or 201
{
  "externalId": "K-889123",
  "pinCode": "482913",
  "mobileKeyUrl": "https://llave.proveedor.com/k/889123"
}

What you return

NameTypeRequiredDescription
externalIdstringYesThe key’s id in your system, up to 200 characters. It is what we send you when revoking.
pinCodestringNoKeypad PIN, up to 32 characters. We show it to the front desk once and only keep its last four digits.
mobileKeyUrlstringNoMust be https. It is shown to the front desk to share with the guest.

Careful: Without externalId, we treat it as failed

If the response has no externalId, or carries a mobileKeyUrl that is not https, we treat it as failed and send you a revoke with the externalId if there was one. Always return the id, even if you resolve the key later.

Revoke a key

POST{base}/revoke

We call it at check-out, on a room move, and when the front desk revokes by hand.

What we send you

NameTypeRequiredDescription
externalIdstringYesThe id you returned when you issued the key.

Request

json code
{ "externalId": "K-889123" }

Response

What we expect back
200 OK   · la llave ya no abre
204      · lo mismo, sin cuerpo
404      · cuenta como revocada: esa llave ya no existe en tu sistema

Revoking twice must be harmless. We read a 404 as success, not as an error: if the key does not exist, it certainly does not open.

Test the connection

POST{base}/ping

What the “Test connection” button in the hotel’s panel runs. Answer 200 if the signature is valid and your bridge can reach the lock system.

What we send you

NameTypeRequiredDescription
keyIdstringYesThe public key of the connection being tested.

Request

json code
{ "keyId": "yrlock_3f9a1c0b7d2e4a6f8b0c1d2e" }

Answer 200 only if you genuinely reach the lock system. A ping that always says yes leaves the hotel believing everything is fine until the first check-in.

Errors

Any response outside 2xx — except the 404 on revoke — is a failure. If you send a JSON body with “message” or “error”, we show it to the front desk trimmed to 200 characters. Do not put personal data or secrets in that text.

An error the front desk can use
{ "message": "cerradura 204 sin batería" }
SituationWhat we do
No answer within 10 seconds, TLS error or refused connectionFailure, and a warning to the front desk.
A 3xx redirectFailure. We do not follow redirects.
A 4xx or a 5xxFailure, with your “message” on screen.
A body over 64 KB or invalid JSONFailure.

Retries

Rule: We do not retry on our own

That way a slow bridge does not block the front desk and duplicate keys are avoided. Whoever decides to retry is the front desk, from the booking.

  • Failed check-in: the guest goes in anyway and the front desk sees the LOCK_SYSTEM_ERROR warning. It retries with “Issue key” from the booking. Each retry carries a fresh reference; if your system had already issued the previous one, it stays alive until its validUntil.
  • Failed check-out: the guest leaves anyway. The key stays marked active until the front desk revokes it or its validUntil arrives, which is check-out time.
  • Failed manual revoke: we hand the error back. The front desk can force the revocation, for instance if the card was destroyed. In that case we note it as revoked alongside your system’s error, and the lock may keep opening until validUntil.
  • Room move: we revoke the old key first and then issue the new one. If the revocation fails, we issue anyway and warn.

When your system has its own retry towards the lock — a gateway with no network, say — answer 2xx as soon as you accept the order and resolve it afterwards. All we need is the externalId.

Security

  • We only call https URLs that resolve to public IPs. Private, loopback, link-local and CGNAT addresses are rejected at connection time too, not just when saving.
  • The secret is stored encrypted with AES-256-GCM. If you suspect a leak, ask the hotel to rotate it.
  • The full PIN is not stored in yaReserva: only its last four digits, so the front desk can recognize it without being able to read it again.

Integrating a hotel?

Credentials come out of the hotel’s panel, and sandbox ones are created the same day. If the hotel does not have an account yet, start by registering it.