API release notes
What changed in the API, webhooks and integrations each month, with new capabilities, behavior changes and fixes for developers building on the platform.
About these notes
Changes to the platform API and integrations, grouped by month, newest first. Each month starts with a short summary, then new features, improvements, behavior changes and fixes. Changes that may require updates to your integration are marked Breaking.
- Covers the REST API (
/v1/…), webhooks, the MCP connector for AI assistants, and lock and credential changes that are visible through the API. - The platform is updated continuously; changes are live for all organizations when released.
- No API changes in: Dec 2025, Oct 2025.
November 2026
So far this month, credential holders accept new offline_credential_enabled and offline_credential_pin_enabled flags for Entry App offline credentials; use them only on lock models whose offline_credential capability is true while support rolls out. Breaking: week schedules are now capped at 40 time ranges, and holiday schedules at 40 single dates beyond their 5 longest multi-day periods, with larger schedules rejected.
Offline credentials
Credential holders accept offline_credential_enabled, which lets the Entry App download an offline credential for each granted lock that supports it, so the lock can be opened without connectivity. Like entry_app_enabled, it requires the account's Entry App feature and an email, and sends an invitation. offline_credential_pin_enabled (requires offline_credential_enabled) lets the holder install a PIN on the lock with the credential. Offline credentials are valid for 7 days, so changes and removed access reach the lock when the Entry App downloads them again. The lock-side capability is not yet enabled for any model in production, so check offline_credential in the lock models response before relying on it.
- Breaking Week schedules are now limited to 40 time ranges, and holiday schedules to 40 single dates beyond their 5 longest multi-day periods; larger schedules are rejected.
October 2026
The MCP server gains write and credential-reveal tools under new mcp.read, mcp.write and mcp.read_secrets scopes, and ChatGPT and Codex can now connect to it. List endpoints accept per_page up to 250 (the default stays 20). Card credentials on WEST-900JF and WEST-900JQ locks work again, and the API documentation was corrected throughout.
ChatGPT and Codex MCP clients
ChatGPT (web, desktop and mobile) and Codex can now connect to the MCP server alongside Claude. The authorization server metadata advertises authorization_response_iss_parameter_supported: true, and authorization redirects to MCP clients include the iss parameter (RFC 9207), so these clients use their stable client ids. Setup instructions for both are on the API Integrations page of the web app.
MCP write tools and scopes
AI clients can now create, update and delete credential holders, grants, SmartPINs, locations and schedules, register and update locks, and update lock settings. Access is controlled by new OAuth scopes chosen on the consent screen: mcp.read (always granted), mcp.write (make changes) and mcp.read_secrets (reveal a PIN, card number, SmartPIN or programming code, one per call). MCP tokens are rejected by the API, which still requires all, and the MCP server rejects all tokens with 403 insufficient_scope. Existing MCP connections were moved to mcp.read; reconnect to grant write or reveal access.
per_pagenow accepts up to 250 (previously 50); the default stays 20. MCP rate-limit responses now give the correctRetry-Afterwait.
- Fixed card credentials being dropped from new grants on WEST-900JF and WEST-900JQ locks.
- Corrected the API documentation: paginated
{items, metadata}list responses, missing attributes and endpoints, wrong values, broken examples and typos.
September 2026
AI clients can now connect to an MCP server at /mcp/v1 on your organization's host, with read-only tools covering locks, settings, events, credential holders, grants, locations, schedules, SmartPINs and the account. The API also adds GET /v1/locks/{lock_id}/grants/current and /grants/expired with an expired boolean on grants, the ENA lock model, 14 prox-capable PDQ -P submodels (existing PDQ submodels now report prox_nfc_reader: false), nfc_antenna_enabled and prox_antenna_enabled settings superseding nfc and reader_frequency_mode, and read-only secondary_wifi_enabled on GET /v1/locks/{id}. Model capabilities now include prox_reader (with prox_nfc_reader kept as an alias), and a Claude Desktop "unknown client" connection error was fixed.
Reader antenna settings
Lock settings expose two capability-gated booleans, nfc_antenna_enabled and prox_antenna_enabled, returned only for models that support them. They can be updated through the lock settings endpoint and supersede the legacy nfc and reader_frequency_mode fields, which remain for backward compatibility. A request that sends legacy and new fields with disagreeing values is rejected with a conflicting_reader_settings error.
ENA lock model
The ENA lock model is now recognized by the platform and listed with its capabilities, which match the WEST-900JF. It has no submodels. Locks of this model can be registered and managed through the existing lock endpoints.
Current and expired grants for a lock
GET /v1/locks/{lock_id}/grants/current and GET /v1/locks/{lock_id}/grants/expired filter a lock's grants by whether access is still valid, mirroring the existing SmartPIN current/expired endpoints. Every serialized grant now also includes an expired boolean. Status is evaluated against the lock's local time, so it matches what the lock itself enforces. The MCP list_lock_grants tool accepts a matching status parameter (current, expired or all).
PDQ prox-capable submodels
Each existing PDQ submodel now has a dual-chip (NFC + proximity) -P twin, bringing PDQ to 28 submodels; the new submodel codes are listed in the locks documentation. The new variants report prox_nfc_reader: true, while the original NFC-only submodels now report false. Use the lock model capabilities to decide which reader settings apply to a lock.
Read-only MCP tools
The MCP server exposes read-only tools that each mirror an API action, including list_locks, get_lock_settings, list_lock_events, get_account, list_credential_holders, list_lock_grants, list_credential_holder_grants, list_locations, list_schedules and list_smart_pins. List tools return the API's paginated { items, metadata } shape and accept page. PINs, card numbers and programming codes are never returned; they appear as { present: true|false }.
MCP server for AI clients
The platform now hosts a Model Context Protocol (MCP) server at /mcp/v1 on your organization's own host. AI clients such as Claude Code and Claude authenticate through the existing OAuth authorization code flow with PKCE, so the consent screen stays branded to your organization and the client acts as the signed-in user. Tokens are only accepted on the host of the organization they were issued for. Setup instructions for each client are shown on the API Integrations page of the web app.
GET /v1/locks/{id}now returns read-onlysecondary_wifi_enabled, reporting whether the lock has a secondary WiFi network provisioned.- Lock model capabilities now include
prox_reader;prox_nfc_readeris still returned as an alias ofprox_reader.
- Fixed Claude Desktop failing to connect to the MCP server with "unknown client" when using its recommended hosted client metadata option.
August 2026
One breaking change: the briefly returned wifi_connectivity lock attribute has been removed from lock endpoints and the lock_update webhook; use alive and wifi_enabled instead. Also, alive now reflects WiFi connectivity only, so Bluetooth syncs no longer mark a lock alive and locks with WiFi turned off report alive: false.
- Breaking The
wifi_connectivitylock attribute, briefly returned by lock endpoints and thelock_updatewebhook, has been removed; usealiveandwifi_enabledinstead. - The lock
aliveattribute now reflects WiFi connectivity only: BLE syncs no longer mark a lock alive, and locks with WiFi disabled reportalive: false.
July 2026
Breaking: the API now enforces per-caller rate limits of 60 write, 120 read and 30 lock-event requests per minute, returning 429 when exceeded, so clients should handle that status and back off.
API rate limits Breaking
Requests are now rate limited per caller: per user for authorization-code tokens, per account for client-credentials tokens, and per IP for unauthenticated endpoints such as GET /v1/organizations/{subdomain}. Each request counts against one fixed one-minute bucket: write (all POST/PUT/DELETE, 60/min), events (GET /v1/locks/{lock_id}/events, 30/min) or read (all other GETs, 120/min). When a limit is exceeded the API returns 429 Too Many Requests with error_type: "rate_limit_exceeded" and a Retry-After header; design clients around these sustained rates and back off on 429.
June 2026
Lock settings now include unikey_read_range_mode (close, intermediate, far) as a named alternative to unikey_read_range, and lock models report an nfc_reader capability, with smart_card_credential now true for any model with nfc_reader or prox_nfc_reader. Accounts billed through your OAuth application become read-only in the web app, account owners can disconnect an integrator (revoking its tokens), and credential conflicts on holder/grant writes now return a detailed 422 with error_type, error_message and validation_errors. Intermittent HTTP 502 responses from the API were also fixed.
Disconnect API integrators
Account owners now have an API Integrators page in the web app that lists the external applications connected to their account, and administrators can disconnect a billing integrator. Disconnecting revokes every active access token your application holds for that account's users. If your application was the account's billing integrator, the account's billing reverts to the organization default.
`nfc_reader` model capability
Lock models now include an nfc_reader capability that indicates NFC card reader hardware. smart_card_credential is kept and is now derived: it is true when a model has either nfc_reader or prox_nfc_reader. As a result, smart card credentials are allowed on locks that only have a proximity reader, such as PDQ models.
Named read range mode setting
Lock settings now include unikey_read_range_mode with the values close, intermediate and far, so you no longer need to know which integers unikey_read_range expects. Both fields are returned during the transition and kept in sync. When updating, unikey_read_range_mode takes priority if both are sent; an integer unikey_read_range that does not map to a known mode is saved as intermediate. The value unknown can be returned when the lock reports an unrecognized value, but cannot be set.
- Credential holder and grant create/update requests that hit a credential conflict now return a 422 with
error_type,error_messageandvalidation_errorsinstead of a generic body.
- Accounts billed through an API integrator's OAuth application are now read-only in the web app; locks, schedules, credential holders, locations and users are managed through the integration.
- Fixed intermittent HTTP 502 responses from the API caused by a connection keep-alive timeout mismatch.
May 2026
No new endpoints this month, but Edge Controller WU1DR locks no longer generate power-on (reboot) events, though battery-replaced events are still reported. Also fixed newly registered locks not receiving their time zone settings.
- Edge Controller WU1DR locks no longer generate power-on (reboot) events; battery-replaced events are still reported.
- Fixed newly registered locks not receiving their time zone settings after registration.
April 2026
Two new lock settings for card readers: reader_frequency_mode on PDQ locks (both_off, nfc_only, prox_only, both_on, with a new prox_nfc_reader capability) and an updatable edge_controller_reader_type (unikey, card_only, card_and_pin) for locks with unikey_reader_attached. A unikey_read_range of -55 is now saved as -50, and existing PDQ locks report nfc_only instead of null; grant updates also no longer fail capability validation after a holder's credentials change.
Edge controller reader type setting
Lock settings now expose edge_controller_reader_type, which selects the reader type attached to an edge controller: unikey, card_only or card_and_pin. It appears in settings responses only for locks whose model has the unikey_reader_attached capability, and you can update it through the lock settings.
PDQ card reader frequency setting
PDQ locks have a new reader_frequency_mode setting that controls which card reader frequencies are active: both_off, nfc_only (default), prox_only or both_on. The setting is available on locks whose model has the new prox_nfc_reader capability (all PDQ variants); for other models it is null and is rejected as unsupported. Read and update it through the lock settings, like other settings.
- When updating lock settings, a
unikey_read_rangevalue of-55is now saved as-50, the intermediate range value.
- Existing PDQ locks now report
reader_frequency_modeasnfc_onlyinstead ofnull. - Fixed grant updates failing capability validation after the credential holder's credentials changed, such as clearing a PIN.
March 2026
WEST lock models now report the deadbolt_calibration capability as false, and lock_update webhooks once again fire when a lock goes offline or comes back online.
- WEST lock models now report the
deadbolt_calibrationcapability asfalse.
- Fixed
lock_updatewebhooks not being sent when a lock went offline or came back online.
February 2026
Lock health is now pushed to you: the new lock_update webhook event fires when a lock's connected_at, state, wifi_level or power_level changes, and the JungHwa (JUN) lock model joins the lock models list. A lock's alive value is now stored and refreshed on sync and hourly, with changes also triggering lock_update; a follow-up fix stops alive staying false after a lock reconnects.
JungHwa (JUN) lock model
The JungHwa (JUN) lock model is now supported and appears in the lock models list with its capabilities. It supports PIN, smart card, SmartPIN and mobile credentials, keypad lockout and a programming code; deadbolt calibration, alarm and manual auto-lock are not supported. Check the model's capability flags before offering features to users.
`lock_update` webhook event
Webhook endpoints can now subscribe to a new lock_update event that fires whenever a lock's connected_at, state, wifi_level or power_level changes. The payload contains the full lock object, the same representation the API returns for a lock (including id, name, serial_number, state, alive, connected_at, wifi_level and power_level). Add lock_update to your webhook endpoint's subscribed events to receive it; no lock event record is created for these deliveries.
- A lock's
alivevalue is now stored and refreshed on sync and hourly, and changes toalivenow triggerlock_updatewebhooks.
- Fixed lock
alivestayingfalseafter a lock reconnected until the next hourly refresh.
January 2026
New /v1/locks/:lock_id/smart_pins/current and /v1/locks/:lock_id/smart_pins/expired endpoints let you list a lock's active and expired SmartPINs separately, and SmartPIN resources now carry an expired boolean. Linking schedules to credentials also no longer fails validation because of a minimum lock firmware version check.
Current and expired SmartPIN lists
Two new endpoints let you list only the SmartPINs that are still valid or only those that have expired, so long-lived locks no longer return a cluttered mix. Call /v1/locks/:lock_id/smart_pins/current or /v1/locks/:lock_id/smart_pins/expired. Every SmartPIN resource now also includes an expired boolean.
- Linking schedules to credentials no longer fails validation because of a minimum lock firmware version check.
November 2025
Battery power levels for WEST models are now calculated with a model-specific formula, so reported values may shift for those locks.
- Battery power levels for WEST models are now calculated with a model-specific formula.
September 2025
Lock lists can now be sorted: GET /v1/locks accepts a sort parameter of name (default), created_at or updated_at, prefixed with - for descending order.
Sort locks
GET /v1/locks accepts a sort parameter. Pass a column name to sort ascending, or prefix it with - to sort descending (for example -updated_at). Allowed columns are name (the default), created_at and updated_at.
August 2025
Organizations with custom model names now see them in GET /v1/locks/models and in each lock's model_code, and can pass them as sub_model when registering locks with POST /v1/locks.
- Organizations with custom model names now see them in
GET /v1/locks/modelsand lockmodel_code, and can pass them assub_modelwhen registering viaPOST /v1/locks.
July 2025
Find locks faster: GET /v1/locks now accepts a term parameter that filters by lock name or serial number.
Search locks by name or serial number
GET /v1/locks accepts a new term query parameter. Locks whose name or serial number contains the term (case-insensitive) are returned. Use it to build search boxes without paging through all locks.
June 2025
Requests made for a deleted user or account now return a clear 401 with error_type user_or_account_deleted and an error_message. The documentation was expanded: POST /v1/locks lists submodels per series and when sub_model is required, credential holder docs explain unikey_enabled prerequisites, and OAuth pages use the standard Client ID and Client Secret terms.
- API docs now call lock removal "Deregister a lock"; endpoint behavior is unchanged.
- OAuth application pages and API docs now use the standard terms Client ID and Client Secret instead of Application ID and Application Secret.
- API requests made for a deleted user or account now return 401 with
error_typeuser_or_account_deletedand anerror_message, instead of an empty body. - Credential holder docs now describe
unikey_enabledand its prerequisites: account and lock mobile credential settings, and a requiredemail. - Lock registration docs for
POST /v1/locksnow list submodels per series and state thatsub_modelis mandatory for model series that have submodels.
May 2025
Lock model responses now include the unikey_reader_attached capability (currently Edge Controller WU1DR only). Organizations can also enable per-account limits, so lock registration and credential holder creation return "plan limit reached" when an account is over its limit.
- Lock registration and credential holder creation can now be rejected with "plan limit reached, upgrade your account" when your organization has enabled per-account limits.
- Lock model responses from
GET /v1/locks/modelsnow include theunikey_reader_attachedcapability, currently enabled only for the Edge Controller WU1DR model.
April 2025
The KLM-8500 lock model is now supported and listed in GET /v1/locks/models. The API documentation adds a step-by-step Quick start guide for new integrations and explains that each organization has its own OAuth authorization URL, while one OAuth application is enough.
Quick start guide
The API documentation has a new five-step Quick start guide that walks through a first integration. It complements the API overview and the locks and credential holders reference sections.
KLM-8500 lock model
The KLM-8500 is now a supported lock model and appears in GET /v1/locks/models as klm-8500. It supports PIN, smart card and SmartPIN credentials and the no_enter_code setting.
- Authorization Code Flow docs now explain that each organization has its own OAuth authorization URL, while a single OAuth application is sufficient.
March 2025
Credential holders gain a unikey_installer flag on POST /v1/credential_holders, returned in credential holder responses. PUT /v1/locks/{id}/lock and PUT /v1/locks/{id}/unlock now return the lock's state and pending_state, so you can confirm the request without a follow-up call.
Unikey installer credential holders
Credential holders can now be designated as Unikey installers, who can onboard locks as Unikey readers. Pass unikey_installer when creating a credential holder with POST /v1/credential_holders; the value is returned in credential holder responses.
PUT /v1/locks/{id}/lockandPUT /v1/locks/{id}/unlocknow return the lock'sstateandpending_statein the response body.
February 2025
Three new lock settings are available: card_byte_order and always_on for Edge Controller WU1DR locks, and unikey_read_range (-80 to -30) for locks with Unikey support. GET /v1/locks/models also now returns submodel_number for Edge Controller WU1DR and the WEST-900JF, WEST-900JQ and WEST-E07 models.
Always-on connection setting
Edge Controller WU1DR locks support a new always_on boolean setting (default false) that keeps the lock's connection to the cloud open. Read and update it through the lock settings endpoints (/v1/locks/{id}/settings). The setting is only returned for models with the capability, which is listed in GET /v1/locks/models.
Unikey read range setting
Locks that support Unikey credentials now expose a unikey_read_range setting through the lock settings endpoints (/v1/locks/{id}/settings). It accepts values from -80 to -30 and is returned alongside unikey_reader only for models with Unikey support.
Card byte order setting
Edge Controller WU1DR locks support a new card_byte_order setting that controls how card numbers are read: least_significant_byte (default) or most_significant_byte. Read and update it through the lock settings endpoints (/v1/locks/{id}/settings). The setting is only returned for models that support it, and the capability is listed in GET /v1/locks/models.
GET /v1/locks/modelsnow returnssubmodel_numberfor Edge Controller WU1DR, WEST-900JF, WEST-900JQ and WEST-E07.
January 2025
You can now cancel a lock or unlock request that hasn't reached the device yet, using the new PUT /v1/locks/{id}/cancel_pending_action endpoint.
Cancel a pending lock or unlock
You can now cancel a lock or unlock request that is still pending and has not yet been delivered to the device. Call PUT /v1/locks/{id}/cancel_pending_action; the response returns the lock's state and pending_state. This is useful when a user changes their mind before the lock next connects.