Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
781 changes: 781 additions & 0 deletions claude.md

Large diffs are not rendered by default.

Binary file added docs/.gitbook/assets/ultraloq-logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions docs/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,10 @@
* [Get Started with Tedee Locks](device-and-system-integration-guides/tedee-locks/get-started-with-tedee-locks.md)
* [TTLock Locks](device-guides/ttlock-locks.md)
* [Get started with TTLock Locks](device-guides/get-started-with-ttlock-devices.md)
* [Ultraloq Locks](device-and-system-integration-guides/ultraloq-locks/README.md)
* [Ultraloq Setup Guide](device-and-system-integration-guides/ultraloq-locks/ultraloq-setup-guide.md)
* [Configuring Ultraloq Device Timezones](device-and-system-integration-guides/ultraloq-locks/configuring-ultraloq-device-timezones.md)
* [Creating Ultraloq Access Codes](device-and-system-integration-guides/ultraloq-locks/creating-ultraloq-access-codes.md)
* [Wyze Locks](device-guides/wyze-locks.md)
* [Get started with Wyze Locks](device-guides/get-started-with-wyze-locks.md)
* [Yale Locks](device-guides/yale-locks.md)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,178 @@ When creating access codes, it is important to be aware of any constraints on th
The `constraint_type` property can be any of the following enum values:

<table><thead><tr><th width="338">Constraint Type</th><th>Description</th></tr></thead><tbody><tr><td><code>no_zeros</code></td><td>Cannot use <code>0</code>s as digits in the PIN code.</td></tr><tr><td><code>cannot_start_with_12</code></td><td>PIN code cannot start with the sequence of digits <code>12</code>.</td></tr><tr><td><code>no_triple_consecutive_ints</code></td><td>No more than three digits in a row can be consecutive or the same in the PIN code.</td></tr><tr><td><code>cannot_specify_pin_code</code></td><td>Cannot specify a PIN code. You must leave the code empty, and the lock provider generates a PIN code.</td></tr><tr><td><code>pin_code_matches_existing_set</code></td><td><p>If you specify a PIN code, it must match an existing set of PIN codes used in the account.</p><p>For example, the PIN code could match the code assigned to a user in the system.</p></td></tr><tr><td><code>start_date_in_future</code></td><td>For time-bound codes, the start date must be in the future.</td></tr><tr><td><code>no_ascending_or_descending_sequence</code></td><td>PIN code cannot consist of a sequence of consecutive digits.</td></tr><tr><td><code>at_least_three_unique_digits</code></td><td>PIN code must contain at least three unique digits.</td></tr><tr><td><code>cannot_contain_089</code></td><td><p>PIN code cannot contain the digits <code>0</code>, <code>8</code>, or <code>9</code>.</p><p>For example, this restriction could apply to a cylinder lock that only includes the digits <code>1</code> to <code>7</code>.</p></td></tr><tr><td><code>cannot_contain_0789</code></td><td><p>PIN code cannot contain the digits <code>0</code>, <code>7</code>, <code>8</code>, or <code>9</code>.</p><p>For example, this restriction could apply to a cylinder lock that only includes the digits <code>1</code> to <code>6</code>.</p></td></tr><tr><td><code>name_length</code></td><td><p>Name of the code has some restrictions on length.</p><p>When the <code>constraint_type</code> is <code>name_length</code>, the constraint object has one or two additional properties called <code>min_length</code> and <code>max_length</code> to specify the length constraints.</p></td></tr><tr><td><code>name_must_be_unique</code></td><td>Name of the code must be unique within the device.</td></tr></tbody></table>

***

## Provider-Specific Requirements

In addition to code constraints, some device providers have additional requirements for creating access codes.

### Timezone Configuration

Some device providers require you to configure the device's timezone before creating time-bound access codes. This is because these devices schedule access codes using device-local time, but their APIs do not report the device's timezone.

**Providers requiring timezone configuration:**

* **Ultraloq** — Must configure timezone using `/devices/report_provider_metadata` before creating time-bound access codes. See [Configuring Ultraloq Device Timezones](../../../../device-and-system-integration-guides/ultraloq-locks/configuring-ultraloq-device-timezones.md).

{% hint style="info" %}
Permanent access codes (codes without `starts_at` and `ends_at`) do not require timezone configuration, even on providers that require it for time-bound codes.
{% endhint %}

**Detecting timezone requirement:**

Check for the provider-specific timezone warning in `device.warnings`:

{% tabs %}
{% tab title="Python" %}
```python
from seam import Seam

seam = Seam()

device = seam.devices.get(device_id="your-device-id")

# Check for timezone warnings
timezone_warnings = [
w for w in device.warnings
if "time_zone" in w.warning_code.lower()
]

if timezone_warnings:
print("⚠️ Timezone configuration required for time-bound codes")
print(f"Warning: {timezone_warnings[0].message}")
```
{% endtab %}

{% tab title="JavaScript" %}
```javascript
import { Seam } from "seam";

const seam = new Seam();

const device = await seam.devices.get({
device_id: "your-device-id"
});

// Check for timezone warnings
const timezoneWarnings = device.warnings.filter(
w => w.warning_code.toLowerCase().includes("time_zone")
);

if (timezoneWarnings.length > 0) {
console.log("⚠️ Timezone configuration required for time-bound codes");
console.log(`Warning: ${timezoneWarnings[0].message}`);
}
```
{% endtab %}

{% tab title="Ruby" %}
```ruby
require "seam"

seam = Seam.new()

device = seam.devices.get(device_id: "your-device-id")

# Check for timezone warnings
timezone_warnings = device.warnings.select do |w|
w.warning_code.downcase.include?("time_zone")
end

if timezone_warnings.any?
puts "⚠️ Timezone configuration required for time-bound codes"
puts "Warning: #{timezone_warnings[0].message}"
end
```
{% endtab %}

{% tab title="PHP" %}
```php
<?php
require 'vendor/autoload.php';

use Seam\SeamClient;

$seam = new SeamClient();

$device = $seam->devices->get(device_id: "your-device-id");

// Check for timezone warnings
$timezoneWarnings = array_filter($device->warnings, function($w) {
return stripos($w->warning_code, "time_zone") !== false;
});

if (count($timezoneWarnings) > 0) {
echo "⚠️ Timezone configuration required for time-bound codes\n";
echo "Warning: " . array_values($timezoneWarnings)[0]->message . "\n";
}
```
{% endtab %}

{% tab title="C#" %}
```csharp
using Seam.Client;
using System.Linq;

var seam = new SeamClient();

var device = seam.Devices.Get(deviceId: "your-device-id");

// Check for timezone warnings
var timezoneWarnings = device.Warnings
.Where(w => w.WarningCode.ToLower().Contains("time_zone"))
.ToList();

if (timezoneWarnings.Any())
{
Console.WriteLine("⚠️ Timezone configuration required for time-bound codes");
Console.WriteLine($"Warning: {timezoneWarnings[0].Message}");
}
```
{% endtab %}

{% tab title="Java" %}
```java
import com.seam.api.Seam;
import com.seam.api.types.Device;
import java.util.stream.Collectors;

Seam seam = Seam.builder().build();

Device device = seam.devices().get(
DevicesGetRequest.builder()
.deviceId("your-device-id")
.build()
);

// Check for timezone warnings
var timezoneWarnings = device.getWarnings().stream()
.filter(w -> w.getWarningCode().toLowerCase().contains("time_zone"))
.collect(Collectors.toList());

if (!timezoneWarnings.isEmpty()) {
System.out.println("⚠️ Timezone configuration required for time-bound codes");
System.out.println("Warning: " + timezoneWarnings.get(0).getMessage());
}
```
{% endtab %}

{% tab title="cURL (bash)" %}
```bash
device=$(curl -X 'POST' \
'https://connect.getseam.com/devices/get' \
-H 'accept: application/json' \
-H "Authorization: Bearer ${SEAM_API_KEY}" \
-H 'Content-Type: application/json' \
-d "{
\"device_id\": \"your-device-id\"
}")

# Check for timezone warnings
echo $device | jq '.device.warnings[] | select(.warning_code | test("time_zone"; "i"))'
```
{% endtab %}
{% endtabs %}

For devices requiring timezone configuration, attempting to create a time-bound access code without first setting the timezone will result in a validation error.
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
---
description: Guide for using Ultraloq smart locks with Seam
---

# Ultraloq Locks

<figure><img src="../../.gitbook/assets/ultraloq-manufacturer-page-cover-light.png" alt="Connect and control Ultraloq devices using the Seam API."><figcaption><p>Connect and control Ultraloq devices using the Seam API.</p></figcaption></figure>

## Overview

Seam integrates with Ultraloq smart locks, providing Wi-Fi-enabled access control with online programming capabilities. Ultraloq locks support both permanent and time-bound access codes, remote lock and unlock operations, and device monitoring.

{% hint style="warning" %}
**Important:** Ultraloq devices require timezone configuration before you can create time-bound access codes. This is a unique requirement for Ultraloq locks. See [Configuring Ultraloq Device Timezones](configuring-ultraloq-device-timezones.md) for details.
{% endhint %}

***

## Supported Devices

All Ultraloq smart locks with Wi-Fi connectivity are supported through this integration.

For detailed information about the Ultraloq devices that Seam supports, see our [Ultraloq Supported Devices page](https://www.seam.co/manufacturers/ultraloq).

***

## Supported Features

We support the following features:

#### Device control

* Lock and unlock actions (online)

#### Access code management

* Permanent access codes (no timezone required)
* Time-bound access codes (requires timezone configuration)
* Custom code lengths between 4 and 8 digits
* Auto-generated codes

#### Device monitoring

* Lock status
* Online/offline state
* Battery level (where supported)

***

## Time Zone Requirement

Unlike most other integrations, Ultraloq devices require timezone configuration to enable time-bound access codes. This is because Ultraloq devices schedule access codes using device-local time, but the Ultraloq API does not report the device's timezone.

### What Works Without Timezone

* ✅ Permanent access codes (codes without start/end times)
* ✅ Lock and unlock operations
* ✅ Device monitoring

### What Requires Timezone

* ❌ Time-bound access codes (codes with `starts_at` and `ends_at`)

When you first connect an Ultraloq device, it will have a `ultraloq_time_zone_unknown` warning in `device.warnings`. You must configure the timezone using the `/devices/report_provider_metadata` endpoint before creating time-bound access codes.

For complete instructions, see [Configuring Ultraloq Device Timezones](configuring-ultraloq-device-timezones.md).

***

## Connecting Ultraloq to Seam

To enable your users to [connect Ultraloq devices through Connect Webviews](../../core-concepts/connect-webviews/customizing-connect-webviews.md#customize-the-brands-to-display-in-your-connect-webviews), include the Ultraloq provider:

```json
{
"accepted_providers": ["ultraloq"]
}
```

After the user authorizes Seam through the OAuth flow, their Ultraloq devices will be automatically discovered and added to Seam.

[→ See: Ultraloq Setup Guide](ultraloq-setup-guide.md)

***

## Brand-specific notes

* **Access codes:** Ultraloq requires access codes to be 4–8 digit numeric PINs (e.g., "1234", "567890").
* **Timezone configuration:** Required before creating time-bound access codes. Permanent codes work without timezone configuration.
* **Code disabling:** Users can disable access codes through the Ultraloq mobile app. Seam detects this and adds a `ultraloq_access_code_disabled` warning to the affected access code.

***

## Next Steps

<table data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>Connect Ultraloq to Seam</strong></td><td>Follow the setup guide to connect your Ultraloq account and configure device timezones.</td><td><a href="ultraloq-setup-guide.md">ultraloq-setup-guide.md</a></td></tr><tr><td><strong>Configure Device Timezones</strong></td><td>Learn how to set device timezones to enable time-bound access codes.</td><td><a href="configuring-ultraloq-device-timezones.md">configuring-ultraloq-device-timezones.md</a></td></tr><tr><td><strong>Create Access Codes</strong></td><td>Learn how to create permanent and time-bound access codes for Ultraloq locks.</td><td><a href="creating-ultraloq-access-codes.md">creating-ultraloq-access-codes.md</a></td></tr><tr><td><strong>Order Locks</strong></td><td>Purchase Ultraloq locks from Amazon.</td><td><a href="https://www.amazon.com/stores/ULTRALOQ/page/1F5DDCF3-7F1E-4B36-8D3F-8F8C5E5A5C5F">https://www.amazon.com/stores/ULTRALOQ</a></td></tr></tbody></table>

***
Loading
Loading