Remote unlock
A KEYPAD code is verified by the lock's own firmware — lockapi never sees the actual entry attempt. A REMOTE code is verified by lockapi itself before the physical unlock happens, which gives it guarantees a keypad code structurally can't: real lockout on wrong guesses, a configurable use limit, and a complete audit trail of every attempt — no vendor webhook dependency at all.
Your own app is what the guest actually types the code into — lockapi has no public guest-facing page. You collect the code from the guest, then call the endpoint below with your API key.
1. Create a REMOTE code
Requires device.capabilities.remoteUnlock === true — see Devices & capabilities.
POST /v1/access_codes
{
"deviceId": "<device id>",
"deliveryMethod": "REMOTE",
"validFrom": "2026-08-01T15:00:00.000Z",
"validUntil": "2026-08-03T11:00:00.000Z",
"maxUses": 1
}
→ { "id": "ac_123", "code": "482913", "maxUses": 1, "useCount": 0, "status": "ACTIVE", ... }maxUses is optional. Omit it (or pass null) for unlimited uses — the right choice for keyless properties where the guest unlocks the door multiple times during their stay. Set it to 1for a one-time entry code (e.g. "enter once to collect the physical keys"). Any integer ≥ 1 is accepted. Once useCount reaches maxUses the code stops accepting further unlock attempts with a 409.
Nothing is sent to the vendor yet — relay code to your guest through whatever channel you already use (SMS, your app, email).
2. Submit the guest's code
POST /v1/access_codes/ac_123/unlock_attempts
Idempotency-Key: <unique per attempt>
{ "code": "482913" }
→ 200 { "result": "CONFIRMED" }CONFIRMED vs. UNCERTAIN
Real vendor hardware doesn't always confirm an unlock reliably (some vendor APIs report success even when the physical unlock silently failed). lockapi checks the lock's actual state after sending the command rather than trusting the vendor's accept response, and returns one of:
CONFIRMED— the lock's state was verified to have changed.useCountis incremented. IfuseCountreachesmaxUses, further attempts return409.UNCERTAIN— the vendor accepted the command but lockapi couldn't confirm the physical state change within a short window. The code is not marked used — it's not the guest's fault the vendor's connection was flaky, so it stays retryable.
Wrong codes and lockout
A wrong code returns 401 and counts against that access code's attempt budget. After 5 wrong attempts the code is automatically revoked — a fresh one has to be issued. An UNCERTAIN result does not count against this budget.
Idempotency
Send an Idempotency-Key on every attempt — unlike most idempotent endpoints, a retried call with the same key replays the cached result even if that result was a failure (wrong code, expired, etc.), not just a success. A physical unlock is not something you want to accidentally trigger twice because a network retry landed on a fresh attempt.
Remote lock
Devices with capabilities.remoteLock === true can also be locked on demand — useful for keyless stays where the guest should lock up when leaving. The access code must be non-revoked and within its validity window; no code verification or attempt budget applies.
POST /v1/access_codes/ac_123/lock_attempts
→ 200 { "result": "CONFIRMED" }The response follows the same CONFIRMED / UNCERTAIN semantics as unlock attempts. Openers and intercoms always have remoteLock: false — they have no bolt, so only unlock (electric strike) is possible on those devices.
Audit trail
Every attempt — success, wrong code, or uncertain — is recorded and queryable:
GET /v1/access_codes/ac_123/events