# Creating Access Codes

## Overview

This guide explains how to create online access codes on an online smart lock. With the [Access Codes](https://docs.seam.co/latest/~/revisions/EtRwCx0I5gXpQr7FnC9J/api/access_codes) API, generate PIN codes on a door lock and share it with visitors, allowing them keyless access.

Seam supports programming two types of online access codes for online door locks:

1. **Ongoing**: Ideal for residents or long-term users. Ongoing codes remain active on a device until removed. Create one by omitting both `starts_at` and `ends_at`. To remove the code, use the [Delete Access Code](https://docs.seam.co/latest/~/revisions/EtRwCx0I5gXpQr7FnC9J/api/access_codes/delete) endpoint.
2. **Time Bound**: Suitable for temporary access like guest visits or service appointments. These codes operate between a designated `starts_at` and `ends_at` time window, granting access only during that period.

{% hint style="info" %}
For more information about creating offline access codes, see [Managing Offline Access Codes](https://docs.seam.co/latest/~/revisions/EtRwCx0I5gXpQr7FnC9J/capability-guides/smart-locks/access-codes/offline-access-codes).
{% endhint %}

***

## Before You Begin: Confirm Capabilities

Before you attempt to create an [online](https://docs.seam.co/latest/~/revisions/EtRwCx0I5gXpQr7FnC9J/capability-guides/smart-locks/access-codes/..#what-is-an-access-code) or [offline](https://docs.seam.co/latest/~/revisions/EtRwCx0I5gXpQr7FnC9J/capability-guides/smart-locks/access-codes/..#offline-access-codes) access code, 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](https://docs.seam.co/latest/~/revisions/EtRwCx0I5gXpQr7FnC9J/device-and-system-capabilities#capability-flags) for the device:

* `device.can_program_online_access_codes`
* `device.can_program_offline_access_codes`

Use [Get Device](https://docs.seam.co/latest/~/revisions/EtRwCx0I5gXpQr7FnC9J/api/devices/get) (or [Get Lock](https://docs.seam.co/latest/~/revisions/EtRwCx0I5gXpQr7FnC9J/api/locks/get)) 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 create an access code.

If either of these capability flags is `false` or not present, you can view the [properties](https://docs.seam.co/latest/~/revisions/EtRwCx0I5gXpQr7FnC9J/api/devices#device-properties) of the device, [errors](https://docs.seam.co/latest/~/revisions/EtRwCx0I5gXpQr7FnC9J/api/devices#device-error-types) or [warnings](https://docs.seam.co/latest/~/revisions/EtRwCx0I5gXpQr7FnC9J/api/devices#device-warning-types) for the device, and [events](https://docs.seam.co/latest/~/revisions/EtRwCx0I5gXpQr7FnC9J/api/events#event-types) related to the device to learn more about the cause of these issues. For example, you could examine the following device properties:

* `device.properties.model.has_built_in_keypad`
* `device.properties.model.can_connect_accessory_keypad`
* `device.properties.accessory_keypad.is_connected`
* `device.properties.accessory_keypad.battery.level`

In addition, you could look for a `device.accessory_keypad_disconnected` event.

{% tabs %}
{% tab title="Python" %}
**Request:**

```python
seam.devices.get(device_id="11111111-1111-1111-1111-444444444444")
```

**Response:**

```
Device(
  device_id='11111111-1111-1111-1111-444444444444',
  can_program_online_access_codes=True,  // You can create online access codes for this device.
  can_program_offline_access_codes=True, // You can create offline access codes for this device.
  ...
)
```

{% endtab %}

{% tab title="cURL (bash)" %}
**Request:**

```bash
# Use GET or POST.
curl -X 'GET' \
  'https://connect.getseam.com/devices/get' \
  -H 'accept: application/json' \
  -H 'Authorization: Bearer ${API_KEY}' \
  -H 'Content-Type: application/json' \
  -d '{
  "device_id": "11111111-1111-1111-1111-444444444444"
}'
```

**Response:**

```json
{
  "lock": {
    "device_id": "11111111-1111-1111-1111-444444444444",
    "can_program_online_access_codes": true,  // You can create online access codes for this device.
    "can_program_offline_access_codes": true, // You can create offline access codes for this device.
    ...
  },
  "ok": true
}
```

{% endtab %}

{% tab title="JavaScript" %}
**Request:**

```javascript
await seam.devices.get({device_id: "11111111-1111-1111-1111-444444444444"});
```

**Response:**

```json
{
  device_id: '11111111-1111-1111-1111-444444444444',
  can_program_online_access_codes: true,  // You can create online access codes for this device.
  can_program_offline_access_codes: true, // You can create offline access codes for this device.
  ...
}
```

{% endtab %}

{% tab title="Ruby" %}
**Request:**

```ruby
client.devices.get(device_id: "11111111-1111-1111-1111-444444444444")
```

**Response:**

```
<Seam::Device:0x00438
  device_id="11111111-1111-1111-1111-444444444444"
  can_program_online_access_codes=true  // You can create online access codes for this device.
  can_program_offline_access_codes=true // You can create offline access codes for this device.
  ...
>
```

{% endtab %}

{% tab title="PHP" %}
**Request:**

```php
$seam->devices->get(device_id: "11111111-1111-1111-1111-444444444444");
```

**Response:**

```json
{
  "device_id": "11111111-1111-1111-1111-444444444444",
  "can_program_online_access_codes": true,  // You can create online access codes for this device.
  "can_program_offline_access_codes": true, // You can create offline access codes for this device.
  ...
}
```

{% endtab %}

{% tab title="C#" %}
**Request:**

```csharp
seam.Devices.Get(deviceId: "11111111-1111-1111-1111-444444444444");
```

**Response:**

```
{
  "device_id": "11111111-1111-1111-1111-444444444444",
  "can_program_online_access_codes": true,  // You can create online access codes for this device.
  "can_program_offline_access_codes": true, // You can create offline access codes for this device.
  ...
}
```

{% endtab %}

{% tab title="Java" %}
**Request:**

```java
seam.devices()
  .get(DevicesGetRequest.builder()
    .deviceId("11111111-1111-1111-1111-444444444444")
    .build());
```

**Response:**

```json
{
  "device_id": "11111111-1111-1111-1111-444444444444",
  "can_program_online_access_codes": true,  // You can create online access codes for this device.
  "can_program_offline_access_codes": true, // You can create offline access codes for this device.
  ...
}
```

{% endtab %}

{% tab title="Go" %}
**Request:**

```go
device, uErr := client.Devices.Get(
  context.Background(),
  &api.DevicesGetRequest{
    DeviceId: "11111111-1111-1111-1111-444444444444",
  })
```

**Response:**

```json
{
  "device_id": "11111111-1111-1111-1111-444444444444",
  "can_program_online_access_codes": true,  // You can create online access codes for this device.
  "can_program_offline_access_codes": true, // You can create offline access codes for this device.
  ...
}
```

{% endtab %}
{% endtabs %}

***

## Programming an Ongoing Online Access Code

Ongoing online access codes are ideal for long-term users that wish to keep the same code. Ongoing codes remain active on a device until removed.

<figure><img src="https://2727122207-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxnN2A67918om1UthYWsF%2Fuploads%2F4rlp1kurtY2DIZT1vptf%2Fongoing-access-code-light.png?alt=media&#x26;token=81231074-6892-4626-aa03-194a15d26669" alt=""><figcaption><p>Timeline of an ongoing access code. The code remains active, until you use the Seam API to remove it.</p></figcaption></figure>

### 1. Create an Ongoing Online Access Code

Set an ongoing online access code by providing the `device_id` of the smart lock on which you want to [create an access code](https://docs.seam.co/latest/~/revisions/EtRwCx0I5gXpQr7FnC9J/api/access_codes/create). Assign an optional `name` to the access code for easier identification within the [Seam Console](https://console.seam.co) and smart lock app.

To customize the PIN code, specify a desired PIN for the `code` property. If you do not specify a `code`, you can set the `preferred_code_length`, and Seam generates a code of this length if the affected device supports the specified preferred code length. See [Access Code Requirements for Door Locks](https://docs.seam.co/latest/~/revisions/EtRwCx0I5gXpQr7FnC9J/capability-guides/smart-locks/access-codes/access-code-requirements-for-door-locks) to understand any requirements specific to the door lock.

{% tabs %}
{% tab title="Python" %}
**Request:**

```python
# Get the device.
device = seam.devices.get(
  device_id="11111111-1111-1111-1111-444444444444"
)

# Confirm that the device supports online access codes.
if device.can_program_online_access_codes:
  # Create the ongoing online access code.
  seam.access_codes.create(
    device_id = device.device_id,
    name = "my ongoing code",
    code = "1234"
  )
```

**Response:**

```
AccessCode(
  access_code_id='11111111-1111-1111-1111-555555555555',
  device_id='11111111-1111-1111-1111-444444444444',
  type='ongoing',
  code='1234',
  name='my ongoing code',
  ...
)
```

{% endtab %}

{% tab title="cURL (bash)" %}
**Request:**

```bash
# Get the device.
device=$(
  # Use GET or POST.
  curl -X 'GET' \
    'https://connect.getseam.com/devices/get' \
    -H 'accept: application/json' \
    -H "Authorization: Bearer ${API_KEY}" \
    -H 'Content-Type: application/json' \
    -d '{
      "device_id": "11111111-1111-1111-1111-444444444444"
  }')

# Confirm that the device supports online access codes.
if  $(jq -r '.device.can_program_online_access_codes' <<< ${device}); then \
  # Create the ongoing online access code.
  curl -X 'POST' \
    'https://connect.getseam.com/access_codes/create' \
    -H 'accept: application/json' \
    -H "Authorization: Bearer ${API_KEY}" \
    -H 'Content-Type: application/json' \
    -d "{
      \"device_id\": \"$(jq -r '.device.device_id' <<< ${device})\",
      \"name\": \"my ongoing code\",
      \"code\": \"1234\"
  }";
fi
```

**Response:**

```json
{
  "action_attempt":{
    "status":"pending",
    "action_type":"CREATE_ACCESS_CODE",
    "action_attempt_id":"11111111-2222-3333-4444-555555555555",
    "result":null,
    "error":null
  },
  "access_code":{
    "access_code_id":"11111111-1111-1111-1111-555555555555",
    "device_id":"11111111-1111-1111-1111-444444444444",
    "name":"my ongoing code",
    "code":"1234",
    "type":"ongoing",
    ...
  },
  "ok":true
}
```

{% endtab %}

{% tab title="JavaScript" %}
**Request:**

```javascript
// Get the device.
const device = await seam.devices.get({
  device_id: "11111111-1111-1111-1111-444444444444"
});

// Confirm that the device supports online access codes.
if (device.can_program_online_access_codes) {
  // Create the ongoing online access code.
  await seam.accessCodes.create({
    device_id: device.device_id,
    name: "my ongoing code",
    code: "1234"
  })
};
```

**Response:**

```json
{
  access_code_id: '11111111-1111-1111-1111-555555555555',
  device_id: '11111111-1111-1111-1111-444444444444',
  name: 'my ongoing code',
  code: '1234',
  type: 'ongoing',
  ...
}
```

{% endtab %}

{% tab title="Ruby" %}
**Request:**

```ruby
# Get the device.
device = client.devices.get(device_id: "11111111-1111-1111-1111-444444444444")

# Confirm that the device supports online access codes.
if (device.can_program_online_access_codes)
  # Create the ongoing online access code.
  client.access_codes.create(
    device_id: device.device_id,
    name: "my ongoing code",
    code: "1234"
  )
end
```

**Response:**

```
<Seam::AccessCode:0x00460
  access_code_id="11111111-1111-1111-1111-555555555555"
  device_id="11111111-1111-1111-1111-444444444444"
  name="my ongoing code"
  code="1234"
  type="ongoing"
  ...
>
```

{% endtab %}

{% tab title="PHP" %}
**Request:**

```php
// Get the device.
$device = $seam->devices->get(device_id: "11111111-1111-1111-1111-444444444444");

// Confirm that the device supports online access codes.
if ($device->can_program_online_access_codes) {
  // Create the ongoing online access code.
  $seam->access_codes->create(
    device_id: $device->device_id,
    name: "my ongoing code",
    code: "1234"
  );
}
```

**Response:**

```json
{
  "access_code_id": "11111111-1111-1111-1111-555555555555",
  "device_id": "11111111-1111-1111-1111-444444444444",
  "name": "my ongoing code",
  "type": "ongoing",
  "code": "1234",
  ...
}
```

{% endtab %}

{% tab title="C#" %}
**Request:**

```csharp
// Get the device.
Device device = seam.Devices.Get(deviceId: "11111111-1111-1111-1111-444444444444");

// Confirm that the device supports online access codes.
if (device.CanProgramOnlineAccessCodes == true) {
  // Create the ongoing online access code.
  seam.AccessCodes.Create(
    deviceId: device.DeviceId,
    name: "my ongoing code",
    code: "1234"
  );
}
```

**Response:**

```json
{
  "type": "ongoing",
  "access_code_id": "11111111-1111-1111-1111-555555555555",
  "device_id": "11111111-1111-1111-1111-444444444444",
  "name": "my ongoing code",
  "code": "1234",
  ...
}
```

{% endtab %}

{% tab title="Java" %}
**Request:**

```java
// Get the device.
Device device = seam.devices()
  .get(DevicesGetRequest.builder()
    .deviceId("11111111-1111-1111-1111-444444444444")
    .build());

// Confirm that the device supports online access codes.
if (device.getCanProgramOnlineAccessCodes())
{
  // Create the ongoing online access code.
  seam.accessCodes()
    .create(AccessCodesCreateRequest.builder()
      .deviceId(device.getDeviceId())
      .name("my ongoing code")
      .code("1234")
      .build());
}
```

**Response:**

```json
{
  "access_code_id" : "11111111-1111-1111-1111-555555555555",
  "device_id" : "11111111-1111-1111-1111-444444444444",
  "name" : "my ongoing code",
  "code" : "1234",
  "type" : "ongoing",
  ...
}
```

{% endtab %}

{% tab title="Go" %}
**Request:**

```go
// Get the device.
device, uErr := client.Devices.Get(
  context.Background(),
  &api.DevicesGetRequest{
    DeviceId: api.String("11111111-1111-1111-1111-444444444444"),
  })

// Confirm that the device supports online access codes.
if *device.CanProgramOnlineAccessCodes {
  // Create the ongoing online access code.
  client.AccessCodes.Create(
    context.Background(),
    &api.AccessCodesCreateRequest{
      DeviceId: device.DeviceId,
      Name: api.String("my ongoing code"),
      Code: api.String("1234"),
    },
  )
}

if uErr != nil {
    return uErr
}

return nil
```

**Response:**

```json
{
  "access_code_id": "11111111-1111-1111-1111-555555555555",
  "device_id": "11111111-1111-1111-1111-444444444444",
  "name": "my ongoing code",
  "code": "1234",
  "type": "ongoing",
  ...
}
```

{% endtab %}
{% endtabs %}

### 2. Verify Successful Ongoing Code Programming

Seam may encounter some problems when setting an access code onto the lock. This could be due to weak internet connectivity, a low battery in the door lock, or someone unplugging the bridge that links the lock to the internet. **Given these potential challenges, it's essential to verify that a code has been successfully programmed on to the lock** to prevent unexpected complications later.

There are two methods to verify that an ongoing access code has been set on the device:

* **Polling**: continuously query the access code until its `status` is updated
* **Webhook**: wait for updates to arrive via webhook requests from the Seam API

### **Polling Method**

Use the `access_code` reference returned by the create function to call the [Get Access Code](https://docs.seam.co/latest/~/revisions/EtRwCx0I5gXpQr7FnC9J/api/access_codes/get) function. A basic implementation would involve polling this endpoint until the `status` of the access code updates to `set`.

If the `status` remains `setting` for a very long time, or if the `access_code` object contains any `warnings` or `errors` properties, consult [the guide on "Troubleshooting Access Code Issues"](https://docs.seam.co/latest/~/revisions/EtRwCx0I5gXpQr7FnC9J/capability-guides/smart-locks/access-codes/troubleshooting-access-code-issues) for further guidance.

<figure><img src="https://2727122207-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxnN2A67918om1UthYWsF%2Fuploads%2FjYSLfnqJxzMdXUvPPPWR%2Fongoing-access-code-polling-verification-dark.png?alt=media&#x26;token=45014375-1a5e-4999-ba04-79d37512c467" alt=""><figcaption><p>Illustration of the polling verification step for an ongoing access code</p></figcaption></figure>

### **Webhook Events Method**

To avoid polling, monitor for incoming Seam webhook events related to the code status:

* The `access_code.set_on_device` event indicates the successful setting of the access code on the device.
* The `access_code.failed_to_set_on_device` or `access_code.delay_in_setting_on_device` events indicate a delay or failure.

In the event of delay or failure, refer to [the "Troubleshooting access code issues" guide](https://docs.seam.co/latest/~/revisions/EtRwCx0I5gXpQr7FnC9J/capability-guides/smart-locks/access-codes/troubleshooting-access-code-issues) for assistance and mitigation strategies.

<figure><img src="https://2727122207-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxnN2A67918om1UthYWsF%2Fuploads%2FEfWsztZQyrLI6K4h7XpM%2Fongoing-access-code-webhook-verification-dark.png?alt=media&#x26;token=81aea687-0111-4c2a-b11a-8f5a0b9681d1" alt=""><figcaption><p>Illustration of the webhook verification method for an ongoing access code</p></figcaption></figure>

***

## Scheduling Time-Bound Online Access Codes

Time-bound online access codes are suitable for temporary access, like guest visits or service appointments. These codes operate between designated `starts_at` and `ends_at` timestamps, granting access only during that period. Seam automatically ensures that the code is programmed on the device at the `starts_at` time and unprogrammed at the `ends_at` time.

<figure><img src="https://2727122207-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxnN2A67918om1UthYWsF%2Fuploads%2FBnwsn561Zi3bOmBgp9gE%2Ftime-bound-access-code-light.png?alt=media&#x26;token=b39f0ec6-e2ed-4247-b2a4-9c186c27a494" alt=""><figcaption><p>Timeline of an time-bound access code. The code remains active until the ends_at timestamp that you configured using the Seam API.</p></figcaption></figure>

### 1. Create a Time-Bound Online Access Code

To set a time-bound online access code, provide the `device_id` of the smart lock on which you want to program a code, along with `starts_at` and `ends_at` [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) timestamps to define the active time window for the code. For more details, see the [Create Access Code](https://docs.seam.co/latest/~/revisions/EtRwCx0I5gXpQr7FnC9J/api/access_codes/create) endpoint.

As with ongoing codes, you can assign an optional `name` to the access code. A clear name helps users to identify the access code quickly within their smart lock app.

Similarly, to customize the PIN code, specify a desired PIN in the `code` property. If you do not specify a `code`, you can set the `preferred_code_length`, and Seam generates a code of this length if the affected device supports the specified preferred code length. See the [Access Code Requirements for Door Locks](https://docs.seam.co/latest/~/revisions/EtRwCx0I5gXpQr7FnC9J/capability-guides/smart-locks/access-codes/access-code-requirements-for-door-locks) to understand any requirements specific to the door lock brand.

{% tabs %}
{% tab title="Python" %}
**Request:**

```python
# Get the device.
device = seam.devices.get(
  device_id="11111111-1111-1111-1111-444444444444"
)

# Confirm that the device supports online access codes.
if device.can_program_online_access_codes:
  # Create the time-bound online access code.
  seam.access_codes.create(
    device_id = device.device_id,
    name = "my time-bound code",
    starts_at = "2025-01-01T16:00:00Z",
    ends_at = "2025-01-22T12:00:00Z",
    code = "2345"
  )
```

**Response:**

```
AccessCode(
  access_code_id='11111111-1111-1111-1111-666666666666',
  device_id='11111111-1111-1111-1111-444444444444',
  type='time_bound',
  code='2345',
  starts_at='2025-01-01T16:00:00.000Z',
  ends_at='2025-01-22T12:00:00.000Z',
  name='my time-bound code',
  ...
)
```

{% endtab %}

{% tab title="cURL (bash)" %}
**Request:**

```sh
# Get the device.
device=$(
  # Use GET or POST.
  curl -X 'GET' \
    'https://connect.getseam.com/devices/get' \
    -H 'accept: application/json' \
    -H "Authorization: Bearer ${API_KEY}" \
    -H 'Content-Type: application/json' \
    -d '{
      "device_id": "11111111-1111-1111-1111-444444444444"
  }')

# Confirm that the device supports online access codes.
if  $(jq -r '.device.can_program_online_access_codes' <<< ${device}); then \
  # Create the time-bound online access code.
  curl -X 'POST' \
    'https://connect.getseam.com/access_codes/create' \
    -H 'accept: application/json' \
    -H "Authorization: Bearer ${API_KEY}" \
    -H 'Content-Type: application/json' \
    -d "{
      \"device_id\": \"$(jq -r '.device.device_id' <<< ${device})\",
      \"name\": \"my time-bound code\",
      \"starts_at\": \"2025-01-01T16:00:00Z\",
      \"ends_at\": \"2025-01-22T12:00:00Z\",
      \"code\": \"2345\"
  }";
fi
```

**Response:**

```json
{
  "action_attempt": {
    "status": "pending",
    "action_type": "CREATE_ACCESS_CODE",
    "action_attempt_id": "11111111-2222-3333-4444-555555555555",
    "result": null,
    "error": null
  },
  "access_code": {
    "access_code_id": "11111111-1111-1111-1111-666666666666",
    "device_id": "11111111-1111-1111-1111-444444444444",
    "name": "my time-bound code",
    "code": "2345",
    "type": "time_bound",
    "starts_at": "2025-01-01T16:00:00.000Z",
    "ends_at": "2025-01-22T12:00:00.000Z",
    ...
  },
  "ok": true
}
```

{% endtab %}

{% tab title="JavaScript" %}
**Request:**

```javascript
// Get the device.
const device = await seam.devices.get({
  device_id: "11111111-1111-1111-1111-444444444444"
});

// Confirm that the device supports online access codes.
if (device.can_program_online_access_codes) {
  // Create the time-bound online access code.
  await seam.accessCodes.create({
    device_id: device.device_id,
    name: "my time-bound code",
    starts_at: "2025-01-01T16:00:00Z",
    ends_at: "2025-01-22T12:00:00Z",
    code: "2345"
  })
};
```

**Response:**

```json
{
  access_code_id: '11111111-1111-1111-1111-666666666666',
  device_id: '11111111-1111-1111-1111-444444444444',
  name: 'my time-bound code',
  code: '2345',
  type: 'time_bound',
  starts_at: '2025-01-01T16:00:00.000Z',
  ends_at: '2025-01-22T12:00:00.000Z',
  ...
}
```

{% endtab %}

{% tab title="Ruby" %}
**Request:**

```ruby
# Get the device.
device = client.devices.get(device_id: "11111111-1111-1111-1111-444444444444")

# Confirm that the device supports online access codes.
if (device.can_program_online_access_codes)
  # Create the time-bound online access code.
  client.access_codes.create(
    device_id: device.device_id,
    name: "my time-bound code",
    starts_at: "2025-01-01T16:00:00Z",
    ends_at: "2025-01-22T12:00:00Z",
    code: "2345"
  )
end
```

**Response:**

```
<Seam::AccessCode:0x00438
  access_code_id="11111111-1111-1111-1111-666666666666"
  device_id="11111111-1111-1111-1111-444444444444"
  name="my time-bound code"
  code="2345"
  type="time_bound"
  starts_at=2025-01-01 16:00:00 UTC
  ends_at=2025-01-22 12:00:00 UTC
  ...
>
```

{% endtab %}

{% tab title="PHP" %}
**Request:**

```php
// Get the device.
$device = $seam->devices->get(device_id: "11111111-1111-1111-1111-444444444444");

// Confirm that the device supports online access codes.
if ($device->can_program_online_access_codes) {
  // Create the time-bound online access code.
  $seam->access_codes->create(
    device_id: $device->device_id,
    name: "my time-bound code",
    starts_at:  "2025-01-01T16:00:00Z",
    ends_at: "2025-01-22T12:00:00Z",
    code: "2345"
  );
}
```

**Response:**

```json
{
  "access_code_id": "11111111-1111-1111-1111-666666666666",
  "device_id": "11111111-1111-1111-1111-444444444444",
  "name": "my time-bound code",
  "type": "time_bound",
  "starts_at": "2025-01-01T16:00:00.000Z",
  "ends_at": "2025-01-22T12:00:00.000Z",
  "code": "2345",
}
```

{% endtab %}

{% tab title="C#" %}
**Request:**

```csharp
// Get the device.
Device device = seam.Devices.Get(deviceId: "11111111-1111-1111-1111-444444444444");

// Confirm that the device supports online access codes.
if (device.CanProgramOnlineAccessCodes == true) {
  // Create the time-bound online access code.
  seam.AccessCodes.Create(
    deviceId: device.DeviceId,
    name: "my time-bound code",
    startsAt: "2025-01-01T16:00:00Z",
    endsAt: "2025-01-22T12:00:00Z",
    code: "2345"
  );
}
```

**Response:**

```json
{
  "type": "time_bound",
  "access_code_id": "11111111-1111-1111-1111-666666666666",
  "device_id": "11111111-1111-1111-1111-444444444444",
  "name": "my time-bound code",
  "starts_at": "2025-01-01T16:00:00Z",
  "ends_at": "2025-01-22T12:00:00Z",
  "code": "2345",
  ...
}
```

{% endtab %}

{% tab title="Java" %}
**Request:**

```java
// Get the device.
Device device = seam.devices()
  .get(DevicesGetRequest.builder()
    .deviceId("11111111-1111-1111-1111-444444444444")
    .build());

// Confirm that the device supports online access codes.
if (device.getCanProgramOnlineAccessCodes())
{
  // Create the time-bound online access code.
  seam.accessCodes()
    .create(AccessCodesCreateRequest.builder()
      .deviceId(device.getDeviceId())
      .name("my time-bound code")
      .startsAt("2025-01-01T16:00:00Z")
      .endsAt("2025-01-22T12:00:00Z")
      .code("2345")
      .build());
}
```

**Response:**

```json
{
  "access_code_id" : "11111111-1111-1111-1111-666666666666",
  "device_id" : "11111111-1111-1111-1111-444444444444",
  "name" : "my time-bound code",
  "code" : "2345",
  "type" : "time_bound",
  "starts_at" : "2025-01-01T16:00:00Z",
  "ends_at" : "2025-01-22T12:00:00Z",
  ...
}
```

{% endtab %}

{% tab title="Go" %}
**Request:**

```go
// Get the device.
device, uErr := client.Devices.Get(
  context.Background(),
  &api.LocksGetRequest{
    DeviceId: api.String("11111111-1111-1111-1111-444444444444"),
  })

// Confirm that the device supports online access codes.
if *device.CanProgramOnlineAccessCodes {
  // Create the time-bound online access code.
  client.AccessCodes.Create(
    context.Background(),
    &api.AccessCodesCreateRequest{
      DeviceId: device.DeviceId,
      Name: api.String("my time-bound code"),
      StartsAt: api.String("2025-01-01T16:00:00Z"),
      EndsAt: api.String("2025-01-22T12:00:00Z"),
      Code: api.String("2345"),
    },
  )
}

if uErr != nil {
    return uErr
}

return nil
```

**Response:**

```json
{
  "access_code_id": "11111111-1111-1111-1111-666666666666",
  "device_id": "11111111-1111-1111-1111-444444444444",
  "name": "my time-bound code",
  "code": "2345",
  "type": "time_bound",
  "starts_at": "2025-01-01T16:00:00.000Z",
  "ends_at": "2025-01-22T12:00:00.000Z",
  ...
}
```

{% endtab %}
{% endtabs %}

### 2. Verify Successful Time-Bound Code Programming

The [lifecycle of a time-bound access code](https://docs.seam.co/latest/~/revisions/EtRwCx0I5gXpQr7FnC9J/capability-guides/smart-locks/access-codes/lifecycle-of-access-codes) is marked by distinct phases:

1. `Unset`: When initially created on Seam, the access code remains in an `unset` state, indicating it has not yet been programmed onto the door lock due to its future activation time.
2. `Setting`: As the scheduled `starts_at` time approaches, Seam initiates the process of programming the code onto the lock, transitioning the code's `status` to `setting`.
3. `Set`: Upon successful programming, the status updates to `set`, signaling that the code is loaded onto the lock, and may grant the designated user the ability to unlock the door.

<figure><img src="https://2727122207-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxnN2A67918om1UthYWsF%2Fuploads%2FXZOQKTremAvTrMQcIcKT%2Fstate-sequence-for-access-codes-lifecycle-dark.png?alt=media&#x26;token=392f3e03-87eb-4cb0-affe-c0afcf1b5f97" alt=""><figcaption><p>Life-cycle of a time-bound access code</p></figcaption></figure>

On door locks that support [natively scheduled](https://docs.seam.co/latest/~/revisions/EtRwCx0I5gXpQr7FnC9J/capability-guides/smart-locks/access-codes/..#native-scheduling) access codes, Seam will preload the access code into the device's internal memory bank **72 hours ahead** of the `starts_at` time. Even if preloaded in memory, the access code will remain in an `unset` state ahead of the `starts_at` time and await the precise activation moment to toggle its status. When the `starts_at` time arrives, the access code becomes active and transition to a `set` status, granting the designated user the ability to utilize it for entry. If there's an issue programming the natively-scheduled code by its `starts_at` time, the code's status will display as `setting`. For more information on the lifecycle of access codes, [please refer to this guide](https://docs.seam.co/latest/~/revisions/EtRwCx0I5gXpQr7FnC9J/capability-guides/smart-locks/access-codes/lifecycle-of-access-codes).

There are two methods to verify that an time-bound access code has been set on the device:

* **Polling**: continuously query the access code until its `status` is updated
* **Webhook**: wait for updates to arrive via webhook requests from the Seam API

### **Polling Method**

Use the `access_code` reference returned by the create function to call the [Get Access Code](https://docs.seam.co/latest/~/revisions/EtRwCx0I5gXpQr7FnC9J/api/access_codes/get) function. In a basic implementation, you would poll this endpoint at the `starts_at` time to check if the access code's status is updated to `set`.

If the `status` remains `setting`, or if the `access_code` object displays any `warnings` or `errors`, refer to [the "Troubleshooting Access Code Issues" guide](https://docs.seam.co/latest/~/revisions/EtRwCx0I5gXpQr7FnC9J/capability-guides/smart-locks/access-codes/troubleshooting-access-code-issues) for assistance.

<figure><img src="https://2727122207-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxnN2A67918om1UthYWsF%2Fuploads%2FzziPJt8ca8FY2N8FBpZt%2Ftimebound-access-code-polling-verification-dark.png?alt=media&#x26;token=b7fd4cbe-338f-41cc-a003-b1f42dfaf1cb" alt=""><figcaption></figcaption></figure>

### **Webhook Events Method**

To avoid polling, monitor for incoming Seam webhook events related to the code status:

* The `access_code.set_on_device` event indicates the successful setting of the access code on the device.
* The `access_code.failed_to_set_on_device` or `access_code.delay_in_setting_on_device` events indicate a delay or failure.

In the event of delay or failure, refer to [the "Troubleshooting access code issues" guide](https://docs.seam.co/latest/~/revisions/EtRwCx0I5gXpQr7FnC9J/capability-guides/smart-locks/access-codes/troubleshooting-access-code-issues) for assistance and mitigation strategies.

<figure><img src="https://2727122207-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxnN2A67918om1UthYWsF%2Fuploads%2Ftv5KDyvKhveiQ3laOrn1%2Ftimebound-access-code-webhook-verification-dark.png?alt=media&#x26;token=bca3e6e1-e96d-4cd6-8b83-62106379154c" alt=""><figcaption></figcaption></figure>
