Seam provides a universal API to connect and control many brands of IoT devices and systems, including smart locks, access control systems (ACSs), thermostats, and noise sensors.
This guide shows you how to install a Seam SDK and then control your 33 Lock device using the Seam API.
Step 1: Install a Seam SDK
First, install a Seam SDK, as follows:
npm i seam
pip install seam
# For some development environments, use pip3 in this command instead of pip.
In this guide, you create a Connect Webview object. Then, you display the graphical component of the created Connect Webview and enter a set of sample credentials to connect a sandbox TTLock account.
This guide shows you how to create a Connect Webview programmatically using the Seam API.
Create a Connect Webview
Create a connect_webview object and then note the returned URL.
Code:
from seam import Seam
seam = Seam() # Seam automatically uses your exported SEAM_API_KEY.
connect_webview = seam.connect_webviews.create(accepted_providers=["ttlock"])
assert connect_webview.login_successful is False
# Use the returned Connect Webview URL to display
# the Connect Webview authorization flow to your user.
print(connect_webview.url)
import { Seam } from "seam";
const seam = new Seam(); // Seam automatically uses your exported SEAM_API_KEY.
const connectWebview = await seam.connectWebviews.create({
accepted_providers: ['ttlock']
});
console.log(connectWebview.login_successful); // false
// Use the returned Connect Webview URL to display
// the Connect Webview authorization flow to your user.
console.log(connectWebview.url);
using Seam.Client;
var seam = new SeamClient(apiToken: SEAM_API_KEY);
var connectWebview = seam.ConnectWebviews.Create(
acceptedProviders: new() {Seam.Api.ConnectWebviews.CreateRequest.AcceptedProvidersEnum.Ttlock}
);
Console.WriteLine(connectWebview.LoginSuccessful); // False
// Use the returned Connect Webview URL to display
// the Connect Webview authorization flow to your user.
Console.WriteLine(connectWebview.Url);
The Seam API exposes each device's properties, such as the door lock status, power status, capabilities, and so on.
Code:
# Retrieve all devices, filtered by manufacturer,
# which is one of several filters that list() supports.
all_ttlock_locks = seam.devices.list(manufacturer="ttlock")
# Select the first device as an example.
front_door = all_ttlock_locks[0]
# Inspect specific properties.
assert front_door.properties["online"] is True # True
assert front_door.properties["locked"] is True # True
# View the entire returned device object.
pprint(front_door)
# Retrieve all devices, filtered by manufacturer, which is
# one of several filters that the list endpoint supports.
all_ttlock_locks=$(
# Use GET or POST.
curl -X 'GET' \
'https://connect.getseam.com/devices/list' \
-H 'accept: application/json' \
-H "Authorization: Bearer ${SEAM_API_KEY}" \
-H 'Content-Type: application/json' \
-d '{
"manufacturer": "ttlock"
}')
# Select the first device as an example.
front_door=$(jq -r '.devices[0]' <<< ${all_ttlock_locks})
# Inspect specific properties.
echo $(jq -r '"Online (true): " + (.properties.online | tostring)' <<< ${front_door})
echo $(jq -r '"Locked (true): " + (.properties.locked | tostring)' <<< ${front_door})
# View the entire returned device object.
echo ${front_door}
// Retrieve all devices, filtered by manufacturer,
// which is one of several filters that list() supports.
const allTtlockLocks = await seam.devices.list({manufacturer: "ttlock"});
// Select the first device as an example.
const frontDoor = allTtlockLocks[0];
// Inspect specific properties.
console.log(frontDoor.properties.online); // true
console.log(frontDoor.properties.locked); // true
// View the entire returned device object.
console.log(frontDoor);
# Retrieve all devices, filtered by manufacturer,
# which is one of several filters that list() supports.
all_ttlock_locks = seam.devices.list(manufacturer: "ttlock")
# Select the first device as an example.
front_door = all_ttlock_locks[0]
# Inspect specific properties.
puts front_door.properties.online # true
puts front_door.properties.locked # true
# View the entire returned device object.
puts front_door.inspect
// Retrieve all devices, filtered by manufacturer,
// which is one of several filters that list() supports.
$all_ttlock_locks = $seam->devices->list(manufacturer: "ttlock");
// Select the first device as an example.
$front_door = $all_ttlock_locks[0];
// Inspect specific properties.
echo $front_door->properties->online ? 'true' : 'false', "\n"; // true
echo $front_door->properties->locked ? 'true' : 'false', "\n"; // true
// View the entire returned device object.
echo json_encode($front_door, JSON_PRETTY_PRINT);
// Retrieve all devices, filtered by manufacturer,
// which is one of several filters that list() supports.
var allTtlockLocks = seam.Devices.List(
manufacturer: Seam.Api.Devices.ListRequest.ManufacturerEnum.Ttlock
);
// Select the first device as an example.
Device frontDoor = allTtlockLocks[0];
// Inspect specific properties.
Console.WriteLine(frontDoor.Properties.Online); // true
Console.WriteLine(frontDoor.Properties.Locked); // true
// View the entire returned device object.
Console.WriteLine(frontDoor);
// Retrieve all devices, filtered by manufacturer,
// which is one of several filters that list() supports.
var allTtlockLocks = seam.devices().list(DevicesListRequest.builder()
.manufacturer(Manufacturer.TTLOCK)
.build());
// Select the first device as an example.
Device frontDoor = allTtlockLocks.get(0);
// Inspect specific properties.
System.out.println(frontDoor.getProperties().getOnline()); // true
System.out.println(frontDoor.getProperties().getLocked()); // true
// View the entire returned device object.
System.out.println(frontDoor);
// Retrieve all devices, filtered by manufacturer,
// which is one of several filters that list() supports.
allTtlockLocks, err := client.Devices.List(
context.Background(), &api.DevicesListRequest{
Manufacturer: api.ManufacturerTtlock.Ptr(),
},
)
// Select the first device as an example.
frontDoor := allTtlockLocks[0]
if err != nil {
return err
}
// Inspect specific properties.
fmt.Println(frontDoor.Properties.Online) // true
fmt.Println(*frontDoor.Properties.Locked) // true
// View the entire returned device object.
fmt.Println(frontDoor)
return nil
Next, you can use the Seam API to control your lock.
Try out the following actions on your 33 Lock device:
Unlock your lock
Code:
# Confirm that the device can remotely unlock.
# You're using a capability flag here!
if front_door.can_remotely_unlock:
# Perform the unlock operation
# and return an action attempt.
action_attempt=seam.locks.unlock_door(device_id=front_door.device_id)
// Confirm that the device can remotely unlock.
// You're using a capability flag here!
if (frontDoor.can_remotely_unlock) {
// Perform the unlock operation
// and return an action attempt.
const actionAttempt = await seam.locks.unlockDoor({
device_id: frontDoor.device_id
});
};
# Confirm that the device can remotely unlock.
# You're using a capability flag here!
if (front_door.can_remotely_unlock)
# Perform the unlock operation
# and return an action attempt.
action_attempt = seam.locks.unlock_door(device_id: front_door.device_id)
end
// Confirm that the device can remotely unlock.
// You're using a capability flag here!
if ($front_door->can_remotely_unlock) {
// Perform the unlock operation
// and return an action attempt.
$action_attempt = $seam->locks->unlock_door(device_id: $front_door->device_id);
}
// Confirm that the device can remotely unlock.
// You're using a capability flag here!
if (frontDoor.CanRemotelyUnlock == true) {
// Perform the unlock operation
// and return an action attempt.
ActionAttempt actionAttempt = seam.Locks.UnlockDoor(deviceId: frontDoor.DeviceId);
}
// Confirm that the device can remotely unlock.
// You're using a capability flag here!
if (frontDoor.getCanRemotelyUnlock())
{
// Perform the unlock operation
// and return an action attempt.
ActionAttempt actionAttempt = seam.locks()
.unlockDoor(LocksUnlockDoorRequest.builder()
.deviceId(frontDoor.getDeviceId())
.build());
}
// Confirm that the device can remotely unlock.
// You're using a capability flag here!
if *frontDoor.CanRemotelyUnlock {
// Perform the unlock operation.
actionAttempt, err := client.Locks.UnlockDoor(
context.Background(),
&api.LocksUnlockDoorRequest{
DeviceId: frontDoor.DeviceId,
},
)
if err != nil {
return err
}
}
return nil
# Get the device by ID.
updated_front_door = seam.devices.get(device_id=front_door.device_id)
# Inspect the locked property to confirm
# that the unlock operation was successful.
assert updated_front_door.properties["locked"] is False # False
Output:
False
Code:
# Get the device by ID.
updated_front_door=$(
# 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\": \"$(jq -r '.device_id' <<< ${front_door})\"
}")
# Inspect the locked property to confirm
# that the unlock operation was successful.
echo $(jq -r '"Locked (false): " + (.device.properties.locked | tostring)' <<< ${updated_front_door})
Output:
Locked (false): false
Code:
// Get the device by ID.
const updatedFrontDoor = await seam.devices.get({device_id: frontDoor.device_id});
// Inspect the locked property to confirm
// that the unlock operation was successful.
console.log(updatedFrontDoor.properties.locked) // false
Output:
false
Code:
# Get the device by ID.
updated_front_door = seam.devices.get(device_id: front_door.device_id)
# Inspect the locked property to confirm
# that the unlock operation was successful.
puts updated_front_door.properties.locked # false
Output:
false
Code:
// Get the device by ID.
$updated_front_door = $seam->devices->get(device_id: $front_door->device_id);
// Inspect the locked property to confirm
// that the unlock operation was successful.
echo $updated_front_door->properties->locked ? 'true' : 'false', "\n"; // false
Output:
false
Code:
// Get the device by ID.
Device updatedFrontDoor = seam.Devices.Get(
deviceId: frontDoor.DeviceId
);
// Inspect the locked property to confirm
// that the unlock operation was successful.
Console.WriteLine(updatedFrontDoor.Properties.Locked); // false
Output:
False
Code:
// Get the device by ID.
Device updatedFrontDoor = seam.devices().get(DevicesGetRequest.builder()
.deviceId(frontDoor.getDeviceId())
.build());
// Inspect the locked property to confirm
// that the unlock operation was successful.
System.out.println(updatedFrontDoor.getProperties().getLocked()); // false
Output:
false
Code:
// Get the device by ID.
updatedFrontDoor, err := client.Devices.Get(
context.Background(), &api.DevicesGetRequest{
DeviceId: api.String(frontDoor.DeviceId),
},
)
if err != nil {
return err
}
// Inspect the locked property to confirm
// that the unlock operation was successful.
fmt.Println(*updatedFrontDoor.Properties.Locked) // false
Output:
false
Program access codes on your lock
Code:
# Confirm that the device supports online access codes.
# Here's another capability flag!
if updated_front_door.can_program_online_access_codes:
# Create an ongoing online access code.
seam.access_codes.create(
device_id = updated_front_door.device_id,
name = "my ongoing code",
code = "1234"
)
# Create a time-bound online access code.
seam.access_codes.create(
device_id = updated_front_door.device_id,
name = "my time-bound code",
starts_at = "2025-01-01T16:00:00Z",
ends_at = "2025-01-22T12:00:00Z",
code = "2345"
)
# List all access codes for this device.
access_codes = seam.access_codes.list(
device_id = updated_front_door.device_id
)
pprint(access_codes)
Seam Components use a responsive design to fit seamlessly on any screen size. They also provide device debugging flows to help your users.
Next steps
Now that you've completed this getting started guide for 33 Lock devices, you can learn more about what you can do with the Seam API.
Quick links
This guide gives you a rapid introduction to connecting and controlling your using the Seam API. For application developers, you can use the Seam API in your app, and your users can authorize your app to control their devices using Seam.
For detailed information about the 33 Lock devices that Seam supports, see our .
To learn more about other IoT device and system brands that Seam supports—such as Yale, Schlage, Google Nest, and many more—visit our .
Another easy way to learn about what you can do with the Seam API is to explore the , which you can access from directly within the .
Seam provides client libraries for many languages, including JavaScript, Python, Ruby, PHP, and others, as well as a Postman collection and an spec.
JavaScript / TypeScript (, )
Python (, )
Ruby Gem (, )
PHP (, )
Java ()
C# (, )
Go ()
Install using .
Next, go to and to get your .
This guide uses a . You can only connect virtual devices and systems in this type of workspace. If you want to connect a real 33 Lock device, use a and API key.
To control your 33 Lock device using the Seam API, you must first authorize your Seam workspace to connect to your associated TTLock account. If your application needs to connect to your users' TTLock accounts, Seam provides fully-embedded, client-side to collect their authorization securely. These user-friendly pre-built authorization flows walk your users through the process of granting your Seam workspace permission to control their 33 Lock devices. The Connect Webview presents a flow that prompts your users to enter their credentials for their TTLock account.
The provides another easy way to connect devices to your Seam workspace.
Go to . On the Devices page, click + Add Devices. Then, see in this guide to complete the Connect Webview authorization flow.
For application developers, you can redirect your user to this Connect Webview URL so that they can authorize your app to control their devices using Seam. We even provide a prebuilt within our suite of that help you build your device management flow.
Because you're using a sandbox workspace, you can connect Seam's test TTLock account. We provide for each of the brands that we support. These sandbox devices and systems enable you to test your app with devices from multiple brands without the need to own all the corresponding physical devices.
Complete the Connect Webview authorization flow by entering the following credentials:
When you link a TTLock account (for your 33 Lock devices) with Seam, we create a device object to represent each 33 Lock lock in your account. You can then retrieve these 33 Lock devices using the and endpoints.
Each device that you connect to Seam has a specific set of capabilities. These capabilities define the Seam API actions that you can use, such as , , and so on. Seam's intuitive and granular inform your application about what features and behaviors each device supports. Notice the capability flags within the code samples in this guide.
To unlock a door, use the endpoint. Specify the device that you want to unlock by including the device_id in the request body. This endpoint returns an to track the progress of the unlock operation.
You can track the status of the unlock operation to confirm that the device unlocked successfully. Query the locked status of the device, by ID, or look for a .
Now that you have successfully unlocked your lock, you can use the endpoint to lock it again.
You can use the Seam API to program on 33 Lock devices. These devices have an integrated keypad. Lock users can then enter these access codes using the keypad to unlock the lock.
The Seam API makes it easy to program both and online access codes.
Now that you have learned the basics of using the Seam API, you can connect and control a real 33 Lock device. To do so, make sure to switch to a and .
For more details about setting up your real 33 Lock device, see the .
Seam makes it easy to develop your application. In addition to the robust Seam API and the wide variety of programming languages that our SDKs support, we also provide a suite of . These prebuilt UI components help you to build your device management flow.
For example, you can use the to display a list of devices and to identify all devices with issues. You can use the to display a device's properties, settings, and issues, as well as to enable your users to perform actions based on each device's capabilities. The provides a similar display and actions for access codes.
To learn about all the Seam Components that we provide, see .
Explore
See the that Seam supports.
Learn
Read about Seam and the that Seam supports.
Use Seam Components
Find out about , which are prebuilt UI components for building your device management flow.
Use webhooks
Learn how to use as an efficient way to receive device events.
Find out more
Explore the other types of devices and systems that you can control with Seam, including , , and .
Develop for mobile access
Learn about Seam's .
If you have any questions or want to report an issue, email us at .
Use the Seam Connect Webview authorization flow to connect a TTLock account with Seam. This flow varies slightly based on the device manufacturer and region.
Seam Components make it easy to develop your application!