diff --git a/docs/.gitbook/assets/akiles-logo.png b/docs/.gitbook/assets/akiles-logo.png new file mode 100644 index 00000000..cca8eb4b Binary files /dev/null and b/docs/.gitbook/assets/akiles-logo.png differ diff --git a/docs/.gitbook/assets/akiles-manufacturer-page-cover-dark.png b/docs/.gitbook/assets/akiles-manufacturer-page-cover-dark.png new file mode 100644 index 00000000..8b3837b2 Binary files /dev/null and b/docs/.gitbook/assets/akiles-manufacturer-page-cover-dark.png differ diff --git a/docs/.gitbook/assets/akiles-manufacturer-page-cover-light.png b/docs/.gitbook/assets/akiles-manufacturer-page-cover-light.png new file mode 100644 index 00000000..c2e9f900 Binary files /dev/null and b/docs/.gitbook/assets/akiles-manufacturer-page-cover-light.png differ diff --git a/docs/.gitbook/assets/akiles_connect-flow-screens_dark.png b/docs/.gitbook/assets/akiles_connect-flow-screens_dark.png new file mode 100644 index 00000000..9f173d88 Binary files /dev/null and b/docs/.gitbook/assets/akiles_connect-flow-screens_dark.png differ diff --git a/docs/.gitbook/assets/akiles_connect-flow-screens_light.png b/docs/.gitbook/assets/akiles_connect-flow-screens_light.png new file mode 100644 index 00000000..a8030b30 Binary files /dev/null and b/docs/.gitbook/assets/akiles_connect-flow-screens_light.png differ diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index 542105bd..221fb0ab 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -234,6 +234,7 @@ * [Sandbox Devices and Systems](device-guides/sandbox-and-sample-data/README.md) * [Sandbox 2N Intercoms](device-guides/sandbox-and-sample-data/2n-intercoms-sample-data.md) * [Sandbox 4SUITES Locks](device-guides/sandbox-and-sample-data/4suites-locks-sample-data.md) + * [Sandbox Akiles Locks](developer-tools/sandbox-and-sample-data/sandbox-akiles-locks.md) * [Sandbox ASSA ABLOY Credential Services](device-guides/sandbox-and-sample-data/assa-abloy-credential-service-sample-data.md) * [Sandbox ASSA ABLOY Visionline Access Control System](device-guides/sandbox-and-sample-data/assa-abloy-visionline-access-management-system-sample-data.md) * [Sandbox August Locks](device-guides/sandbox-and-sample-data/august-locks-sample-data.md) @@ -275,6 +276,8 @@ * [Get started with 2N Intercoms](device-guides/get-started-with-2n-intercoms.md) * [4SUITES Locks](device-and-system-integration-guides/4suites-locks/README.md) * [Get started with 4SUITES locks](device-and-system-integration-guides/4suites-locks/get-started-with-4suites-locks.md) +* [Akiles Locks](device-and-system-integration-guides/akiles-locks/README.md) + * [Get started with Akiles locks](device-and-system-integration-guides/akiles-locks/get-started-with-akiles-locks.md) * [ASSA ABLOY Credential Services](device-guides/assa-abloy-credential-services-credential-manager-in-development.md) * [ASSA ABLOY Visionline Access Control System](device-guides/assa-abloy-visionline-access-control-system-in-development/README.md) * [Visionline ACS Setup Instructions](device-and-system-integration-guides/assa-abloy-visionline-access-control-system-in-development/visionline-acs-setup-instructions/README.md) diff --git a/docs/api-clients/connect_webviews/README.md b/docs/api-clients/connect_webviews/README.md index 1142c728..6e2d5745 100644 --- a/docs/api-clients/connect_webviews/README.md +++ b/docs/api-clients/connect_webviews/README.md @@ -46,17 +46,18 @@ When you [create a Connect Webview](create.md), specify the desired provider cat | `noise_sensors` | Only returns provider integrations marked as noise sensors. | {% hint style="info" %} -To list all providers within a category, use the [List Device Providers](../devices/list_device_providers.md) method with the desired `provider_category` filter. +To list all providers within a category, use the [List Device Providers](../devices/list\_device\_providers.md) method with the desired `provider_category` filter. {% endhint %} ### Device Provider Keys -To list all provider keys, use the [List Device Providers](../devices/list_device_providers.md) method with no filters. +To list all provider keys, use the [List Device Providers](../devices/list\_device\_providers.md) method with no filters. | Provider Name | Device Provider Key | | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------- | | [2N](../../device-guides/2n-intercom-systems.md) | `my_2n` | | [4SUITES](../../device-and-system-integration-guides/4suites-locks/) | `four_suites` | +| [Akiles](../../device-and-system-integration-guides/akiles-locks/) | `akiles` | | [Akuvox](https://akuvox.com/) | `akuvox` | | [ASSA ABLOY Credential Service](../../device-guides/assa-abloy-credential-services-credential-manager-in-development.md) | `assa_abloy_credential_service` | | [ASSA ABLOY Visionline Access Control System](../../device-guides/assa-abloy-visionline-access-control-system-in-development/) | `visionline` | diff --git a/docs/developer-tools/sandbox-and-sample-data/sandbox-akiles-locks.md b/docs/developer-tools/sandbox-and-sample-data/sandbox-akiles-locks.md new file mode 100644 index 00000000..a5bafa69 --- /dev/null +++ b/docs/developer-tools/sandbox-and-sample-data/sandbox-akiles-locks.md @@ -0,0 +1,7 @@ +# Sandbox Akiles Locks + +Use the following set of credentials to add virtual [Akiles locks](../../device-and-system-integration-guides/akiles-locks/) to your Seam [sandbox workspace](../../core-concepts/workspaces/#sandbox-workspaces): + +| Email Address | Password | +| ---------------- | -------- | +| jane@example.com | 1234 | diff --git a/docs/device-and-system-integration-guides/akiles-locks/README.md b/docs/device-and-system-integration-guides/akiles-locks/README.md new file mode 100644 index 00000000..a1217dad --- /dev/null +++ b/docs/device-and-system-integration-guides/akiles-locks/README.md @@ -0,0 +1,98 @@ +--- +description: Guide for using Akiles locks with Seam +--- + +# Akiles Locks + +
Connect and control any Akiles device using the Seam API.

Connect and control any Akiles device using the Seam API.

+ +## Overview + +[Akiles](https://akiles.app/en) is a Barcelona-based company that produces smart lock products for the European market. These offerings include the Smart Cylinder, Roomlock, and Pinpad, as well as the Smart Controller for electrified locks and access points. Akiles also offers the Akiles Gateway and Akiles Cloud. Seam itegrates with Akiles through the Akiles Gateway to provide remote unlock functionality and access code creation and management. + +*** + +## Supported Devices + +This integration supports all Akiles locks. These locks require the [Akiles Gateway](https://akiles.app/en/products/smart-lock-system-gateway). Seam also supports the addition of the optional [Akiles Pinpad](https://akiles.app/en/products/smart-lock-system-pinpad) to enable entering access codes for devices that do not have an integrated keypad. + +The following table details the requirements for compatibility with this Seam integration: + +
CapabilityRequired Accessories
Remote unlock
  • Akiles Gateway
Access codes
  • Akiles Gateway
  • Akiles Pinpad (if the device does not have an integrated keypad)
+ +{% @seam-gitbook-plugin-v2/seam-component content="" %} + +We support the following features: + +* [Triggering web unlock actions](../../products/smart-locks/lock-and-unlock.md) +* [Programming access codes](../../products/smart-locks/access-codes/) on devices that have an integrated keypad or Akiles Pinpad + +*** + +### Device Provider Key + +To create a [Connect Webview](../../core-concepts/connect-webviews/) that enables your users to connect their Tedee devices to Seam, include the `akiles` [device provider key](../../api-clients/connect\_webviews/#device-provider-keys) in the `accepted_providers` list. For more information, see [Customize the Brands to Display in Your Connect Webview](../../core-concepts/connect-webviews/customizing-connect-webviews.md#customize-the-brands-to-display-in-your-connect-webviews). + +*** + +## Setup Instructions + +To control Akiles devices using Seam, you must prompt owners of these devices to add the Akiles Gateway and locks in the Akiles app and then connect these devices to Seam. + +### Add Devices in the Akiles App + +1. Plug in your Akiles Gateway and connect it using Ethernet. + + The LED should be blue to indicate that it is connected. +2. Before installing an Akiles Roomlock, take a picture of the QR code inside the lock body.\ + The QR code is located on the inside of the lock, opposite the keypad. This code is required to add the lock in the Akiles app. +3. Log in to the Akiles app. + + * [Web](https://web.akiles.app/login) + * [iOS](https://apps.apple.com/app/akiles/id1467888600) + * [Google Play](https://play.google.com/store/apps/details?id=app.akiles\&hl=en) + + Make sure to note your credentials for the Akiles app. +4. In the Akiles app, click the top-left menu and select **Devices**. +5. At the upper-right corner, click **Actions +** and select **New Device**. +6. Type a name for the new device and select the site with which you want to associate the device. +7. In the **Device Type** area, add the Akiles Gateway. + * Use a QR code scanner, scan the QR code on the back of the Gateway to retrieve the hardware ID number. Note that smartphone camera apps have built-in QR code scanners. + * In the **Device Type** field, paste the hardware ID number.\ + The Akiles app displays Device and Version information based on the hardware ID. + * Click **Create Device**.\ + The Akiles app creates the device representation and displays the device status. A Gateway takes a moment to connect to the Akiles server, run a firmware auto-update, and reboot. +8. Adding each Akiles lock. + * Using the photo that you took of the QR code inside the lock, scan this code to retrieve the hardware ID number. Note that smartphone photo apps are capable of scanning QR codes in photos. + * In the **Device Type** field, paste the hardware ID number.\ + The Akiles app displays Device and Version information based on the hardware ID. + * Click **Create Device**.\ + The Akiles app creates the device representation and displays that the device status is offline. +9. Connect each lock to the Gateway. + * Click the top-left menu and select **Links**.\ + By default, the Akiles app displays a link between the Gateway and server. You can check the link status in this location at any time. + * Click **Link +**. + * Clear the **Server** field to remove **Server** from **Central Device**. + * Click **Central Device** and select **Gateway**. + * **Peripheral Device** and select **Lock**. + * Click **Create Link**.\ + This link connects the lock to the Akiles server and may take several minutes to complete. It also performs firmware updates that take additional time. +10. Click the top-left menu, select **Devices**, and make sure that all devices are online. + +### Connect Akiles Devices to Seam + +Use your credentials for the Akiles app to log in to the [Seam Connect Webview](../../core-concepts/connect-webviews/) to add your devices to Seam. + +*** + +## Where to Order + +To purchase Akiles devices, contact the Akiles sales team. + +
Akiles Contact Pagehttps://akiles.app/en/contactakiles-logo.png
+ +*** diff --git a/docs/device-and-system-integration-guides/akiles-locks/get-started-with-akiles-locks.md b/docs/device-and-system-integration-guides/akiles-locks/get-started-with-akiles-locks.md new file mode 100644 index 00000000..1bc65ac6 --- /dev/null +++ b/docs/device-and-system-integration-guides/akiles-locks/get-started-with-akiles-locks.md @@ -0,0 +1,1935 @@ +--- +description: Learn how to connect and control Akiles locks with the Seam API. +--- + +# Get started with Akiles locks + +
Akiles smart locks

Akiles smart locks

+ +## Overview + +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 gives you a rapid introduction to connecting and controlling your [Akiles lock](./) 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. + +Seam supports the following Akiles locks: + +{% @seam-gitbook-plugin-v2/seam-component content="" %} + +To learn more about other IoT device and system brands that Seam supports—such as Yale, Schlage, Google Nest, and many more—visit our [integration page](https://www.seam.co/supported-devices-and-systems). + +{% hint style="success" %} +This guide shows you how to install a Seam SDK and then control your Akiles lock using the Seam API. + +Another easy way to learn about what you can do with the Seam API is to explore the [interactive Seam CLI](../../core-concepts/seam-console/seam-online-cli.md), which you can access from directly within the [Seam Console](../../core-concepts/seam-console/). + +:arrow\_forward: [Go to the Seam Console!](https://console.seam.co/) +{% endhint %} + +*** + +## Step 1: Install a Seam SDK + +Seam provides client libraries for many languages, including JavaScript, Python, Ruby, PHP, and others, as well as a Postman collection and an [OpenAPI](https://connect.getseam.com/openapi.json) spec. + +* JavaScript / TypeScript ([npm](https://www.npmjs.com/package/seam), [GitHub](https://github.com/seamapi/javascript)) +* Python ([pip](https://pypi.org/project/seam/), [GitHub](https://github.com/seamapi/python)) +* Ruby Gem ([rubygem](https://rubygems.org/gems/seamapi), [GitHub](https://github.com/seamapi/ruby)) +* PHP ([packagist](https://packagist.org/packages/seamapi/seam), [GitHub](https://github.com/seamapi/php)) +* Java ([GitHub](https://github.com/seamapi/java)) +* C# ([nuget](https://www.nuget.org/packages/Seam), [GitHub](https://github.com/seamapi/csharp)) +* Go ([GitHub](https://github.com/seamapi/go)) + +First, install a Seam SDK, as follows: + +{% tabs %} +{% tab title="JavaScript" %} +```bash +npm i seam +``` +{% endtab %} + +{% tab title="Python" %} +```bash +pip install seam +# For some development environments, use pip3 in this command instead of pip. +``` +{% endtab %} + +{% tab title="Ruby" %} +```bash +bundle add seamapi +``` +{% endtab %} + +{% tab title="PHP" %} +```bash +composer require seamapi/seam +``` +{% endtab %} + +{% tab title="Java" %} +**Gradle:** + +```gradle +// build.gradle +dependencies { + implementation 'io.github.seamapi:java:0.x.x' +} +``` + +**Maven:** + +```xml + + + io.github.seamapi + java + 0.x.x + +``` +{% endtab %} + +{% tab title="C#" %} +Install using [nuget](https://www.nuget.org/packages/Seam). +{% endtab %} + +{% tab title="Go" %} +```bash +go get github.com/seamapi/go +``` +{% endtab %} +{% endtabs %} + +Next, go to [https://console.seam.co/](https://console.seam.co/) and [sign up for Seam](../../core-concepts/seam-console/#create-a-seam-account) to get your [API key](../../core-concepts/authentication/api-keys.md). + +{% @supademo/embed demoId="vLRzYM2Nwoi4j_cH9WCNQ" url="https://app.supademo.com/demo/vLRzYM2Nwoi4j_cH9WCNQ" %} + +Then, export your API key as an environment variable. + +```bash +$ export SEAM_API_KEY=seam_test2bMS_94SrGUXuNR2JmJkjtvBQDg5c +``` + +{% hint style="info" %} +This guide uses a [sandbox workspace](../../core-concepts/workspaces/#sandbox-workspaces). You can only connect virtual devices and systems in this type of workspace. If you want to connect a real Akiles lock, use a [non-sandbox workspace](../../core-concepts/workspaces/#production-workspaces) and API key. +{% endhint %} + +*** + +## Step 2: Link your Akiles account with Seam + +To control your Akiles lock using the Seam API, you must first authorize your Seam workspace to connect to your Akiles account. If your application needs to connect to your users' Akiles accounts, Seam provides fully-embedded, [customizable](../../core-concepts/connect-webviews/customizing-connect-webviews.md) client-side [Connect Webviews](../../core-concepts/connect-webviews/) 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 Akiles locks. The Connect Webview presents a flow that prompts your users to enter their credentials for their Akiles account. + +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 Akiles account. + +{% hint style="success" %} +This guide shows you how to create a Connect Webview programmatically using the Seam API. + +The [Seam Console](../../core-concepts/seam-console/) provides another easy way to connect devices to your Seam workspace. + +Go to [https://console.seam.co/](https://console.seam.co/). On the **Devices** page, click **+ Add Devices**. Then, see [Authorize your workspace](get-started-with-akiles-locks.md#authorize-your-workspace) in this guide to complete the Connect Webview authorization flow. + +You can also use the Seam Console to add devices. +{% endhint %} + +### Create a Connect Webview + +Create a `connect_webview` object and then note the returned URL. + +{% tabs %} +{% tab title="Python" %} +**Code:** + +```python +from seam import Seam + +seam = Seam() # Seam automatically uses your exported SEAM_API_KEY. + +connect_webview = seam.connect_webviews.create(accepted_providers=["akiles"]) + +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) +``` + +**Output:** + +``` +https://connect.getseam.com/connect_webviews/view?connect_webview_id=12345678-1234-1234-1234-123456789012&auth_token=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +``` +{% endtab %} + +{% tab title="cURL (bash)" %} +**Code:** + +```bash +curl -X 'POST' \ + 'https://connect.getseam.com/connect_webviews/create' \ + -H 'accept: application/json' \ + -H "Authorization: Bearer ${SEAM_API_KEY}" \ + -H 'Content-Type: application/json' \ + -d '{ + "accepted_providers": ["akiles"] +}' | jq -r '"Login Successful (false): " + (.connect_webview.login_successful | tostring), + "URL: " + .connect_webview.url' + # Use the returned Connect Webview URL to display + # the Connect Webview authorization flow to your user. +``` + +**Output:** + +``` +Login Successful (false): false +https://connect.getseam.com/connect_webviews/view?connect_webview_id=12345678-1234-1234-1234-123456789012&auth_token=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +``` +{% endtab %} + +{% tab title="JavaScript" %} +**Code:** + +```javascript +import { Seam } from "seam"; + +const seam = new Seam(); // Seam automatically uses your exported SEAM_API_KEY. + +const connectWebview = await seam.connectWebviews.create({ + accepted_providers: ['akiles'] +}); + +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); +``` + +**Output:** + +``` +false +https://connect.getseam.com/connect_webviews/view?connect_webview_id=12345678-1234-1234-1234-123456789012&auth_token=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +``` +{% endtab %} + +{% tab title="Ruby" %} +**Code:** + +```ruby +require "seamapi" + +seam = Seam::Client.new() # Seam automatically uses your exported SEAM_API_KEY. + +connect_webview = seam.connect_webviews.create( + accepted_providers: ["akiles"] +) + +puts connect_webview.login_successful # false + +# Use the returned Connect Webview URL to display +# the Connect Webview authorization flow to your user. +puts connect_webview.url +``` + +**Output:** + +``` +false +https://connect.getseam.com/connect_webviews/view?connect_webview_id=12345678-1234-1234-1234-123456789012&auth_token=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +``` +{% endtab %} + +{% tab title="PHP" %} +**Code:** + +```php +connect_webviews->create( + accepted_providers: ["akiles"] +); + +echo $connect_webview->login_successful ? 'true' : 'false', "\n"; // false + +// Use the returned Connect Webview URL to display +// the Connect Webview authorization flow to your user. +echo $connect_webview->url; +``` + +**Output:** + +``` +false +https://connect.getseam.com/connect_webviews/view?connect_webview_id=12345678-1234-1234-1234-123456789012&auth_token=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +``` +{% endtab %} + +{% tab title="C#" %} +**Code:** + +```csharp +using Seam.Client; + +var seam = new SeamClient(apiToken: SEAM_API_KEY); + +var connectWebview = seam.ConnectWebviews.Create( + acceptedProviders: new() {Seam.Api.ConnectWebviews.CreateRequest.AcceptedProvidersEnum.Akiles} +); + +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); +``` + +**Output:** + +``` +False +https://connect.getseam.com/connect_webviews/view?connect_webview_id=12345678-1234-1234-1234-123456789012&auth_token=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +``` +{% endtab %} + +{% tab title="Java" %} +**Code:** + +```java +import java.io.Console; +import java.util.*; +import com.fasterxml.jackson.annotation.*; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.seam.api.Seam; +import com.seam.api.core.ObjectMappers; +import com.seam.api.types.ConnectWebview; +import com.seam.api.types.Device; +import com.seam.api.types.Manufacturer; +import com.seam.api.types.ActionAttempt; +import com.seam.api.types.AccessCode; +import com.seam.api.resources.connectwebviews.requests.ConnectWebviewsCreateRequest; +import com.seam.api.resources.connectwebviews.requests.ConnectWebviewsGetRequest; +import com.seam.api.resources.devices.requests.DevicesListRequest; +import com.seam.api.resources.devices.requests.DevicesGetRequest; +import com.seam.api.resources.locks.requests.LocksUnlockDoorRequest; +import com.seam.api.resources.accesscodes.requests.AccessCodesCreateRequest; +import com.seam.api.resources.accesscodes.requests.AccessCodesListRequest; + +public class Main { + + public static void main(String[] args) { + + Seam seam = Seam.builder() + .apiKey(SEAM_API_KEY) + .build(); + + ConnectWebview connectWebview = seam.connectWebviews().create(ConnectWebviewsCreateRequest.builder() + .acceptedProviders(List.of(AcceptedProvider.AKILES)) + .build()); + + System.out.println(connectWebview.getLoginSuccessful()); // false + + // Use the returned Connect Webview URL to display + // the Connect Webview authorization flow to your user. + System.out.println(connectWebview.getUrl()); + + } +} +``` + +**Output:** + +``` +false +https://connect.getseam.com/connect_webviews/view?connect_webview_id=12345678-1234-1234-1234-123456789012&auth_token=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +``` +{% endtab %} + +{% tab title="Go" %} +**Code:** + +```go +package main + +import ( + "context" + "fmt" + "os" + + api "github.com/seamapi/go" + seam "github.com/seamapi/go/client" +) + +func main() { + if err := run(); err != nil { + _, _ = fmt.Fprintln(os.Stderr, err.Error()) + os.Exit(1) + } +} + +func run() error { + client := seam.NewClient( + seam.WithApiKey(SEAM_API_KEY), + ) + + connectWebview, err := client.ConnectWebviews.Create( + context.Background(), + &api.ConnectWebviewsCreateRequest{ + AcceptedProviders: []api.AcceptedProvider{ + api.AcceptedProviderAkiles, + }, + }, + ) + + if err != nil { + return err + } + + fmt.Println(connectWebview.LoginSuccessful) // false + + // Use the returned Connect Webview URL to display + // the Connect Webview authorization flow to your user. + fmt.Println(connectWebview.Url) + + return nil +} +``` + +**Output:** + +``` +false +https://connect.getseam.com/connect_webviews/view?connect_webview_id=12345678-1234-1234-1234-123456789012&auth_token=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +``` +{% endtab %} +{% endtabs %} + +*** + +### Authorize your workspace + +In a web browser, go to the URL that the Connect Webview object returned. + +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 [Connect Account Button](../../seam-components/react-components/connect-account-button.md) within our suite of [Seam Components](../../seam-components/overview/) that help you build your device management flow. + +{% hint style="success" %} +Because you're using a sandbox workspace, you can connect Seam's test Akiles account. We provide [virtual devices](../../device-guides/sandbox-and-sample-data/) 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. +{% endhint %} + +Complete the Connect Webview authorization flow by entering the following [Akiles sandbox account](../../developer-tools/sandbox-and-sample-data/sandbox-akiles-locks.md) credentials: + +* **Email:** jane@example.com +* **Password:** 1234 + +
Use the Seam Connect Webview authorization flow to connect an Akiles account with Seam. This flow varies slightly based on the device manufacturer.

Use the Seam Connect Webview authorization flow to connect an Akiles account with Seam. This flow varies slightly based on the device manufacturer.

+ +Confirm that authorization through the Connect Webview was successful by querying its status. + +{% tabs %} +{% tab title="Python" %} +**Code:** + +```python +updated_connect_webview = seam.connect_webviews.get(connect_webview.connect_webview_id) + +assert updated_connect_webview.login_successful is True # True +``` + +**Output:** + +``` +True +``` +{% endtab %} + +{% tab title="cURL (bash)" %} +**Code:** + +```bash +curl -X 'GET' \ + 'https://connect.getseam.com/connect_webviews/get' \ + -H 'accept: application/json' \ + -H "Authorization: Bearer ${SEAM_API_KEY}" \ + -H 'Content-Type: application/json' \ + -d "{ + \"connect_webview_id\": \"${connect_webview_id}\" +}" | jq -r '"Login Successful (true): " + (.connect_webview.login_successful | tostring)' +``` + +**Output:** + +``` +Login Successful (true): true +``` +{% endtab %} + +{% tab title="JavaScript" %} +**Code:** + +```javascript +const updatedConnectWebview = await seam.connectWebviews.get({ + connect_webview_id: connectWebview.connect_webview_id +}); + +console.log(updatedConnectWebview.login_successful); // true +``` + +**Output:** + +``` +true +``` +{% endtab %} + +{% tab title="Ruby" %} +**Code:** + +```ruby +updated_connect_webview = seam.connect_webviews.get( + connect_webview_id: connect_webview.connect_webview_id +) + +puts updated_connect_webview.login_successful # true +``` + +**Output:** + +``` +true +``` +{% endtab %} + +{% tab title="PHP" %} +**Code:** + +```php +$updated_connect_webview = $seam->connect_webviews->get( + connect_webview_id: $connect_webview->connect_webview_id +); + +echo $updated_connect_webview->login_successful ? 'true' : 'false', "\n"; // true +``` + +**Output:** + +``` +true +``` +{% endtab %} + +{% tab title="C#" %} +**Code:** + +```csharp +var updatedConnectWebview = seam.ConnectWebviews.Get( + connectWebviewId: connectWebview.connectWebviewId +); + +Console.WriteLine(updatedConnectWebview.LoginSuccessful); // True +``` + +**Output:** + +``` +True +``` +{% endtab %} + +{% tab title="Java" %} +**Code:** + +```java +ConnectWebview updatedConnectWebview = seam.connectWebviews().get(ConnectWebviewsGetRequest.builder() + .connectWebviewId(connectWebview.getConnectWebviewId()) + .build()); + +System.out.println(updatedConnectWebview.getLoginSuccessful()); // true +``` + +**Output:** + +``` +true +``` +{% endtab %} + +{% tab title="Go" %} +**Code:** + +```go +updatedConnectWebview, err := client.ConnectWebviews.Get( + context.Background(), + &api.ConnectWebviewsGetRequest{ + ConnectWebviewId: connectWebview.connectWebviewId, + }, +) + +if err != nil { + return err +} + +fmt.Println(updatedConnectWebview.LoginSuccessful) // true + +return nil +``` + +**Output:** + +``` +true +``` +{% endtab %} +{% endtabs %} + +*** + +## Step 3: Retrieve Akiles lock devices + +When you link an Akiles account with Seam, we create a `device` object to represent each Akiles lock in your account. You can then retrieve these Akiles devices using the [List Devices](../../api-clients/devices/list.md) and [Get Device](../../api-clients/devices/get.md) endpoints. + +The Seam API exposes each device's properties, such as the door lock status, capabilities, and so on. + +{% tabs %} +{% tab title="Python" %} +**Code:** + +```python +# Retrieve all devices, filtered by manufacturer, +# which is one of several filters that list() supports. +all_akiles_locks = seam.devices.list(manufacturer="akiles") + +# Select the first device as an example. +front_door = all_akiles_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) +``` + +**Output:** + +``` +Device( + device_id='11111111-1111-1111-1111-444444444444', + display_name='Lock 1', + workspace_id='00000000-0000-0000-0000-000000000000' + connected_account_id='11111111-1111-1111-1111-222222222222', + created_at='2024-05-29T20:08:48.878Z', + properties={ + 'manufacturer': 'akiles', + 'online': True, + 'locked': True, + ... + } + can_remotely_unlock=True, + can_program_online_access_codes=True, + ... +) +``` +{% endtab %} + +{% tab title="cURL (bash)" %} +**Code:** + +```bash +# Retrieve all devices, filtered by manufacturer, which is +# one of several filters that the list endpoint supports. +all_akiles_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": "akiles" + }') + +# Select the first device as an example. +front_door=$(jq -r '.devices[0]' <<< ${all_akiles_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} +``` + +**Output:** + +```json +Online (true): true +Locked (true): true +{ + "device_id": "11111111-1111-1111-1111-444444444444", + "display_name": "Lock 1", + "workspace_id": "00000000-0000-0000-0000-000000000000", + "connected_account_id": "11111111-1111-1111-1111-222222222222", + "created_at": "2024-05-29T20:08:48.878Z", + "properties": { + "manufacturer": "akiles", + "locked": true, + "online": true, + ... + }, + "can_remotely_unlock": true, + "can_program_online_access_codes": true, + ... +} +``` +{% endtab %} + +{% tab title="JavaScript" %} +**Code:** + +```javascript +// Retrieve all devices, filtered by manufacturer, +// which is one of several filters that list() supports. +const allAkilesLocks = await seam.devices.list({manufacturer: "akiles"}); + +// Select the first device as an example. +const frontDoor = allAkilesLocks[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); +``` + +**Output:** + +```json +true +true +{ + device_id: '11111111-1111-1111-1111-444444444444', + display_name: 'Lock 1', + workspace_id: '00000000-0000-0000-0000-000000000000', + connected_account_id: '11111111-1111-1111-1111-222222222222', + created_at: '2024-05-29T20:08:48.878Z', + properties: { + manufacturer: 'akiles', + online: true, + locked: true, + ... + }, + can_remotely_unlock: true, + can_program_online_access_codes: true, + ... +} +``` +{% endtab %} + +{% tab title="Ruby" %} +**Code:** + +```ruby +# Retrieve all devices, filtered by manufacturer, +# which is one of several filters that list() supports. +all_akiles_locks = seam.devices.list(manufacturer: "akiles") + +# Select the first device as an example. +front_door = all_akiles_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 +``` + +**Output:** + +```json +true +true +< + Seam::Device:0x00438 + device_id="11111111-1111-1111-1111-444444444444" + display_name="Lock 1" + workspace_id="00000000-0000-0000-0000-000000000000" + connected_account_id="11111111-1111-1111-1111-222222222222" + created_at=2024-05-29 20:08:48.878 UTC + properties={ + "manufacturer"=>"akiles", + "online"=>true, + "locked"=>true, + ... + } + can_remotely_unlock=true + can_program_online_access_codes=true + ... +> +``` +{% endtab %} + +{% tab title="PHP" %} +**Code:** + +```php +// Retrieve all devices, filtered by manufacturer, +// which is one of several filters that list() supports. +$all_akiles_locks = $seam->devices->list(manufacturer: "akiles"); + +// Select the first device as an example. +$front_door = $all_akiles_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); +``` + +**Output:** + +```json +true +true +{ + "device_id": "11111111-1111-1111-1111-444444444444", + "display_name": "Lock 1", + "workspace_id": "00000000-0000-0000-0000-000000000000" + "connected_account_id": "11111111-1111-1111-1111-222222222222", + "created_at": "2024-05-29T20:08:48.878Z", + "properties": { + "manufacturer": "akiles", + "online": true, + "locked": true, + ... + }, + "can_remotely_unlock": true, + "can_program_online_access_codes": true, + ... +} +``` +{% endtab %} + +{% tab title="C#" %} +**Code:** + +```csharp +// Retrieve all devices, filtered by manufacturer, +// which is one of several filters that list() supports. +var allAkilesLocks = seam.Devices.List( + manufacturer: Seam.Api.Devices.ListRequest.ManufacturerEnum.Akiles +); + +// Select the first device as an example. +Device frontDoor = allAkilesLocks[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); +``` + +**Output:** + +```json +True +True +{ + "device_id": "11111111-1111-1111-1111-444444444444", + "display_name": "Lock 1", + "workspace_id": "00000000-0000-0000-0000-000000000000", + "connected_account_id": "11111111-1111-1111-1111-222222222222", + "created_at": "2024-05-29T20:08:48.878Z", + "properties": { + "manufacturer": "akiles", + "online": true, + "locked": true, + ... + }, + "can_remotely_unlock": true, + "can_program_online_access_codes": true, + ... +} +``` +{% endtab %} + +{% tab title="Java" %} +**Code:** + +```java +// Retrieve all devices, filtered by manufacturer, +// which is one of several filters that list() supports. +var allAkilesLocks = seam.devices().list(DevicesListRequest.builder() + .manufacturer(Manufacturer.AKILES) + .build()); + +// Select the first device as an example. +Device frontDoor = allAkilesLocks.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); +``` + +**Output:** + +```json +true +true +{ + "device_id" : "11111111-1111-1111-1111-444444444444", + "display_name": "Lock 1", + "workspace_id" : "00000000-0000-0000-0000-000000000000", + "connected_account_id" : "11111111-1111-1111-1111-222222222222", + "created_at" : "2024-05-29T20:08:48.878Z", + "properties" : { + "manufacturer" : "akiles", + "online" : true, + "locked" : true, + ... + }, + "can_remotely_unlock" : true, + "can_program_online_access_codes": true, + ... +} +``` +{% endtab %} + +{% tab title="Go" %} +**Code:** + +```go +// Retrieve all devices, filtered by manufacturer, +// which is one of several filters that list() supports. +allAkilesLocks, err := client.Devices.List( + context.Background(), &api.DevicesListRequest{ + Manufacturer: api.ManufacturerAkiles.Ptr(), + }, +) + +// Select the first device as an example. +frontDoor := allAkilesLocks[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 +``` + +**Output:** + +```json +true +true +{ + "device_id": "11111111-1111-1111-1111-444444444444", + "display_name": "Lock 1", + "workspace_id": "00000000-0000-0000-0000-000000000000", + "connected_account_id": "11111111-1111-1111-1111-222222222222", + "created_at": "2024-05-29T20:08:48.878Z", + "properties": { + "manufacturer": "akiles", + "online": true, + "locked": true, + ... + }, + "can_remotely_unlock": true, + "can_program_online_access_codes": true, + ... +} +``` +{% endtab %} +{% endtabs %} + +*** + +## Step 4: Control your Akiles lock + +Next, you can use the Seam API to control your lock. + +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 [remote unlock actions](../../products/smart-locks/lock-and-unlock.md), [programming access codes](../../products/smart-locks/access-codes/), and so on. Seam's intuitive and granular [capability flags](../../capability-guides/device-and-system-capabilities.md#capability-flags) inform your application about what features and behaviors each device supports. Notice the capability flags within the code samples in this guide. + +Try out the following actions on your Akiles lock: + +* [ ] [Unlock your lock](get-started-with-akiles-locks.md#unlock-your-lock) +* [ ] [Program access codes on your lock](get-started-with-akiles-locks.md#program-access-codes-on-your-lock) + +### Unlock your lock + +To unlock a door, use the [Unlock Door](../../api-clients/locks/unlock\_door.md) endpoint. Specify the device that you want to unlock by including the `device_id` in the request body. This endpoint returns an [action attempt](../../core-concepts/action-attempts.md) to track the progress of the unlock operation. + +{% tabs %} +{% tab title="Python" %} +**Code:** + +```python +# 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) +``` + +**Output:** + +``` +ActionAttempt( + status='pending', + action_type='UNLOCK_DOOR', + action_attempt_id='11111111-2222-3333-4444-555555555555', + result=None, + error={} +) +``` +{% endtab %} + +{% tab title="cURL (bash)" %} +**Code:** + +```bash +# Confirm that the device can remotely unlock. +# You're using a capability flag here! +if $(jq -r '.can_remotely_lock' <<< ${front_door}); then \ + # Perform the unlock operation + # and return an action attempt. + curl -X 'POST' \ + 'https://connect.getseam.com/locks/unlock_door' \ + -H 'accept: application/json' \ + -H "Authorization: Bearer ${SEAM_API_KEY}" \ + -H 'Content-Type: application/json' \ + -d "{ + \"device_id\": \"$(jq -r '.device_id' <<< ${front_door})\" + }"; +fi +``` + +**Output:** + +```json +{ + "action_attempt": { + "status":"pending", + "action_type":"UNLOCK_DOOR", + "action_attempt_id":"11111111-2222-3333-4444-555555555555", + "result":null, + "error":null + }, + "ok":true +} +``` +{% endtab %} + +{% tab title="JavaScript" %} +**Code:** + +```javascript +// 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 + }); +}; +``` + +**Output:** + +```json +{ + actionAttempt: { + status: 'success', + action_attempt_id: '11111111-2222-3333-4444-555555555555', + action_type: 'UNLOCK_DOOR', + result: {}, + error: null + } +} +``` +{% endtab %} + +{% tab title="Ruby" %} +**Code:** + +```ruby +# 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(front_door.device_id) +end +``` + +**Output:** + +``` + +``` +{% endtab %} + +{% tab title="PHP" %} +**Code:** + +```php +// 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); +} +``` + +**Output:** + +```json +{ + "action_attempt_id":"11111111-2222-3333-4444-555555555555", + "action_type":"UNLOCK_DOOR", + "error":null, + "result":{}, + "status":"success" +} +``` +{% endtab %} + +{% tab title="C#" %} +**Code:** + +```csharp +// 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); +} +``` + +**Output:** + +```json +{ + "status": "pending", + "action_type": "UNLOCK_DOOR", + "action_attempt_id": "11111111-2222-3333-4444-555555555555" +} +``` +{% endtab %} + +{% tab title="Java" %} +**Code:** + +```java +// 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()); +} +``` + +**Output:** + +```json +Optional[ + { + "action_type" : "UNLOCK_DOOR", + "action_attempt_id" : "11111111-2222-3333-4444-555555555555", + "status" : "pending" + } +] +``` +{% endtab %} + +{% tab title="Go" %} +**Code:** + +```go +// 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 +``` + +**Output:** + +```json +&{pending + { + "status": "pending", + "action_type": "UNLOCK_DOOR", + "action_attempt_id": "11111111-2222-3333-4444-555555555555", + "result": null, + "error": null + } +} +``` +{% endtab %} +{% endtabs %} + +You can track the status of the unlock operation to confirm that the device unlocked successfully. Query the `locked` status of the device, [retrieve the action attempt](../../api-clients/action\_attempts/get.md) by ID, or look for a [`lock.unlocked` event](../../api-clients/events/#event-types). + +To query the `locked` status of the device: + +{% tabs %} +{% tab title="Python" %} +**Code:** + +```python +# 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 +``` +{% endtab %} + +{% tab title="cURL (bash)" %} +**Code:** + +```bash +# 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 +``` +{% endtab %} + +{% tab title="JavaScript" %} +**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 +``` +{% endtab %} + +{% tab title="Ruby" %} +**Code:** + +```ruby +# 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 +``` +{% endtab %} + +{% tab title="PHP" %} +**Code:** + +```php +// 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 +``` +{% endtab %} + +{% tab title="C#" %} +**Code:** + +```csharp +// 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 +``` +{% endtab %} + +{% tab title="Java" %} +**Code:** + +```java +// 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 +``` +{% endtab %} + +{% tab title="Go" %} +**Code:** + +```go +// 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 +``` +{% endtab %} +{% endtabs %} + +*** + +### Program access codes on your lock + +You can use the Seam API to program [online access codes](../../products/smart-locks/access-codes/) on Akiles locks that have an integrated keypad or an Akiles Pinpad. Lock users can then enter these access codes using the keypad or Pinpad to unlock the lock. + +The Seam API makes it easy to program both [ongoing](../../products/smart-locks/access-codes/#ongoing-access-codes) and [time-bound](../../products/smart-locks/access-codes/#time-bound-access-codes) online access codes. + +{% tabs %} +{% tab title="Python" %} +**Code:** + +```python +# 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) +``` + +**Output:** + +``` +[ + AccessCode( + access_code_id='11111111-1111-1111-1111-555555555555', + device_id='11111111-1111-1111-1111-444444444444', + type='ongoing', + code='1234', + name='my ongoing code', + ... + ) + 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)" %} +**Code:** + +```bash +# Confirm that the device supports online access codes. +# Here's another capability flag! +if $(jq -r '.device.can_program_online_access_codes' <<< ${updated_front_door}); then \ + # Create an ongoing online access code. + curl -X 'POST' \ + 'https://connect.getseam.com/access_codes/create' \ + -H 'accept: application/json' \ + -H "Authorization: Bearer ${SEAM_API_KEY}" \ + -H 'Content-Type: application/json' \ + -d "{ + \"device_id\": \"$(jq -r '.device.device_id' <<< ${updated_front_door})\", + \"name\": \"my ongoing code\", + \"code\": \"1234\" + }" + # Create a time-bound online access code. + curl -X 'POST' \ + 'https://connect.getseam.com/access_codes/create' \ + -H 'accept: application/json' \ + -H "Authorization: Bearer ${SEAM_API_KEY}" \ + -H 'Content-Type: application/json' \ + -d "{ + \"device_id\": \"$(jq -r '.device.device_id' <<< ${updated_front_door})\", + \"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=$( + # Use GET or POST. + curl -X 'GET' \ + 'https://connect.getseam.com/access_codes/list' \ + -H 'accept: application/json' \ + -H "Authorization: Bearer ${SEAM_API_KEY}" \ + -H 'Content-Type: application/json' \ + -d "{ + \"device_id\": \"$(jq -r '.device.device_id' <<< ${updated_front_door})\" + }") + echo ${access_codes}; +fi +``` + +**Output:** + +```json +{ + "access_codes": [ + { + "access_code_id":"11111111-1111-1111-1111-555555555555", + "device_id":"11111111-1111-1111-1111-444444444444", + "name":"my ongoing code", + "code":"1234", + "type":"ongoing", + ... + }, + { + "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" %} +**Code:** + +```javascript +// Confirm that the device supports online access codes. +// Here's another capability flag! +if (updatedFrontDoor.can_program_online_access_codes) { + // Create an ongoing online access code. + await seam.accessCodes.create({ + device_id: updatedFrontDoor.device_id, + name: "my ongoing code", + code: "1234" + }); + // Create a time-bound online access code. + await seam.accessCodes.create({ + device_id: updatedFrontDoor.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. + const accessCodes = await seam.accessCodes.list({ + device_id: updatedFrontDoor.device_id + }); + console.log(accessCodes); +}; +``` + +**Output:** + +```json +[ + { + access_code_id: '11111111-1111-1111-1111-555555555555', + device_id: '11111111-1111-1111-1111-444444444444', + name: 'my ongoing code', + code: '1234', + type: 'ongoing', + ... + }, + { + 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" %} +**Code:** + +```ruby +# 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 + ) + puts access_codes.inspect +end +``` + +**Output:** + +``` +[ + , + +] +``` +{% endtab %} + +{% tab title="PHP" %} +**Code:** + +```php +// 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 + ); + echo json_encode($access_codes, JSON_PRETTY_PRINT); +} +``` + +**Output:** + +```json +[ + { + "access_code_id": "11111111-1111-1111-1111-555555555555", + "device_id": "11111111-1111-1111-1111-444444444444", + "name": "my ongoing code", + "type": "ongoing", + "code": "1234", + ... + }, + { + "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#" %} +**Code:** + +```csharp +// Confirm that the device supports online access codes. +// Here's another capability flag! +if (updatedFrontDoor.CanProgramOnlineAccessCodes == true) { + // Create an ongoing online access code. + seam.AccessCodes.Create( + deviceId: updatedFrontDoor.DeviceId, + name: "my ongoing code", + code: "1234" + ); + // Create a time-bound online access code. + seam.AccessCodes.Create( + deviceId: updatedFrontDoor.DeviceId, + name: "my time-bound code", + startsAt: "2025-01-01T16:00:00Z", + endsAt: "2025-01-22T12:00:00Z", + code: "2345" + ); + // List all access codes for this device. + var accessCodes = seam.AccessCodes.List( + deviceId: updatedFrontDoor.DeviceId + ); + foreach (var accessCode in accessCodes) + { + Console.WriteLine(accessCode); + } +} +``` + +**Output:** + +```json +{ + "type": "ongoing", + "access_code_id": "11111111-1111-1111-1111-555555555555", + "device_id": "11111111-1111-1111-1111-444444444444", + "name": "my ongoing code", + "code": "1234", + ... +} +{ + "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" %} +**Code:** + +```java +// Confirm that the device supports online access codes. +// Here's another capability flag! +if (updatedFrontDoor.getCanProgramOnlineAccessCodes()) +{ + // Create an ongoing online access code. + seam.accessCodes() + .create(AccessCodesCreateRequest.builder() + .deviceId(updatedFrontDoor.getDeviceId()) + .name("my ongoing code") + .code("1234") + .build()); + // Create a time-bound online access code. + seam.accessCodes() + .create(AccessCodesCreateRequest.builder() + .deviceId(updatedFrontDoor.getDeviceId()) + .name("my time-bound code") + .startsAt("2025-01-01T16:00:00Z") + .endsAt("2025-01-22T12:00:00Z") + .code("2345") + .build()); + // List all access codes for this device. + var accessCodes = seam.accessCodes() + .list(AccessCodesListRequest.builder() + .deviceId(updatedFrontDoor.getDeviceId()) + .build()); + System.out.println(accessCodes); +} +``` + +**Output:** + +```json +[ + { + "access_code_id" : "11111111-1111-1111-1111-555555555555", + "device_id" : "11111111-1111-1111-1111-444444444444", + "name" : "my ongoing code", + "code" : "1234", + "type" : "ongoing", + ... + }, + { + "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" %} +**Code:** + +```go +// Confirm that the device supports online access codes. +// Here's another capability flag! +if *updatedFrontDoor.CanProgramOnlineAccessCodes { + // Create an ongoing online access code. + client.AccessCodes.Create( + context.Background(), + &api.AccessCodesCreateRequest{ + DeviceId: updatedFrontDoor.DeviceId, + Name: api.String("my ongoing code"), + Code: api.String("1234"), + }, + ) + // Create a time-bound online access code. + client.AccessCodes.Create( + context.Background(), + &api.AccessCodesCreateRequest{ + DeviceId: updatedFrontDoor.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"), + }, + ) + // List all access codes for this device. + accessCodes, err := client.AccessCodes.List( + context.Background(), + &api.AccessCodesListRequest{ + DeviceId: updatedFrontDoor.DeviceId, + }, + ) + fmt.Println(accessCodes) + + if err != nil { + return err + } +} + +return nil +``` + +**Output:** + +```json +[ + { + "access_code_id": "11111111-1111-1111-1111-555555555555", + "device_id": "11111111-1111-1111-1111-444444444444", + "name": "my ongoing code", + "code": "1234", + "type": "ongoing", + ... + } + { + "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 %} + +*** + +## Step 5: Connect a real Akiles lock + +Now that you have learned the basics of using the Seam API, you can connect and control a real Akiles device. To do so, make sure to switch to a [non-sandbox workspace](../../core-concepts/workspaces/#production-workspaces) and [API key](../../core-concepts/authentication/api-keys.md). + +For more details about setting up your real Akiles lock, see the [Akiles locks integration guide](./). + +*** + +## Step 6: Build your application! + +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 [Seam Components](../../seam-components/overview/). These prebuilt UI components help you to build your device management flow. + +
Seam Components make it easy to develop your application!

Seam Components make it easy to develop your application!

+ +For example, you can use the [Device Table Seam Component](../../seam-components/react-components/device-table.md) to display a list of devices and to identify all devices with issues. You can use the [Device Details Seam Component](../../seam-components/react-components/device-details.md) 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 [Access Code Details Seam Component](../../seam-components/react-components/access-code-details.md) provides a similar display and actions for 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. + +To learn about all the Seam Components that we provide, see [Seam Components](../../seam-components/overview/). + +*** + +## Next steps + +Now that you've completed this getting started guide for Akiles devices, you can learn more about what you can do with the Seam API. + +* [ ] **Explore**\ + See the [other devices and system integrations](../overview.md) that Seam supports. +* [ ] **Learn**\ + Read about Seam [concepts](../../device-guides/broken-reference/) and the [device and system capabilities ](../../capability-guides/device-and-system-capabilities.md)that Seam supports. +* [ ] **Use Seam Components**\ + Find out about [Seam Components](../../seam-components/overview/), which are prebuilt UI components for building your device management flow. +* [ ] **Use webhooks**\ + Learn how to use [webhooks](../../core-concepts/webhooks.md) 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 [access control systems](../../products/access-systems/), [thermostats](../../products/thermostats/), and [noise sensors](../../products/noise-sensors/). +* [ ] **Develop for mobile access**\ + Learn about Seam's [mobile access solution](../../products/mobile-access-in-development/). + +{% hint style="info" %} +If you have any questions or want to report an issue, email us at [support@seam.co](mailto:support@seam.co). +{% endhint %} + +*** + +## Quick links + +
Get an API Key (free)Sign up for the Seam Console and get your API keys. →seam-api-key.pnghttps://console.seam.co/
Contact SalesGot a project or a specific question? Contact our team to get answers. →seam-contact-us-light.pnghttps://www.seam.co/contact-us
diff --git a/docs/device-and-system-integration-guides/overview.md b/docs/device-and-system-integration-guides/overview.md index 8427cd09..396320ed 100644 --- a/docs/device-and-system-integration-guides/overview.md +++ b/docs/device-and-system-integration-guides/overview.md @@ -20,7 +20,7 @@ To find the integration guide for each of your devices or systems, see the follo ## Smart Locks -
2N Intercom Systems2n-logo.png2n-intercom-systems.md
4SUITES Locks4suites-logo.png4suites-locks
August Locksaugust-logo.pngaugust-locks.md
dormakaba Oracode Locksdormakaba-logo.pngdormakaba-oracode-locks.md
iglooHome Locksigloohome-logo.pngigloohome-locks.md
Kwikset Lockskwikset-logo.pngkwikset-locks.md
Lockly Lockslockly-logo.pnglockly-locks
Nuki Locksnuki-logo.pngnuki-locks.md
Salto Lockssalto-logo.pngsalto-locks.md
Schlage Locksschlage-logo.pngget-started-with-schlage-locks.md
SmartThings Hubs + Smart Lockssmartthings-logo.pngget-started-with-smartthings-hubs-+-smart-locks.md
Tedee Lockstedee-logo.pngtedee-locks
TTLock Locksttlock-logo.pngttlock-locks.md
Wyze Lockswyze-logo.pngwyze-locks.md
Yale Locksyale-logo.pngyale-locks.md
+
2N Intercom Systems2n-logo.png2n-intercom-systems.md
4SUITES Locks4suites-logo.png4suites-locks
Akiles Locksakiles-logo.pngakiles-locks
August Locksaugust-logo.pngaugust-locks.md
dormakaba Oracode Locksdormakaba-logo.pngdormakaba-oracode-locks.md
iglooHome Locksigloohome-logo.pngigloohome-locks.md
Kwikset Lockskwikset-logo.pngkwikset-locks.md
Lockly Lockslockly-logo.pnglockly-locks
Nuki Locksnuki-logo.pngnuki-locks.md
Salto Lockssalto-logo.pngsalto-locks.md
Schlage Locksschlage-logo.pngget-started-with-schlage-locks.md
SmartThings Hubs + Smart Lockssmartthings-logo.pngget-started-with-smartthings-hubs-+-smart-locks.md
Tedee Lockstedee-logo.pngtedee-locks
TTLock Locksttlock-logo.pngttlock-locks.md
Wyze Lockswyze-logo.pngwyze-locks.md
Yale Locksyale-logo.pngyale-locks.md
*** diff --git a/docs/device-guides/sandbox-and-sample-data/README.md b/docs/device-guides/sandbox-and-sample-data/README.md index 12f9551c..67f7fef2 100644 --- a/docs/device-guides/sandbox-and-sample-data/README.md +++ b/docs/device-guides/sandbox-and-sample-data/README.md @@ -14,6 +14,10 @@ description: >- [4suites-locks-sample-data.md](4suites-locks-sample-data.md) {% endcontent-ref %} +{% content-ref url="../../developer-tools/sandbox-and-sample-data/sandbox-akiles-locks.md" %} +[sandbox-akiles-locks.md](../../developer-tools/sandbox-and-sample-data/sandbox-akiles-locks.md) +{% endcontent-ref %} + {% content-ref url="assa-abloy-credential-service-sample-data.md" %} [assa-abloy-credential-service-sample-data.md](assa-abloy-credential-service-sample-data.md) {% endcontent-ref %}