Changelog/May 4, 2026
May 4, 2026

Access Code Timeline in the Seam Console

Changelog image for Access Code Timeline in the Seam Console
  • Access Code Timeline in the Seam Console

  • Today, we're excited to introduce the Access Code Timeline — a new side pane in the Seam Console that shows the full lifecycle of any access code at a glance. Open a device that supports access codes (can_program_online_access_codes or can_program_offline_access_codes), click any code, and a panel slides out with a chronological view of every programming event: creation, scheduled programming, set on the device, retries and delays, modifications, failures, deletion.
  • Built for debugging

  • Access code programming spans Seam, the manufacturer's backend API, and (often) the lock itself. When something goes sideways — a code didn't appear on the lock, a guest couldn't get in, a backup access code fired unexpectedly — the timeline answers what happened, when, and why without you having to stitch together logs, webhooks, and provider state.
  • Debugging interface
  • Coming to more resources

  • The timeline is the first piece of a broader pattern we're rolling out across the Seam Console — the same chronological detail pane will arrive for access grants, thermostat schedules, and other long-lived resources where lifecycle visibility matters.
  • Have feedback, or other resources you'd like to see this pattern on? Email us at support@seam.co.
  • 2026.05.04 Changelog

  • New

  • API
    • Spaces ↔ connected accounts: New endpoints POST /spaces/add_connected_account and POST/DELETE /spaces/remove_connected_account let you scope a connected account to a specific space, and /connected_accounts/list accepts a space_id filter.
    • customer_data on spaces: The Space resource now exposes customer_data with time_zone, default_checkin_time, and default_checkout_time. /spaces/create accepts the field, and /spaces/update patches keys individually (pass null to clear).
    • use_backup_access_code_pool on /access_codes/create_multiple: The bulk-create endpoint now honors the backup access code pool with the same constraints as /access_codes/create (time-bound only, supported providers only).
    • requested_at on response errors: Error responses now include a requested_at timestamp, making it easier to correlate Seam errors with your logs and provider-side activity.
    • Inspect request error details: Every error response now includes a request_error_id, and the corresponding error-detail page lives at a public URL (/public/request_error/<id>) so you can open it directly — and share it with Seam support — for richer context on a failed request.
    • Pagination on /spaces/get_related: The endpoint now paginates results per resource type (capped at 50 per type), giving you cursor-based control over related-resource lookups and resolving query failures on workspaces with very large access-method counts.
  • Console
    • Redesigned billing page and upgrade flow: The Console billing page has been redesigned, and the upgrade flow refreshed.
  • Providers
    • Dormakaba Ambiance mobile keys: Mobile key support is now wired up for Dormakaba Ambiance, including a new can_issue_mobile_keys: true capability flag and end-to-end issuance for mobile-key-only access grants.
    • Dormakaba Oracode — native time-bound codes: Oracode codes are now classified as native time-bound and program on creation. Codes scheduled up to a year in advance now report creating (not deferring_creation) and register with Dormakaba on the next sync, instead of waiting for a 1-hour pre-start window.
    • Brivo — PIN and mobile pass credentials: Credential discovery now includes PIN and mobile pass credentials in addition to cards. PINs map to access_method: "code", mobile passes to cloud_key, and cards to card.
    • Salto KS — salto_ks_lock_access_code_support_removed warning: When a Salto KS lock's device model changes from one that supports access codes to one that doesn't, the device now carries a clear warning with a link to the help-center article. The warning auto-clears if the lock model is restored.
  • MCP
    • DeviceDB now indexed in the public Seam MCP Docs Server: The hosted MCP at mcp.seam.co/mcp now indexes 400+ device models and full manufacturer / provider docs, plus per-device-type catalog chunks (sensors, smart locks, thermostats, etc.) — so questions like "which noise sensors does Seam support?" return the full inventory.
  • Changed

  • API
    • deleting pending mutation visible while a delete is in flight: /access_codes/delete now writes a deleting entry to pending_mutations_map atomically with is_being_deleted = true, so /access_codes/get and the timeline reflect the in-flight delete until perm-delete completes.
    • Reason-aware error messages on access-code failures: When an access code fails because the device is offline, the connected account is disconnected, or the device has been removed, the error_map message on failed_to_set_on_device / failed_to_remove_from_device now reflects the real cause instead of generic boilerplate.
    • max_access_codes_reached warning fires from provider responses: Provider-reported "all PIN slots are full" errors now correctly raise the max_access_codes_reached warning on the device — previously the warning only fired from Seam's count-based pre-check.
  • Providers
    • Salto KS — salto_ks_user_not_subscribed warning surfaces on subscription-limit errors: When Salto returns the 1101 subscription-limit error, the affected access code now carries salto_ks_user_not_subscribed instead of being silently cleared.
    • ASSA ABLOY Visionline — provider error details preserved on card encoding 400s: The provider's code, message, and developerMessage are now surfaced in the credential's error_map instead of being collapsed into a generic error.
  • Fixed

  • API & access codes
    • Pre-create updates clear pending mutations: Updating an access code before it's been programmed to the device now correctly clears updating_code / updating_name / updating_time_frame once the create succeeds.
    • Native time-bound codes outside the grace window report deferring_creation: Far-future native time-bound codes (Schlage, Yale, August, Dormakaba) now report deferring_creation until inside the 72-hour grace window, instead of misleadingly reporting creating.
  • Brivo
    • Smarter disconnect handling: Brivo accounts no longer flip to disconnected on transient rate-limit responses, and the acs_system_disconnected warning clears once the account reconnects. Genuine refresh-token failures correctly disconnect the account and emit connected_account.reauthorization_requested so your app can prompt a reconnect. Note: we sent an advisory to all Brivo customers last week to reconnect their Brivo accounts so these changes take effect.
  • Dormakaba Oracode
    • Backup access code pool no longer accepted: Oracode PINs are derived algorithmically by the door firmware from the stay, so backup-pool semantics don't apply. /access_codes/create with use_backup_access_code_pool: true on Oracode now returns a 400, and /devices/get reports properties.supports_backup_access_code_pool: false.
  • Salto
    • subscription_limit_almost_reached warning now clears correctly when the user count drops back below 80% utilization.
    • Self-heal access codes mid-create: Codes whose subscribe step failed after the user was created now self-heal on the next sync instead of staying stuck.
    • Robust handling of access-group changes: ACS sync no longer crashes when an access group is deleted between the list and the read, and the access-group lifecycle is more resilient when the upstream API fails partially.
    • Empty-sites accounts no longer hit Salto in a tight loop: Connected accounts where all sites have been removed no longer make repeating 401 calls to Salto.
  • Schlage
    • Recover already-created codes on duplicate-code errors: When Schlage reports AccessCodeAlreadyInUse, Seam matches the existing code on the lock by PIN and binds the local row to it, eliminating a large class of duplicate_code_on_device errors.
    • Skip push when the device or account is disconnected: Push attempts now short-circuit on both device-level and account-level disconnection, so Seam stops calling Schlage with stale tokens for orphaned codes.
    • Native time-bound codes respect IANA timezones: Timezone strings (America/New_York, etc.) reported via /devices/report_provider_metadata are now resolved correctly, fixing native time-bound codes that were being shifted by the UTC offset on locks with location.timezone set.
  • ASSA ABLOY Visionline
    • Drop invalid joiner cards before encoding: Mobile-key requests now strip joiner cards Visionline can't accept (overridden, cancelled, discarded, expired, unknown) before sending — eliminating a class of stuck mobile keys with illegal_card_in_joiners errors.
    • Card and mobile key starts align for dual-access reservations: Dual-access reservations (card + mobile key) no longer fail when the front desk encodes the card after starts_at; both credentials now align on a starts-no-earlier-than-now timestamp.
  • SmartThings
    • No more false external-deletion on Schlage-via-SmartThings: Schlage locks behind SmartThings sometimes return an empty lockCodes attribute right after a setCode / deleteCode. Seam no longer treats that signal as an external deletion.
  • August / Yale Home
    • Webhooks with non-UUID partnerUserID ignored: August webhooks carrying a non-UUID partnerUserID no longer enter the matching flow.
    • PIN operations track end-to-end so webhooks resolve correctly: Pre-confirming deletes was masking real failures; deletes now wait for the actual partnerUserID, and pin operations are tracked through their lifecycle so webhooks reliably resolve to the correct access code.
    • Managed access codes no longer adopt external partner PINs: A legacy August path could have a managed access code adopt an external partner's PIN, leaving the managed code stuck unset. Adoption is now blocked when the existing August user belongs to a different partner. Yale Home /pins deletion is similarly gated on the partner-user link existing.
  • Nuki
    • No disconnect on proactive token refresh failure: A failure during proactive token refresh no longer flips the account to disconnected.
    • Device ownership preserved for shared Nuki Web locks: Devices shared via Nuki Web no longer get reassigned away from their owning account during sync.
  • Akiles
    • No false low-battery events on mains-powered devices: AC-powered Akiles devices no longer emit false device.low_battery events. Battery level is now only computed when the device is actually battery-powered.
  • Lockly
    • Manual thumbturn lock/unlock events now surface: Manual thumbturn events were being dropped on negative-UTC devices and by case-sensitive event mapping. Both are fixed; manual thumbturn now reliably emits lock.locked / lock.unlocked.
  • ControlByWeb
    • No more online/offline flap from competing pollers: A second poller was overwriting the authoritative connection state, producing spurious device.disconnected → device.connected event pairs every ~10 minutes. The device-level poll no longer writes online state.
By subscribing you agree to our Privacy Policy.
One API for All Devices
Global Infrastructure for Controlling the Physical World
Seam makes controlling IoT devices seamless and programmable. Our teams operate globally,
enabling businesses of all sizes.
Smart Locks
Access Systems
Knowledge
Lock Capabilities
Thermostats
Sensors
© 2026 Seam Labs, Inc.