Skip to main content
Ultraloq devices require timezone configuration before you can create time-bound access codes. This guide explains why this is necessary and how to configure timezones for your Ultraloq devices.

Why Timezone Configuration is Required

Ultraloq devices have a unique characteristic that requires manual timezone configuration: The Problem:
  • Ultraloq devices schedule access codes using device-local time (e.g., “2024-01-15 14:30”)
  • The Ultraloq API returns timestamps without timezone information
  • Without knowing the device’s timezone, Seam cannot correctly convert UTC timestamps to device-local time
The Solution:
  • You must manually configure each device’s timezone using the /devices/report_provider_metadata API
  • This tells Seam what timezone the device is in so it can correctly schedule time-bound access codes
This is a one-time configuration per device. Once set, the timezone persists until you change it.

What Works Without Timezone

You can use the following features without configuring the device’s timezone:
  • Permanent access codes — Codes without starts_at and ends_at work immediately
  • Lock and unlock operations — Remote lock/unlock commands work immediately
  • Device monitoring — Battery level, lock status, and online/offline state

What Requires Timezone

The following feature requires timezone configuration:
  • Time-bound access codes — Codes with starts_at and ends_at require timezone
If you attempt to create a time-bound access code without configuring the timezone, you’ll receive a validation error:
{
  "error": {
    "type": "invalid_input",
    "message": "Time zone required for time-bound access codes on Ultraloq devices"
  }
}

Detecting Unconfigured Devices

When you first connect an Ultraloq device, it will have the ultraloq_time_zone_unknown warning:
import { Seam } from 'seam'

const seam = new Seam()

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

// Check for timezone warning
const hasTimezoneWarning = device.warnings.some(
  (w) => w.warning_code === 'ultraloq_time_zone_unknown',
)

if (hasTimezoneWarning) {
  console.log('⚠️ Timezone not configured')
  console.log('Configure timezone before creating time-bound access codes')
}

// Check timezone value
const timezone = device.properties.ultraloq_metadata?.time_zone
console.log(`Current timezone: ${timezone}`) // Will be null if not configured

Configuring Timezones

Single Device

To configure the timezone for a single device, use the /devices/report_provider_metadata endpoint:
import { Seam } from 'seam'

const seam = new Seam()

// Configure timezone for one device
await seam.devices.reportProviderMetadata({
  devices: [
    {
      device_id: 'your-device-id',
      ultraloq_metadata: {
        time_zone: 'America/New_York',
      },
    },
  ],
})

console.log('✓ Timezone configured successfully!')

Multiple Devices (Batch Configuration)

You can configure timezones for multiple devices in a single API call:
import { Seam } from 'seam'

const seam = new Seam()

// Get all Ultraloq devices
const devices = await seam.devices.list({
  device_type: 'ultraloq_lock',
})

// Configure timezone for all devices
await seam.devices.reportProviderMetadata({
  devices: devices.map((device) => ({
    device_id: device.device_id,
    ultraloq_metadata: {
      time_zone: 'America/Los_Angeles', // Or get from user
    },
  })),
})

console.log(`✓ Configured timezone for ${devices.length} devices`)

Valid Timezone Values

You must use IANA timezone strings (also called “tz database” timezones). These are standardized timezone identifiers in the format Continent/City.

Examples of Valid Timezones

  • "America/New_York" — Eastern Time (US)
  • "America/Chicago" — Central Time (US)
  • "America/Denver" — Mountain Time (US)
  • "America/Los_Angeles" — Pacific Time (US)
  • "America/Phoenix" — Arizona (no DST)
  • "America/Toronto" — Eastern Time (Canada)
  • "Europe/London" — UK
  • "Europe/Paris" — Central European Time
  • "Asia/Tokyo" — Japan
  • "Australia/Sydney" — Australian Eastern Time
Do not use timezone abbreviations like "EST", "PST", or "GMT-5". These are ambiguous and will cause validation errors. Always use the full IANA timezone string.

Finding the Right Timezone

For a complete list of valid IANA timezones, see: Most programming languages also provide timezone lookup utilities:
// Using Intl API (built-in)
const userTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone
console.log(`User's timezone: ${userTimezone}`)
// Example: "America/Los_Angeles"

// Or using moment-timezone library
const moment = require('moment-timezone')
const allTimezones = moment.tz.names()
console.log(`Available timezones: ${allTimezones.length}`)

Verification

After configuring the timezone, verify that the configuration was successful:
import { Seam } from 'seam'

const seam = new Seam()

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

// Verify timezone is set
const timezone = device.properties.ultraloq_metadata.time_zone
console.log(`Device timezone: ${timezone}`)

// Verify warning is cleared
const hasWarning = device.warnings.some(
  (w) => w.warning_code === 'ultraloq_time_zone_unknown',
)

if (!hasWarning) {
  console.log('✓ Timezone configured successfully!')
  console.log('✓ Device is ready to create time-bound access codes')
} else {
  console.log('✗ Warning still present - check timezone configuration')
}
After configuration, the device will also have the timezone in device.location.timezone:
{
  "device_id": "...",
  "properties": {
    "ultraloq_metadata": {
      "time_zone": "America/New_York"
    }
  },
  "location": {
    "timezone": "America/New_York"
  },
  "warnings": []
}

Changing Timezones

You can change a device’s timezone at any time by calling /devices/report_provider_metadata again with the new timezone.
import { Seam } from 'seam'

const seam = new Seam()

// User moved device from New York to Los Angeles
await seam.devices.reportProviderMetadata({
  devices: [
    {
      device_id: 'your-device-id',
      ultraloq_metadata: {
        time_zone: 'America/Los_Angeles', // Changed from America/New_York
      },
    },
  ],
})

console.log('✓ Timezone updated to Pacific Time')
Impact on Existing Access Codes:
  • Existing time-bound access codes maintain their UTC timestamps
  • They continue working correctly because Seam stores them in UTC internally
  • Future access codes will use the new timezone for scheduling

Best Practices

1. Set Timezone Immediately After Connection

Configure the timezone as soon as you connect an Ultraloq device, before users try to create time-bound access codes:
# Good practice: Configure timezone right after connection
devices = seam.devices.list(connected_account_id=account_id)

seam.devices.report_provider_metadata(
  devices=[
    {
      "device_id": device.device_id,
      "ultraloq_metadata": {"time_zone": user_timezone}
    }
    for device in devices
  ]
)

2. Check Warnings Before Creating Time-Bound Codes

Always check for the ultraloq_time_zone_unknown warning before creating time-bound access codes:
def can_create_time_bound_codes(device):
  return not any(
    w.warning_code == "ultraloq_time_zone_unknown"
    for w in device.warnings
  )

if can_create_time_bound_codes(device):
  # Safe to create time-bound codes
  seam.access_codes.create(
    device_id=device.device_id,
    starts_at="...",
    ends_at="..."
  )
else:
  # Prompt user to configure timezone
  print("Configure device timezone before creating time-bound codes")

3. Use device.location.timezone for Reference

After configuration, you can reference the configured timezone from device.location.timezone:
device = seam.devices.get(device_id="...")

if device.location and device.location.timezone:
  print(f"Device is in {device.location.timezone}")
  # Use this timezone for display or calculations

4. Provide Clear UI Guidance

In your application UI, guide users to select the correct timezone:
┌─────────────────────────────────────────────┐
│ ⚠️  Action Required: Set Device Timezone    │
│                                             │
│ Your Ultraloq device needs a timezone to   │
│ support scheduled access codes.             │
│                                             │
│ Device: Front Door Lock                     │
│                                             │
│ Select timezone: [America/New_York     ▼]  │
│                                             │
│ [ Configure Timezone ]                      │
└─────────────────────────────────────────────┘

Troubleshooting

Invalid Timezone Error

Problem: You receive an error like "Invalid timezone. Must be a valid IANA timezone string." Solution:
  • Verify you’re using a valid IANA timezone (e.g., "America/New_York", not "EST")
  • Check for typos in the timezone string
  • Refer to the IANA timezone list

Warning Not Cleared After Configuration

Problem: The ultraloq_time_zone_unknown warning persists after calling report_provider_metadata. Solution:
  • Verify the API call succeeded (check for errors in the response)
  • Refresh the device by calling seam.devices.get() again
  • Ensure you used the correct device_id
  • Wait a few seconds and check again (state updates are usually immediate but may take a moment)

Time-Bound Codes Still Failing

Problem: Time-bound access codes still fail to create after configuring timezone. Solution:
  • Verify device.properties.ultraloq_metadata.time_zone is not null
  • Check that device.warnings does not contain ultraloq_time_zone_unknown
  • Ensure you’re providing both starts_at and ends_at in your access code request
  • Verify your timestamps are valid ISO 8601 UTC strings

API Reference

For complete API documentation, see:

Next Steps

Now that you understand timezone configuration, you can: