> ## Documentation Index
> Fetch the complete documentation index at: https://www.seam.co/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Configuring Schlage Lock Time Zones

> Set the time zone for Schlage locks so that Seam programs time-bound access codes at exact local times, including across daylight saving time changes.

Schlage locks enforce time-bound access codes in the lock's local time. Seam converts the UTC `starts_at` and `ends_at` that you send into the lock's local time. To do this exactly for codes that cross a daylight saving time (DST) change, Seam needs the lock's IANA time zone, such as `America/New_York`.

Seam infers the time zone for most Schlage locks automatically. This guide explains when it can't, what happens in that case, and how to set the time zone yourself.

> [!NOTE]
>
> This guide applies to devices with a `device_type` of `schlage_lock`.

***

## How Seam Determines a Lock's Time Zone

Schlage reports each lock's current UTC offset, such as `-05:00`, but not its time zone. Seam infers the time zone from the offsets that the lock reports:

* **Two offsets from a DST cycle:** After a lock has reported both its standard and its daylight saving offset, the pair identifies the time zone. For example, `-05:00` and `-04:00` identify `America/New_York`.
* **An offset used only by time zones without DST:** Some offsets identify a time zone on their own. For example, `-10:00` identifies `Pacific/Honolulu`.

Until one of these applies, the lock's time zone is unknown. A single summer offset isn't enough. For example, a lock that reports `-07:00` in the summer could be in Pacific Time, which observes DST, or in Arizona, which doesn't. Seam doesn't guess, because a wrong time zone shifts every code on the lock by an hour.

As a result, the time zone is often unknown for:

* **Recently connected locks** that haven't gone through a DST change yet. Seam infers their time zone after the next DST change.
* **Locks in places that don't observe DST**, such as Arizona. These locks report the same offset all year, so Seam may never infer their time zone.

***

## What Happens When the Time Zone Is Unknown

All Schlage features work without a time zone, including time-bound access codes. The only difference is for time-bound codes that cross a DST change.

For these codes, Seam applies a 1-hour safety buffer on the lock so that guests can always get in during the time frame you requested. For a spring-forward change, the code ends up to 1 hour later. For a fall-back change, the code starts up to 1 hour earlier. Seam also adds the `time_frame_adjusted_for_unknown_time_zone` warning to the access code.

For details, see [Schlage Locks and Daylight Saving Time](/docs/device-and-system-integration-guides/schlage-locks/schlage-locks-daylight-savings-time-adjustments.md).

***

## Find Locks Without a Time Zone

A lock's time zone is in `device.location.time_zone`. If this property is empty, the time zone is unknown. To find these locks, list your Schlage locks and check each one:

```javascript JavaScript theme={"dark"}
import { Seam } from 'seam'

const seam = new Seam()

// List Schlage locks
const devices = await seam.devices.list({
  device_type: 'schlage_lock',
})

// Keep the locks whose time zone is unknown
const locksWithoutTimeZone = devices.filter(
  (device) => !device.location?.time_zone,
)

for (const device of locksWithoutTimeZone) {
  console.log(device.device_id)
}
```

```bash cURL theme={"dark"}
curl -s -X 'POST' \
  'https://connect.getseam.com/devices/list' \
  -H 'accept: application/json' \
  -H "Authorization: Bearer ${SEAM_API_KEY}" \
  -H 'Content-Type: application/json' \
  -d '{
    "device_type": "schlage_lock"
  }' |
  jq -r '.devices[] | select((.location.time_zone // "") == "") | .device_id'
```

```python Python theme={"dark"}
from seam import Seam

seam = Seam()

# List Schlage locks
devices = seam.devices.list(device_type="schlage_lock")

# Keep the locks whose time zone is unknown
for device in devices:
  if device.location is None or not device.location.time_zone:
    print(device.device_id)
```

```ruby Ruby theme={"dark"}
require "seam"

seam = Seam.new()

# List Schlage locks
devices = seam.devices.list(device_type: "schlage_lock")

# Keep the locks whose time zone is unknown
devices.each do |device|
  time_zone = device.location&.time_zone
  puts device.device_id if time_zone.nil? || time_zone.empty?
end
```

```php PHP theme={"dark"}
<?php
require 'vendor/autoload.php';

use Seam\Seam;

$seam = new Seam();

// List Schlage locks
$devices = $seam->devices->list(device_type: "schlage_lock");

// Keep the locks whose time zone is unknown
foreach ($devices as $device) {
  if (($device->location?->time_zone ?? "") === "") {
    echo $device->device_id . "\n";
  }
}
```

```csharp C# theme={"dark"}
using Seam.Api;
using Seam.Client;

var seam = new SeamClient(apiToken: Environment.GetEnvironmentVariable("SEAM_API_KEY"));

// List Schlage locks
var devices = seam.Devices.List(
  deviceType: Devices.ListRequest.DeviceTypeEnum.SchlageLock
);

// Keep the locks whose time zone is unknown
foreach (var device in devices)
{
  if (string.IsNullOrEmpty(device.Location?.TimeZone))
  {
    Console.WriteLine(device.DeviceId);
  }
}
```

```java Java theme={"dark"}
import com.seam.api.Seam;
import com.seam.api.resources.devices.requests.DevicesListRequest;
import com.seam.api.types.Device;
import com.seam.api.types.DeviceType;
import java.util.List;
import java.util.Map;

Seam seam = Seam.builder()
  .apiKey(System.getenv("SEAM_API_KEY"))
  .build();

// List Schlage locks
List<Device> devices = seam.devices().list(
  DevicesListRequest.builder()
    .deviceType(DeviceType.SCHLAGE_LOCK)
    .build()
);

// Keep the locks whose time zone is unknown.
// The Java SDK types device.location as a plain object, so read it as a map.
for (Device device : devices) {
  Object timeZone = device.getLocation()
    .map(location -> ((Map<?, ?>) location).get("time_zone"))
    .orElse(null);

  if (timeZone == null || timeZone.toString().isEmpty()) {
    System.out.println(device.getDeviceId());
  }
}
```

```go Go theme={"dark"}
package main

import (
	"context"
	"fmt"
	"os"

	api "github.com/seamapi/go"
	seamclient "github.com/seamapi/go/client"
)

func main() {
	client := seamclient.NewClient(
		seamclient.WithApiKey(os.Getenv("SEAM_API_KEY")),
	)

	// List Schlage locks
	devices, err := client.Devices.List(
		context.Background(),
		&api.DevicesListRequest{
			DeviceType: api.DeviceTypeSchlageLock.Ptr(),
		},
	)
	if err != nil {
		panic(err)
	}

	// Keep the locks whose time zone is unknown.
	// The Go SDK only exposes the deprecated location.timezone field.
	for _, device := range devices {
		if device.Location == nil || device.Location.Timezone == nil || *device.Location.Timezone == "" {
			fmt.Println(device.DeviceId)
		}
	}
}
```

```bash Seam CLI theme={"dark"}
seam devices list --device-type schlage_lock |
  jq -r '.devices[] | select((.location.time_zone // "") == "") | .device_id'
```

> [!NOTE]
>
> `/devices/list` returns results in pages. If you have many devices, see
> [Pagination](/docs/api/pagination.md) to retrieve all of them.

***

## Set a Lock's Time Zone

To set the time zone for one or more locks, use [`/devices/report_provider_metadata`](/docs/api/devices/report_provider_metadata). Set `schlage_metadata.time_zone` for each lock to its IANA time zone. You can include multiple locks in one request:

```javascript JavaScript theme={"dark"}
import { Seam } from 'seam'

const seam = new Seam()

await seam.devices.reportProviderMetadata({
  devices: [
    {
      device_id: '11111111-1111-1111-1111-111111111111',
      schlage_metadata: { time_zone: 'America/New_York' },
    },
    {
      device_id: '22222222-2222-2222-2222-222222222222',
      schlage_metadata: { time_zone: 'America/Phoenix' },
    },
  ],
})
```

```bash cURL theme={"dark"}
curl -X 'POST' \
  'https://connect.getseam.com/devices/report_provider_metadata' \
  -H 'accept: application/json' \
  -H "Authorization: Bearer ${SEAM_API_KEY}" \
  -H 'Content-Type: application/json' \
  -d '{
    "devices": [
      {
        "device_id": "11111111-1111-1111-1111-111111111111",
        "schlage_metadata": { "time_zone": "America/New_York" }
      },
      {
        "device_id": "22222222-2222-2222-2222-222222222222",
        "schlage_metadata": { "time_zone": "America/Phoenix" }
      }
    ]
  }'
```

```python Python theme={"dark"}
from seam import Seam

seam = Seam()

seam.devices.report_provider_metadata(
  devices=[
    {
      "device_id": "11111111-1111-1111-1111-111111111111",
      "schlage_metadata": {"time_zone": "America/New_York"},
    },
    {
      "device_id": "22222222-2222-2222-2222-222222222222",
      "schlage_metadata": {"time_zone": "America/Phoenix"},
    },
  ]
)
```

```ruby Ruby theme={"dark"}
require "seam"

seam = Seam.new()

seam.devices.report_provider_metadata(
  devices: [
    {
      device_id: "11111111-1111-1111-1111-111111111111",
      schlage_metadata: { time_zone: "America/New_York" }
    },
    {
      device_id: "22222222-2222-2222-2222-222222222222",
      schlage_metadata: { time_zone: "America/Phoenix" }
    }
  ]
)
```

```php PHP theme={"dark"}
<?php
require 'vendor/autoload.php';

use Seam\Seam;

$seam = new Seam();

$seam->devices->report_provider_metadata(
  devices: [
    [
      "device_id" => "11111111-1111-1111-1111-111111111111",
      "schlage_metadata" => ["time_zone" => "America/New_York"],
    ],
    [
      "device_id" => "22222222-2222-2222-2222-222222222222",
      "schlage_metadata" => ["time_zone" => "America/Phoenix"],
    ],
  ]
);
```

```csharp C# theme={"dark"}
using System.Collections.Generic;
using Seam.Api;
using Seam.Client;

var seam = new SeamClient(apiToken: Environment.GetEnvironmentVariable("SEAM_API_KEY"));

seam.Devices.ReportProviderMetadata(
  devices: new List<Devices.ReportProviderMetadataRequestDevices>
  {
    new Devices.ReportProviderMetadataRequestDevices(
      deviceId: "11111111-1111-1111-1111-111111111111",
      schlageMetadata: new Devices.ReportProviderMetadataRequestDevicesSchlageMetadata(
        timeZone: Devices.ReportProviderMetadataRequestDevicesSchlageMetadata.TimeZoneEnum.AmericaNewYork
      )
    ),
    new Devices.ReportProviderMetadataRequestDevices(
      deviceId: "22222222-2222-2222-2222-222222222222",
      schlageMetadata: new Devices.ReportProviderMetadataRequestDevicesSchlageMetadata(
        timeZone: Devices.ReportProviderMetadataRequestDevicesSchlageMetadata.TimeZoneEnum.AmericaPhoenix
      )
    ),
  }
);
```

```java Java theme={"dark"}
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

// The Seam Java SDK (0.2.0) has no method for /devices/report_provider_metadata,
// so this example calls the endpoint with the JDK HTTP client (Java 15+).
String body = """
  {
    "devices": [
      {
        "device_id": "11111111-1111-1111-1111-111111111111",
        "schlage_metadata": { "time_zone": "America/New_York" }
      },
      {
        "device_id": "22222222-2222-2222-2222-222222222222",
        "schlage_metadata": { "time_zone": "America/Phoenix" }
      }
    ]
  }
  """;

HttpRequest request = HttpRequest.newBuilder()
  .uri(URI.create("https://connect.getseam.com/devices/report_provider_metadata"))
  .header("Authorization", "Bearer " + System.getenv("SEAM_API_KEY"))
  .header("Content-Type", "application/json")
  .POST(HttpRequest.BodyPublishers.ofString(body))
  .build();

HttpResponse<String> response = HttpClient.newHttpClient()
  .send(request, HttpResponse.BodyHandlers.ofString());

if (response.statusCode() != 200) {
  throw new RuntimeException("Seam API error: " + response.body());
}
```

```go Go theme={"dark"}
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"os"
)

// The Seam Go SDK (v0.6.1) has no method for /devices/report_provider_metadata,
// so this example calls the endpoint with net/http.
func main() {
	body, err := json.Marshal(map[string]any{
		"devices": []map[string]any{
			{
				"device_id":        "11111111-1111-1111-1111-111111111111",
				"schlage_metadata": map[string]string{"time_zone": "America/New_York"},
			},
			{
				"device_id":        "22222222-2222-2222-2222-222222222222",
				"schlage_metadata": map[string]string{"time_zone": "America/Phoenix"},
			},
		},
	})
	if err != nil {
		panic(err)
	}

	req, err := http.NewRequest(
		http.MethodPost,
		"https://connect.getseam.com/devices/report_provider_metadata",
		bytes.NewReader(body),
	)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("SEAM_API_KEY"))
	req.Header.Set("Content-Type", "application/json")

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()

	if res.StatusCode != http.StatusOK {
		errorBody, _ := io.ReadAll(res.Body)
		panic(fmt.Sprintf("Seam API error: %s", errorBody))
	}
}
```

```bash Seam CLI theme={"dark"}
seam devices report-provider-metadata --raw '{
  "devices": [
    {
      "device_id": "11111111-1111-1111-1111-111111111111",
      "schlage_metadata": { "time_zone": "America/New_York" }
    },
    {
      "device_id": "22222222-2222-2222-2222-222222222222",
      "schlage_metadata": { "time_zone": "America/Phoenix" }
    }
  ]
}'
```

> [!NOTE]
>
> The Java and Go SDKs don't include a method for
> `/devices/report_provider_metadata`, so the Java and Go examples call the
> endpoint over HTTP.

Keep the following in mind:

* **Use IANA time zone names**, such as `America/Chicago` or `America/Phoenix`. Abbreviations such as `EST` and offsets such as `-05:00` aren't accepted.
* **All devices in a request succeed or fail together.** If Seam can't update one of the devices, for example because its `device_id` doesn't match a Schlage lock in your workspace, Seam doesn't update any of them.
* **Seam doesn't overwrite a time zone that you set.** Seam only infers a time zone for locks that don't have one.
* **You can change the time zone at any time** by calling `/devices/report_provider_metadata` again.

***

## What Changes After You Set the Time Zone

After you set a lock's time zone:

* `device.location.time_zone` contains the time zone.
* Seam removes the `time_frame_adjusted_for_unknown_time_zone` warning from the lock's access codes.
* Seam programs time-bound codes with the exact times you requested, on both sides of any DST change.

Setting the time zone doesn't reprogram codes that are already on the lock. Seam programs time-bound codes onto the lock up to 72 hours before their `starts_at`, so any code that Seam has already programmed keeps the schedule it was programmed with, including any buffer. To get exact times for codes that cross the next DST change, set the time zone at least 72 hours before those codes start. For more information, see [Native Scheduling](/docs/low-level-apis/smart-locks/access-codes/index.md#native-scheduling).

***

## Choose the Correct Time Zone

A wrong time zone is worse than no time zone. If you set a time zone that doesn't match the lock's location, Seam programs every time-bound code on the lock at the wrong local time, which can lock guests out.

* **Base the time zone on the property's address**, not on the state or country alone. Several US states, including Florida, Indiana, Kentucky, Tennessee, and Texas, span more than one time zone.
* **Use the time zone for locations that don't observe DST.** For example, use `America/Phoenix` for most of Arizona, not `America/Denver`.
* **Find the right IANA name** in the [list of tz database time zones](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).

***

## Next Steps

* [Schlage Locks and Daylight Saving Time](/docs/device-and-system-integration-guides/schlage-locks/schlage-locks-daylight-savings-time-adjustments.md)
* [Get started with Schlage Locks](/docs/device-and-system-integration-guides/schlage-locks/get-started-with-schlage-locks.md)
* [`/devices/report_provider_metadata` API reference](/docs/api/devices/report_provider_metadata)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.