Overview
Seam enables you to lock or unlock your door lock remotely. This guide walks you through how to perform these actions using the Seam API.
When you send a command to a smart lock, it might take a while for Seam to confirm the action’s success. To handle this, Seam provides an “action attempt” object, which indicates whether the action was successful.
To ensure that the action has been successfully executed, we advise checking the status of the action attempt object by polling the “Get Action Attempt” request. Once Seam has successfully confirmed the action, the action attempt’s status will indicate success.
Some providers and device models cannot confirm whether the physical lock or unlock happened in a reasonable time or at all. In those cases, a successful action attempt can still include action_attempt.result.was_confirmed_by_device = false.
Before You Begin: Confirm Capabilities
Before you attempt to lock or unlock a device, be sure to confirm that your device has the capability to perform these operations. You can inspect the capabilities of a device by checking the following capability flags for the device:
device.can_remotely_lock
device.can_remotely_unlock
Use Get Device for a specific device to return these capability flags. Then, use an if statement or similar check to confirm that the relevant flag is both present and true before attempting to lock or unlock the device.
If either of these capability flags is false or not present, you can view the properties of the device, errors or warnings for the device, and events related to the device to learn more about the cause of these issues. For example, you could examine device.properties.online. In addition, you could look for a device.disconnected event.
JavaScript
cURL
Python
Ruby
PHP
C#
Request:await seam.devices.get('11111111-1111-1111-1111-444444444444')
Response:{
device_id: '11111111-1111-1111-1111-444444444444',
can_remotely_lock: true, // You can use seam.locks.lockDoor() on this device.
can_remotely_unlock: true, // You can use seam.locks.unlockDoor() on this device.
...
}
Request:# Use GET or POST.
curl -X 'GET' \
'https://connect.getseam.com/devices/get' \
-H 'accept: application/json' \
-H "Authorization: Bearer ${SEAM_API_KEY}" \
-H 'Content-Type: application/json' \
-d '{
"device_id": "11111111-1111-1111-1111-444444444444"
}'
Response:{
"device": {
"device_id": "11111111-1111-1111-1111-444444444444",
"can_remotely_lock": true, // You can use /locks/lock_door on this device.
"can_remotely_unlock": true, // You can use /locks/unlock_door on this device.
...
},
"ok": true
}
Request:seam.devices.get(device_id="11111111-1111-1111-1111-444444444444")
Response:Device(
device_id='11111111-1111-1111-1111-444444444444',
can_remotely_lock=True, // You can use seam.locks.lock_door() on this device.
can_remotely_unlock=True, // You can use seam.locks.unlock_door() on this device.
...
)
Request:client.devices.get(device_id: "11111111-1111-1111-1111-444444444444")
Response:<
Seam::Device:0x00438
device_id="11111111-1111-1111-1111-444444444444"
can_remotely_lock=true // You can use client.locks.lock_door() on this device.
can_remotely_unlock=true // You can use client.locks.unlock_door() on this device.
...
>
Request:$seam->devices->get("11111111-1111-1111-1111-444444444444");
Response:{
"device_id": "11111111-1111-1111-1111-444444444444",
"can_remotely_lock": true, // You can use $seam->locks->lock_door() on this device.
"can_remotely_unlock": true, // You can use $seam->locks->unlock_door() on this device.
...
}
Request:seam.Devices.Get(deviceId: "11111111-1111-1111-1111-444444444444");
Response:{
"device_id": "11111111-1111-1111-1111-444444444444",
"can_remotely_lock": true, // You can use seam.Locks.LockDoor() on this device.
"can_remotely_unlock": true, // You can use seam.Locks.UnlockDoor() on this device.
...
}
Locking a Door
You can lock a door using the lock_door endpoint. To confirm the success of the action, see Verifying the success of a lock or unlock action.
JavaScript
cURL
Python
Ruby
PHP
C#
Request:// Get the device.
const device = await seam.devices.get({
device_id: '11111111-1111-1111-1111-444444444444',
})
// Confirm that the device can remotely lock.
if (device.can_remotely_lock) {
// Perform the lock operation.
await seam.locks.lockDoor({
device_id: device.device_id,
})
}
Response:{
"actionAttempt": {
"status": "success",
"action_attempt_id": "11111111-2222-3333-4444-555555555555",
"action_type": "LOCK_DOOR",
"result": {},
"error": null
}
}
Request:# Get the device.
device=$(
# Use GET or POST.
curl -X 'GET' \
'https://connect.getseam.com/devices/get' \
-H 'accept: application/json' \
-H "Authorization: Bearer ${SEAM_API_KEY}" \
-H 'Content-Type: application/json' \
-d '{
"device_id": "11111111-1111-1111-1111-444444444444"
}')
# Confirm that the device can remotely lock.
if $(jq -r '.device.can_remotely_lock' <<< ${device}); then \
# Perform the lock operation.
curl -X 'POST' \
'https://connect.getseam.com/locks/lock_door' \
-H 'accept: application/json' \
-H "Authorization: Bearer ${SEAM_API_KEY}" \
-H 'Content-Type: application/json' \
-d "{
\"device_id\": \"$(jq -r '.device.device_id' <<< ${device})\"
}";
fi
Response:{
"action_attempt": {
"status": "pending",
"action_type": "LOCK_DOOR",
"action_attempt_id": "11111111-2222-3333-4444-555555555555",
"result": null,
"error": null
},
"ok": true
}
Request:# Get the device.
device = seam.devices.get(
device_id="11111111-1111-1111-1111-444444444444"
)
# Confirm that the device can remotely lock.
if device.can_remotely_lock:
# Perform the lock operation.
seam.locks.lock_door(device_id=device.device_id)
Response:ActionAttempt(status='pending',
action_type='LOCK_DOOR',
action_attempt_id='11111111-2222-3333-4444-555555555555',
result=None,
error={})
Request:# Get the device.
device = client.devices.get(device_id: "11111111-1111-1111-1111-444444444444")
# Confirm that the device can remotely lock.
if (device.can_remotely_lock)
# Perform the lock operation.
client.locks.lock_door(device_id: device.device_id)
end
Response:<Seam::ActionAttempt:0x00438
status="pending"
action_type="LOCK_DOOR"
action_attempt_id="11111111-2222-3333-4444-555555555555"
result=nil>
Request:// Get the device.
$device = $seam->devices->get(device_id: "11111111-1111-1111-1111-444444444444");
// Confirm that the device can remotely lock.
if ($device->can_remotely_lock) {
// Perform the lock operation.
$seam->locks->lock_door(device_id: $device->device_id);
}
Response:{
"action_attempt_id": "11111111-2222-3333-4444-555555555555",
"action_type": "LOCK_DOOR",
"error": null,
"result": {},
"status": "success"
}
Request:// Get the device.
Device device = seam.Devices.Get(deviceId: "11111111-1111-1111-1111-444444444444");
// Confirm that the device can remotely lock.
if (device.CanRemotelyLock == true) {
// Perform the lock operation.
seam.Locks.LockDoor(deviceId: device.DeviceId);
}
Response:{
"status": "pending",
"action_type": "LOCK_DOOR",
"action_attempt_id": "11111111-2222-3333-4444-555555555555"
}
Unlocking a Door
You can unlock a door using the unlock_door endpoint. To confirm the success of the action, see Verifying the success of a lock or unlock action.
JavaScript
cURL
Python
Ruby
PHP
C#
Request:// Get the device.
const device = await seam.devices.get({
device_id: '11111111-1111-1111-1111-444444444444',
})
// Confirm that the device can remotely unlock.
if (device.can_remotely_unlock) {
// Perform the unlock operation.
await seam.locks.unlockDoor({
device_id: device.device_id,
})
}
Response:{
"actionAttempt": {
"status": "success",
"action_attempt_id": "11111111-2222-3333-4444-555555555555",
"action_type": "UNLOCK_DOOR",
"result": {
"was_confirmed_by_device": false
},
"error": null
}
}
Request:# Get the device.
device=$(
# Use GET or POST.
curl -X 'GET' \
'https://connect.getseam.com/devices/get' \
-H 'accept: application/json' \
-H "Authorization: Bearer ${SEAM_API_KEY}" \
-H 'Content-Type: application/json' \
-d '{
"device_id": "11111111-1111-1111-1111-444444444444"
}')
# Confirm that the device can remotely unlock.
if $(jq -r '.device.can_remotely_unlock' <<< ${device}); then \
# Perform the unlock operation.
curl -X 'POST' \
'https://connect.getseam.com/locks/unlock_door' \
-H 'accept: application/json' \
-H "Authorization: Bearer ${SEAM_API_KEY}" \
-H 'Content-Type: application/json' \
-d "{
\"device_id\": \"$(jq -r '.device.device_id' <<< ${device})\"
}";
fi
Response:{
"action_attempt": {
"status": "pending",
"action_type": "UNLOCK_DOOR",
"action_attempt_id": "11111111-2222-3333-4444-555555555555",
"result": null,
"error": null
},
"ok": true
}
Request:# Get the device.
device = seam.devices.get(
device_id="11111111-1111-1111-1111-444444444444"
)
# Confirm that the device can remotely unlock.
if device.can_remotely_unlock:
# Perform the unlock operation.
seam.locks.unlock_door(device_id=device.device_id)
Response:ActionAttempt(status='pending',
action_type='UNLOCK_DOOR',
action_attempt_id='11111111-2222-3333-4444-555555555555',
result=None,
error={})
Request:# Get the device.
device = client.devices.get(device_id: "11111111-1111-1111-1111-444444444444")
# Confirm that the device can remotely unlock.
if (device.can_remotely_unlock)
# Perform the unlock operation.
client.locks.unlock_door(device_id: device.device_id)
end
Response:<Seam::ActionAttempt:0x00438
status="pending"
action_type="UNLOCK_DOOR"
action_attempt_id="11111111-2222-3333-4444-555555555555"
result=nil>
Request:// Get the device.
$device = $seam->devices->get(device_id: "11111111-1111-1111-1111-444444444444");
// Confirm that the device can remotely unlock.
if ($device->can_remotely_unlock) {
// Perform the unlock operation.
$seam->locks->unlock_door(device_id: $device->device_id);
}
Response:{
"action_attempt_id": "11111111-2222-3333-4444-555555555555",
"action_type": "UNLOCK_DOOR",
"error": null,
"result": {
"was_confirmed_by_device": false
},
"status": "success"
}
Request:// Get the device.
Device device = seam.Devices.Get(deviceId: "11111111-1111-1111-1111-444444444444");
// Confirm that the device can remotely unlock.
if (device.CanRemotelyUnlock == true) {
// Perform the unlock operation.
seam.Locks.UnlockDoor(deviceId: device.DeviceId);
}
Response:{
"status": "pending",
"action_type": "UNLOCK_DOOR",
"action_attempt_id": "11111111-2222-3333-4444-555555555555"
}
Verifying the Success of a Lock or Unlock Action
1. Execute a Lock request (or other action)
When initiating a lock or unlock action, the Seam API returns an action attempt, which monitors the success or failure of the action.
JavaScript
cURL
Python
Ruby
PHP
C#
Request:await seam.locks.lockDoor({
device_id: '11111111-1111-1111-1111-444444444444',
})
Response:{
"actionAttempt": {
"status": "success",
"action_attempt_id": "11111111-2222-3333-4444-555555555555",
"action_type": "LOCK_DOOR",
"result": {},
"error": null
}
}
Request:curl -X 'POST' \
'https://connect.getseam.com/locks/lock_door' \
-H 'accept: application/json' \
-H "Authorization: Bearer ${SEAM_API_KEY}" \
-H 'Content-Type: application/json' \
-d '{
"device_id": "11111111-1111-1111-1111-444444444444"
}'
Response:{
"action_attempt": {
"status": "pending",
"action_type": "LOCK_DOOR",
"action_attempt_id": "11111111-2222-3333-4444-555555555555",
"result": null,
"error": null
},
"ok": true
}
Request:seam.locks.lock_door(device_id="11111111-1111-1111-1111-444444444444")
Response:ActionAttempt(status='pending',
action_type='LOCK_DOOR',
action_attempt_id='11111111-2222-3333-4444-555555555555',
result=None,
error={})
Request:client.locks.lock_door(device_id: "11111111-1111-1111-1111-444444444444")
Response:<Seam::ActionAttempt:0x00438
status="pending"
action_type="LOCK_DOOR"
action_attempt_id="11111111-2222-3333-4444-555555555555"
result=nil>
Request:$seam->locks->lock_door(device_id: "11111111-1111-1111-1111-444444444444");
Response:{
"action_attempt_id": "11111111-2222-3333-4444-555555555555",
"action_type": "LOCK_DOOR",
"error": null,
"result": {},
"status": "success"
}
Request:seam.Locks.LockDoor(deviceId: "11111111-1111-1111-1111-444444444444");
Response:{
"status": "pending",
"action_type": "LOCK_DOOR",
"action_attempt_id": "11111111-2222-3333-4444-555555555555"
}
2. Poll the Action Attempt to Verify the Success of the Action
Use the action_attempt_id from the prior response to make a Get Action Attempt request. When the action attempt’s status changes to success, it indicates the action has been successful.
Some providers and device models do not confirm whether a lock or unlock
completed on the physical device. In those cases, the action attempt can still
succeed while action_attempt.result.was_confirmed_by_device is false. Use
this property to set the right expectation in your UI, especially for unlock
flows.
JavaScript
cURL
Python
Ruby
PHP
C#
Request:await seam.actionAttempts.get({
action_attempt_id: '11111111-2222-3333-4444-555555555555',
})
Response:{
"status": "success",
"action_attempt_id": "11111111-2222-3333-4444-555555555555",
"action_type": "LOCK_DOOR",
"result": {
"was_confirmed_by_device": true
},
"error": null
}
Request:# Use GET or POST.
curl -X 'GET' \
'https://connect.getseam.com/action_attempts/get' \
-H 'accept: application/json' \
-H "Authorization: Bearer ${SEAM_API_KEY}" \
-H 'Content-Type: application/json' \
-d '{
"action_attempt_id": "11111111-2222-3333-4444-555555555555"
}'
Response:{
"action_attempt": {
"status": "success",
"action_attempt_id": "11111111-2222-3333-4444-555555555555",
"action_type": "LOCK_DOOR",
"result": {
"was_confirmed_by_device": true
},
"error": null
},
"ok": true
}
Request:seam.action_attempts.get(action_attempt_id="11111111-2222-3333-4444-555555555555")
Response:ActionAttempt(action_attempt_id='11111111-2222-3333-4444-555555555555',
action_type='LOCK_DOOR',
status='success',
result={'was_confirmed_by_device': True},
error=None)
Request:client.action_attempts.get(action_attempt_id: "11111111-2222-3333-4444-555555555555")
Response:<Seam::ActionAttempt:0x00438
status="success"
action_attempt_id="11111111-2222-3333-4444-555555555555"
action_type="LOCK_DOOR"
result={"was_confirmed_by_device"=>true}>
Request:$seam->action_attempts->get(action_attempt_id: "11111111-2222-3333-4444-555555555555");
Response:{
"action_attempt_id": "11111111-2222-3333-4444-555555555555",
"action_type": "LOCK_DOOR",
"error": null,
"result": {
"was_confirmed_by_device": true
},
"status": "success"
}
Request:seam.ActionAttempts.Get("11111111-2222-3333-4444-555555555555");
Response:{
"status": "success",
"action_type": "LOCK_DOOR",
"action_attempt_id": "11111111-2222-3333-4444-555555555555",
"result": {
"was_confirmed_by_device": true
},
"error": null
}
Checking the Locked Status of a Lock
To retrieve the locked status of a specific door lock, use the Get Device endpoint by providing the device_id of the desired lock. This operation returns detailed information, including the current locked status. Note that if the lock is offline, Seam does not return the device.locked property.
JavaScript
cURL
Python
Ruby
PHP
C#
Request:await seam.devices.get('11111111-1111-1111-1111-444444444444')
Response:{
device_id: '11111111-1111-1111-1111-444444444444',
properties: {
locked: true,
...
},
...
}
Request:# Use GET or POST.
curl -X 'GET' \
'https://connect.getseam.com/devices/get' \
-H 'accept: application/json' \
-H "Authorization: Bearer ${SEAM_API_KEY}" \
-H 'Content-Type: application/json' \
-d '{
"device_id": "11111111-1111-1111-1111-444444444444"
}'
Response:{
"lock": {
"device_id": "11111111-1111-1111-1111-444444444444",
"properties": {
"locked": true,
...
},
...
},
"ok": true
}
Request:seam.devices.get(device_id="11111111-1111-1111-1111-444444444444")
Response:Device(
device_id='11111111-1111-1111-1111-444444444444',
properties={
'locked': True,
...
},
...
)
Request:client.devices.get(device_id: "11111111-1111-1111-1111-444444444444")
Response:<Seam::Device:0x00438
device_id="11111111-1111-1111-1111-444444444444"
properties={
"locked"=>true,
...
}
...
>
Request:$seam->devices->get("11111111-1111-1111-1111-444444444444");
Response:{
"device_id": "11111111-1111-1111-1111-444444444444",
"properties": {
"locked": true,
...
},
...
}
Request:seam.Devices.Get("11111111-1111-1111-1111-444444444444");
Response:{
"device_id": "11111111-1111-1111-1111-444444444444",
"properties": {
"locked": true,
...
},
...
}
Lock and Unlock Events
Whenever a lock is locked or unlocked, Seam emits a lock.locked or lock.unlocked event. You can see these events by making a List Events request or by setting up a webhook. For more information on how to set up webhooks, see the Webhooks guide.
A lock or unlock event looks like the following:
{
"event": {
"event_id": "22222222-3333-4444-5555-666666666666",
"device_id": "11111111-1111-1111-1111-444444444444",
"event_type": "lock.locked",
"workspace_id": "00000000-0000-0000-0000-000000000000",
"created_at": "2023-10-13T15:10:18.443Z",
"occurred_at": "2023-10-13T15:09:08.531Z",
"method": "unknown",
"connected_account_id": "11111111-1111-1111-1111-222222222222"
},
"ok": true
}
For more information about the lock.locked and lock.unlocked attributes, please see Events.