Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

PyPI GitHub Actions

SDK for the Seam API written in Python.

Description

Seam makes it easy to integrate IoT devices with your applications. This is an official SDK for the Seam API. Please refer to the official Seam Docs to get started.

Parts of this SDK are generated from always up-to-date type information provided by @seamapi/types node package. This ensures all API methods, request shapes, and response shapes are accurate and fully typed.

Contents

Installation

This package is registered on the Python Package Index (PyPI) as seam.

Install it with:

$ pip install seam

Usage

Examples

Note: These examples assume `SEAM_API_KEY` is set in your environment.

List devices

from seam import Seam

seam = Seam()
devices = seam.devices.list()

Unlock a door

from seam import Seam

seam = Seam()
lock = seam.locks.get(name="Front Door")
seam.locks.unlock_door(device_id=lock.device_id)

Authentication Method

The SDK supports API key and personal access token authentication mechanisms. Authentication may be configured by passing the corresponding options directly to the Seam constructor, or with the more ergonomic static factory methods.

API Key

An API key is scoped to a single workspace and should only be used on the server. Obtain one from the Seam Console.

# Set the `SEAM_API_KEY` environment variable
seam = Seam()

# Pass as the first argument to the constructor
seam = Seam("your-api-key")

# Pass as a keyword argument to the constructor
seam = Seam(api_key="your-api-key")

# Use the factory method
seam = Seam.from_api_key("your-api-key")

Personal Access Token

A Personal Access Token is scoped to a Seam Console user. Obtain one from the Seam Console. A workspace ID must be provided when using this method and all requests will be scoped to that workspace.

# Set the `SEAM_PERSONAL_ACCESS_TOKEN` and `SEAM_WORKSPACE_ID` environment variables
seam = Seam()

# Pass as an option to the constructor
seam = Seam(
    personal_access_token="your-personal-access-token",
    workspace_id="your-workspace-id",
)

# Use the factory method
seam = Seam.from_personal_access_token(
    "your-personal-access-token",
    "your-workspace-id",
)

Action Attempts

Some asynchronous operations, e.g., unlocking a door, return an action attempt. Seam tracks the progress of the requested operation and updates the action attempt when it succeeds or fails.

To make working with action attempts more convenient for applications, this library provides the wait_for_action_attempt option and enables it by default.

When the wait_for_action_attempt option is enabled, the SDK:

  • Polls the action attempt up to the timeout at the polling_interval (both in seconds).

  • Resolves with a fresh copy of the successful action attempt.

  • Raises a SeamActionAttemptFailedError if the action attempt is unsuccessful.

  • Raises a SeamActionAttemptTimeoutError if the action attempt is still pending when the timeout is reached.

  • Both errors expose an action_attempt property.

If you already have an action attempt ID and want to wait for it to resolve, simply use

seam.action_attempts.get(action_attempt_id=action_attempt_id)

Or, to get the current state of an action attempt by ID without waiting,

seam.action_attempts.get(
    action_attempt_id=action_attempt_id,
    wait_for_action_attempt=False,
)

To disable this behavior, set the default option for the client:

seam = Seam(
    api_key="your-api-key",
    wait_for_action_attempt=False,
)

seam.locks.unlock_door(device_id=device_id)

or the behavior may be configured per-request:

seam.locks.unlock_door(
    device_id=device_id,
    wait_for_action_attempt=False,
)

The polling_interval and timeout may be configured for the client or per-request. For example:

from seam import Seam, SeamActionAttemptFailedError, SeamActionAttemptTimeoutError

seam = Seam("your-api-key")

lock = seam.locks.list()

if len(locks) == 0:
    raise Exception("No locks in this workspace")

lock = locks[0]

try:
    seam.locks.unlock_door(
        device_id=lock.device_id,
        wait_for_action_attempt={
            "timeout": 5.0,
            "polling_interval": 1.0,
        },
    )

    print("Door unlocked")
except SeamActionAttemptFailedError as e:
    print("Could not unlock the door")
except SeamActionAttemptTimeoutError as e:
    print("Door took too long to unlock")

Pagination

Some Seam API endpoints that return lists of resources support pagination. Use the SeamPaginator class to fetch and process resources across multiple pages.

Manually fetch pages with the next_page_cursor

from seam import Seam

seam = Seam()

paginator = seam.create_paginator(seam.devices.list, {"limit": 20})

devices, pagination = paginator.first_page()

if pagination.has_next_page:
    more_devices, _ = paginator.next_page(pagination.next_page_cursor)

Resume pagination

Get the first page on initial load and store the state (e.g., in memory or a file):

import json
from seam import Seam

seam = Seam()

params = {"limit": 20}
paginator = seam.create_paginator(seam.devices.list, params)

devices, pagination = paginator.first_page()

# Example: Store state for later use (e.g., in a file or database)
pagination_state = {
    "params": params,
    "next_page_cursor": pagination.next_page_cursor,
    "has_next_page": pagination.has_next_page,
}
with open("/tmp/seam_devices_list.json", "w") as f:
    json.dump(pagination_state, f)

Get the next page at a later time using the stored state:

import json
from seam import Seam

seam = Seam()

# Example: Load state from where it was stored
with open("/tmp/seam_devices_list.json", "r") as f:
    pagination_state = json.load(f)

if pagination_state.get("has_next_page"):
    paginator = seam.create_paginator(
        seam.devices.list, pagination_state["params"]
    )
    more_devices, _ = paginator.next_page(
        pagination_state["next_page_cursor"]
    )

Iterate over all resources

from seam import Seam

seam = Seam()

paginator = seam.create_paginator(seam.devices.list, {"limit": 20})

for account in paginator.flatten():
    print(account.account_type_display_name)

Return all resources across all pages as a list

from seam import Seam

seam = Seam()

paginator = seam.create_paginator(seam.devices.list, {"limit": 20})

all_devices = paginator.flatten_to_list()

Requests without a Workspace in Scope

Some Seam API endpoints do not require a workspace in scope. The SeamWithoutWorkspace client is not bound to a specific workspace and may use those endpoints with an appropriate authentication method.

Personal Access Token without a Workspace

A Personal Access Token is scoped to a Seam Console user. Obtain one from the Seam Console.

from seam import SeamWithoutWorkspace

# Set the `SEAM_PERSONAL_ACCESS_TOKEN` environment variable
seam = SeamWithoutWorkspace()

# Pass as an option to the constructor
seam = SeamWithoutWorkspace(personal_access_token="your-personal-access-token")

# Use the factory method
seam = SeamWithoutWorkspace.from_personal_access_token("your-personal-access-token")

# List workspaces authorized for this Personal Access Token
workspaces = seam.workspaces.list()

Webhooks

The Seam API implements webhooks using Svix. This SDK exports a thin wrapper SeamWebhook around the svix package. Use it to parse and validate Seam webhook events.

Refer to the Svix docs on Consuming Webhooks for an in-depth guide on best-practices for handling webhooks in your application.

This example is for Flask, see the Svix docs for more examples in specific frameworks.

import os

from flask import Flask, request
from seam import SeamWebhook

app = Flask(__name__)

webhook = SeamWebhook(os.getenv('SEAM_WEBHOOK_SECRET'))

@app.route('/webhook', methods=['POST'])
def handle_webhook():
    try:
        data = webhook.verify(request.get_data(), request.headers)
    except Exception:
        return 'Bad Request', 400

    try:
        store_event(data)
    except Exception:
          return 'Internal Server Error', 500

    return '', 204

def store_event(data):
    print(data)

if __name__ == '__main__':
    app.run(port=8080)

Advanced Usage

Setting the endpoint

Some contexts may need to override the API endpoint, e.g., testing or proxy setups.

Either pass the endpoint option to the constructor, or set the SEAM_ENDPOINT environment variable.

Setting the request timeout

Requests time out after 30 seconds by default. Pass the timeout option, in seconds, to override this:

from seam import Seam

seam = Seam(api_key="your-api-key", timeout=60)

Setting it to None disables the timeout entirely.

A request that exceeds the timeout raises httpx.TimeoutException.

Configuring retries

By default, the SDK makes up to three attempts: the initial request and two retries. Retries are limited to GET, HEAD, OPTIONS, PUT, and DELETE requests that fail because of a transport error, timeout, HTTP 429 response, or HTTP 5xx response. POST and PATCH requests are not retried.

Retries use exponential backoff with jitter: approximately 200–240 ms before the first retry and 400–480 ms before the second. A Retry-After header is honored instead of the calculated backoff. The request timeout is reset for each attempt.

Pass the retries option to configure retry behavior. Retries are handled by httpx-retries, and its Retry class is re-exported from seam for convenience:

from seam import Seam, Retry

seam = Seam(
    api_key="your-api-key",
    retries=Retry(total=3, backoff_factor=0.5, status_forcelist=[503]),
)

Configuring the httpx client

For control the options above do not cover, pass httpx_options. These are handed to the underlying httpx Client and take precedence over the defaults the SDK sets:

from httpx import Limits

seam = Seam(
    api_key="your-api-key",
    httpx_options={
        "limits": Limits(max_connections=25, max_keepalive_connections=20),
    },
)

Development and Testing

Quickstart

$ git clone https://github.com/seamapi/python.git
$ cd python
$ uv sync

Run each command below in a separate terminal window:

$ just watch

Primary development tasks are defined in the justfile.

Source Code

The source code is hosted on GitHub. Clone the project with

$ git clone https://github.com/seamapi/python.git

Requirements

You will need Python 3 and uv and Node.js with npm and just.

Install the development dependencies with

$ uv sync
$ npm install

Tests

Lint code with

$ just lint

Run tests with

$ just test

Run tests on changes with

$ just watch

Publishing

New versions are created with uv version.

Automatic

New versions are released automatically with semantic-release as long as commits follow the Angular Commit Message Conventions.

Manual

Publish a new version by triggering a version workflow_dispatch on GitHub Actions. The version input will be passed as the first argument to uv version.

This may be done on the web or using the GitHub CLI with

$ gh workflow run version.yml --raw-field version=<version>

GitHub Actions

GitHub Actions should already be configured: this section is for reference only.

The following repository secrets must be set on GitHub Actions.

  • PYPI_API_TOKEN: API token for publishing on PyPI.

These must be set manually.

Secrets for Optional GitHub Actions

The version, format, generate, and semantic-release GitHub actions require a user with write access to the repository including access to read and write packages. Set these additional secrets to enable the action:

  • GH_TOKEN: A personal access token for the user.

  • GIT_USER_NAME: The name to set for Git commits.

  • GIT_USER_EMAIL: The email to set for Git commits.

  • GPG_PRIVATE_KEY: The GPG private key.

  • GPG_PASSPHRASE: The GPG key passphrase.

Contributing

Please submit and comment on bug reports and feature requests.

To submit a patch:

  1. Fork it (https://github.com/seamapi/python/fork).

  2. Create your feature branch (git checkout -b my-new-feature).

  3. Make changes.

  4. Commit your changes (git commit -am ‘Add some feature’).

  5. Push to the branch (git push origin my-new-feature).

  6. Create a new Pull Request.

License

This Python package is licensed under the MIT license.

Warranty

This software is provided by the copyright holders and contributors “as is” and any express or implied warranties, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose are disclaimed. In no event shall the copyright holder or contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

seam-3.0.0b4.tar.gz (136.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

seam-3.0.0b4-py3-none-any.whl (204.1 kB view details)

Uploaded Python 3

File details

Details for the file seam-3.0.0b4.tar.gz.

File metadata

  • Download URL: seam-3.0.0b4.tar.gz
  • Upload date:
  • Size: 136.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for seam-3.0.0b4.tar.gz
Algorithm Hash digest
SHA256 4358da73f0a4f467f9dd89add7d39bde52eb94912acf4c75be70c50466f07e6f
MD5 c5aa5c54a39f12eec0dbc24f9e659aa3
BLAKE2b-256 8ce063e28b09fc4dd5f3a4a5b8ce11dd6984b0a03fb4629923efa5e7c0c88660

See more details on using hashes here.

File details

Details for the file seam-3.0.0b4-py3-none-any.whl.

File metadata

  • Download URL: seam-3.0.0b4-py3-none-any.whl
  • Upload date:
  • Size: 204.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for seam-3.0.0b4-py3-none-any.whl
Algorithm Hash digest
SHA256 5c2ef1b835a9b7dcc32fd2fcfd82debf449d154ee140848550d9bea15dd7cce3
MD5 63a3f0f512a3238d7a5f92d3f3c77c37
BLAKE2b-256 23f9bf7ae7b58dee183e8a5a9793f74e2194c0e5bf766b6eafc7c7ac5eaf6f46

See more details on using hashes here.

Release history Release notifications | RSS feed

3.13.12

2 files

3.13.11

2 files

3.13.10

2 files

3.13.9

2 files

3.13.8

2 files

3.13.7

2 files

3.13.6

2 files

3.13.5

2 files

3.13.4

2 files

3.13.3

2 files

3.13.2

2 files

3.13.1

2 files

3.13.0

2 files

3.12.0

2 files

3.11.0

2 files

3.10.0

2 files

3.9.0

2 files

3.8.0

2 files

3.7.0

2 files

3.6.1

2 files

3.6.0

2 files

3.5.0

2 files

3.4.0

2 files

3.3.0

2 files

3.2.0

2 files

3.1.0

2 files

3.0.0

2 files

This release

3.0.0b4 This release

2 files

2.2.0

2 files

2.1.0

2 files

2.0.0

2 files

1.210.0

2 files

1.209.1

2 files

1.209.0

2 files

1.208.0

2 files

1.207.0

2 files

1.206.1

2 files

1.206.0

2 files

1.205.0

2 files

1.204.1

2 files

1.145.0

2 files

1.144.0

2 files

1.143.0

2 files

1.142.0

2 files

1.141.0

2 files

1.140.0

2 files

1.139.0

2 files

1.138.0

2 files

1.137.0

2 files

1.136.0

2 files

1.135.0

2 files

1.134.0

2 files

1.133.0

2 files

1.132.0

2 files

1.131.0

2 files

1.130.0

2 files

1.129.0

2 files

1.128.0

2 files

1.127.0

2 files

1.126.0

2 files

1.125.0

2 files

1.124.0

2 files

1.123.0

2 files

1.122.0

2 files

1.121.0

2 files

1.120.0

2 files

1.119.0

2 files

1.118.0

2 files

1.117.0

2 files

1.116.0

2 files

1.115.0

2 files

1.114.0

2 files

1.113.0

2 files

1.112.0

2 files

1.111.0

2 files

1.110.0

2 files

1.109.0

2 files

1.108.0

2 files

1.107.0

2 files

1.106.0

2 files

1.105.0

2 files

1.104.0

2 files

1.103.0

2 files

1.102.0

2 files

1.101.0

2 files

1.100.0

2 files

1.99.0

2 files

1.98.0

2 files

1.97.0

2 files

1.96.0

2 files

1.95.0

2 files

1.94.0

2 files

1.93.0

2 files

1.92.0

2 files

1.91.0

2 files

1.90.0

2 files

1.89.0

2 files

1.88.0

2 files

1.87.0

2 files

1.86.0

2 files

1.85.0

2 files

1.84.0

2 files

1.83.0

2 files

1.82.0

2 files

1.81.0

2 files

1.80.0

2 files

1.79.0

2 files

1.78.0

2 files

1.77.0

2 files

1.76.0

2 files

1.75.0

2 files

1.74.0

2 files

1.73.0

2 files

1.72.0

2 files

1.71.0

2 files

1.70.0

2 files

1.69.1

2 files

1.69.0

2 files

1.68.0

2 files

1.67.0

2 files

1.66.0

2 files

1.65.0

2 files

1.64.0

2 files

1.63.0

2 files

1.62.0

2 files

1.61.0

2 files

1.60.0

2 files

1.59.0

2 files

1.58.0

2 files

1.57.0

2 files

1.56.0

2 files

1.55.0

2 files

1.54.0

2 files

1.53.0

2 files

1.52.0

2 files

1.51.0

2 files

1.50.0

2 files

1.49.0

2 files

1.48.0

2 files

1.47.0

2 files

1.46.0

2 files

1.45.0

2 files

1.44.0

2 files

1.43.0

2 files

1.42.0

2 files

1.41.0

2 files

1.40.0

2 files

1.39.0

2 files

1.38.0

2 files

1.37.0

2 files

1.36.0

2 files

1.35.0

2 files

1.34.0

2 files

1.33.0

2 files

1.32.0

2 files

1.31.0

2 files

1.30.0

2 files

1.29.0

2 files

1.28.0

2 files

1.27.0

2 files

1.26.0

2 files

1.25.0

2 files

1.24.0

2 files

1.23.0

2 files

1.22.0

2 files

1.21.0

2 files

1.20.0

2 files

1.19.0

2 files

1.18.0

2 files

1.17.0

2 files

1.16.0

2 files

1.15.0

2 files

1.14.0

2 files

1.13.0

2 files

1.12.0

2 files

1.11.0

2 files

1.10.0

2 files

1.9.0

2 files

1.8.0

2 files

1.7.1

2 files

1.7.0

1 file

1.6.0

2 files

1.5.0

2 files

1.4.0

2 files

1.3.0

2 files

1.2.1

2 files

1.2.0

2 files

1.1.0

2 files

1.0.1

2 files

1.0.0

2 files

0.15.0

2 files

0.14.0

2 files

0.13.1

2 files

0.13.0

2 files

0.12.1

2 files

0.12.0

2 files

0.11.0

2 files

0.10.0

2 files

0.9.0

2 files

0.8.0

2 files

0.7.1

2 files

0.7.0

2 files

0.6.2

2 files

0.6.1

2 files

0.6.0

2 files

0.5.0

2 files

0.4.1

2 files

0.4.0

2 files

0.3.1

2 files

0.3.0

2 files

0.2.0

2 files

0.1.0

2 files

0.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page