From 29a33d48b0676cb5ae47cde685f480a155992cce Mon Sep 17 00:00:00 2001 From: Evan Sosenko Date: Tue, 18 Aug 2026 20:55:37 -0700 Subject: [PATCH 1/3] feat: Use semantic method for all endpoints --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index d2ef893..dfc7f5a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,7 +6,7 @@ "": { "name": "@seamapi/python", "devDependencies": { - "@seamapi/blueprint": "^1.7.0", + "@seamapi/blueprint": "^1.8.0", "@seamapi/fake-seam-connect": "1.86.0", "@seamapi/smith": "^1.1.0", "@seamapi/types": "1.1001.0", @@ -787,9 +787,9 @@ "license": "MIT" }, "node_modules/@seamapi/blueprint": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@seamapi/blueprint/-/blueprint-1.7.0.tgz", - "integrity": "sha512-on9pREQKyFgIaS99KLcck5K6AqLEO8Iy5h1heuJ2sEC2A7wXk5s/TL8iDOB3+4eeaAwuHRPgze9/Omo84KjJkw==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@seamapi/blueprint/-/blueprint-1.8.0.tgz", + "integrity": "sha512-NUghBmYaKreBeBxwPIB2O9hjIFZtEjVj73tAsuKdJR8t4BxlKK1I0XDQXxo3ZsH2QezNlbdo9/0MoX/33VXuhQ==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index fa3bddf..2bc724a 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ } }, "devDependencies": { - "@seamapi/blueprint": "^1.7.0", + "@seamapi/blueprint": "^1.8.0", "@seamapi/fake-seam-connect": "1.86.0", "@seamapi/smith": "^1.1.0", "@seamapi/types": "1.1001.0", From 19cf78896c1fbfc2f437272b0fab44ac7e48979b Mon Sep 17 00:00:00 2001 From: Seam Bot Date: Wed, 19 Aug 2026 03:56:19 +0000 Subject: [PATCH 2/3] ci: Generate code --- seam/routes/access_codes.py | 26 ++++++------- seam/routes/access_grants.py | 44 +++++++++++----------- seam/routes/access_methods.py | 12 +++--- seam/routes/acs_encoders.py | 14 +++---- seam/routes/acs_entrances.py | 38 +++++++++---------- seam/routes/action_attempts.py | 12 +++--- seam/routes/connect_webviews.py | 16 ++++---- seam/routes/connected_accounts.py | 18 ++++----- seam/routes/customers.py | 42 ++++++++++----------- seam/routes/devices.py | 36 +++++++++--------- seam/routes/devices_unmanaged.py | 28 +++++++------- seam/routes/events.py | 62 +++++++++++++++---------------- seam/routes/locks.py | 16 ++++---- seam/routes/noise_sensors.py | 16 ++++---- seam/routes/spaces.py | 34 ++++++++--------- seam/routes/thermostats.py | 16 ++++---- seam/routes/user_identities.py | 16 ++++---- 17 files changed, 223 insertions(+), 223 deletions(-) diff --git a/seam/routes/access_codes.py b/seam/routes/access_codes.py index 8ad4923..be1c44a 100644 --- a/seam/routes/access_codes.py +++ b/seam/routes/access_codes.py @@ -736,35 +736,35 @@ def list( :returns: OK :raises ValueError: At least one parameter must be provided.""" - json_payload: Dict[str, Any] = {} + params: Dict[str, Any] = {} if access_code_ids is not None: - json_payload["access_code_ids"] = access_code_ids + params["access_code_ids"] = access_code_ids if access_grant_id is not None: - json_payload["access_grant_id"] = access_grant_id + params["access_grant_id"] = access_grant_id if access_grant_key is not None: - json_payload["access_grant_key"] = access_grant_key + params["access_grant_key"] = access_grant_key if access_method_id is not None: - json_payload["access_method_id"] = access_method_id + params["access_method_id"] = access_method_id if customer_key is not None: - json_payload["customer_key"] = customer_key + params["customer_key"] = customer_key if device_id is not None: - json_payload["device_id"] = device_id + params["device_id"] = device_id if limit is not None: - json_payload["limit"] = limit + params["limit"] = limit if page_cursor is not None: - json_payload["page_cursor"] = page_cursor + params["page_cursor"] = page_cursor if search is not None: - json_payload["search"] = search + params["search"] = search if user_identifier_key is not None: - json_payload["user_identifier_key"] = user_identifier_key + params["user_identifier_key"] = user_identifier_key - if not json_payload: + if not params: raise ValueError( "At least one parameter is required for /access_codes/list" ) - res = self.client.post("/access_codes/list", json=json_payload) + res = self.client.get("/access_codes/list", params=params) return [AccessCode.from_dict(item) for item in res["access_codes"]] diff --git a/seam/routes/access_grants.py b/seam/routes/access_grants.py index 8b396e9..a114698 100644 --- a/seam/routes/access_grants.py +++ b/seam/routes/access_grants.py @@ -407,23 +407,23 @@ def get_related( :returns: OK :raises ValueError: At least one parameter must be provided.""" - json_payload: Dict[str, Any] = {} + params: Dict[str, Any] = {} if access_grant_ids is not None: - json_payload["access_grant_ids"] = access_grant_ids + params["access_grant_ids"] = access_grant_ids if access_grant_keys is not None: - json_payload["access_grant_keys"] = access_grant_keys + params["access_grant_keys"] = access_grant_keys if exclude is not None: - json_payload["exclude"] = exclude + params["exclude"] = exclude if include is not None: - json_payload["include"] = include + params["include"] = include - if not json_payload: + if not params: raise ValueError( "At least one parameter is required for /access_grants/get_related" ) - res = self.client.post("/access_grants/get_related", json=json_payload) + res = self.client.get("/access_grants/get_related", params=params) return Batch.from_dict(res["batch"]) @@ -476,36 +476,36 @@ def list( :param user_identity_id: ID of user identity by which you want to filter the list of Access Grants. :returns: OK""" - json_payload: Dict[str, Any] = {} + params: Dict[str, Any] = {} if access_code_id is not None: - json_payload["access_code_id"] = access_code_id + params["access_code_id"] = access_code_id if access_grant_ids is not None: - json_payload["access_grant_ids"] = access_grant_ids + params["access_grant_ids"] = access_grant_ids if access_grant_key is not None: - json_payload["access_grant_key"] = access_grant_key + params["access_grant_key"] = access_grant_key if acs_entrance_id is not None: - json_payload["acs_entrance_id"] = acs_entrance_id + params["acs_entrance_id"] = acs_entrance_id if acs_system_id is not None: - json_payload["acs_system_id"] = acs_system_id + params["acs_system_id"] = acs_system_id if customer_key is not None: - json_payload["customer_key"] = customer_key + params["customer_key"] = customer_key if device_id is not None: - json_payload["device_id"] = device_id + params["device_id"] = device_id if limit is not None: - json_payload["limit"] = limit + params["limit"] = limit if location_id is not None: - json_payload["location_id"] = location_id + params["location_id"] = location_id if page_cursor is not None: - json_payload["page_cursor"] = page_cursor + params["page_cursor"] = page_cursor if reservation_key is not None: - json_payload["reservation_key"] = reservation_key + params["reservation_key"] = reservation_key if space_id is not None: - json_payload["space_id"] = space_id + params["space_id"] = space_id if user_identity_id is not None: - json_payload["user_identity_id"] = user_identity_id + params["user_identity_id"] = user_identity_id - res = self.client.post("/access_grants/list", json=json_payload) + res = self.client.get("/access_grants/list", params=params) return [AccessGrant.from_dict(item) for item in res["access_grants"]] diff --git a/seam/routes/access_methods.py b/seam/routes/access_methods.py index c98b129..5de0767 100644 --- a/seam/routes/access_methods.py +++ b/seam/routes/access_methods.py @@ -364,21 +364,21 @@ def get_related( :returns: OK :raises ValueError: At least one parameter must be provided.""" - json_payload: Dict[str, Any] = {} + params: Dict[str, Any] = {} if access_method_ids is not None: - json_payload["access_method_ids"] = access_method_ids + params["access_method_ids"] = access_method_ids if exclude is not None: - json_payload["exclude"] = exclude + params["exclude"] = exclude if include is not None: - json_payload["include"] = include + params["include"] = include - if not json_payload: + if not params: raise ValueError( "At least one parameter is required for /access_methods/get_related" ) - res = self.client.post("/access_methods/get_related", json=json_payload) + res = self.client.get("/access_methods/get_related", params=params) return Batch.from_dict(res["batch"]) diff --git a/seam/routes/acs_encoders.py b/seam/routes/acs_encoders.py index e90f2b5..7bfc114 100644 --- a/seam/routes/acs_encoders.py +++ b/seam/routes/acs_encoders.py @@ -236,20 +236,20 @@ def list( :param page_cursor: Identifies the specific page of results to return, obtained from the previous page's ``next_page_cursor``. :returns: OK""" - json_payload: Dict[str, Any] = {} + params: Dict[str, Any] = {} if acs_system_id is not None: - json_payload["acs_system_id"] = acs_system_id + params["acs_system_id"] = acs_system_id if acs_system_ids is not None: - json_payload["acs_system_ids"] = acs_system_ids + params["acs_system_ids"] = acs_system_ids if acs_encoder_ids is not None: - json_payload["acs_encoder_ids"] = acs_encoder_ids + params["acs_encoder_ids"] = acs_encoder_ids if limit is not None: - json_payload["limit"] = limit + params["limit"] = limit if page_cursor is not None: - json_payload["page_cursor"] = page_cursor + params["page_cursor"] = page_cursor - res = self.client.post("/acs/encoders/list", json=json_payload) + res = self.client.get("/acs/encoders/list", params=params) return [AcsEncoder.from_dict(item) for item in res["acs_encoders"]] diff --git a/seam/routes/acs_entrances.py b/seam/routes/acs_entrances.py index 8973de3..b4a0233 100644 --- a/seam/routes/acs_entrances.py +++ b/seam/routes/acs_entrances.py @@ -231,32 +231,32 @@ def list( :param space_id: ID of the space for which you want to list entrances. :returns: OK""" - json_payload: Dict[str, Any] = {} + params: Dict[str, Any] = {} if access_method_id is not None: - json_payload["access_method_id"] = access_method_id + params["access_method_id"] = access_method_id if acs_credential_id is not None: - json_payload["acs_credential_id"] = acs_credential_id + params["acs_credential_id"] = acs_credential_id if acs_entrance_ids is not None: - json_payload["acs_entrance_ids"] = acs_entrance_ids + params["acs_entrance_ids"] = acs_entrance_ids if acs_system_id is not None: - json_payload["acs_system_id"] = acs_system_id + params["acs_system_id"] = acs_system_id if connected_account_id is not None: - json_payload["connected_account_id"] = connected_account_id + params["connected_account_id"] = connected_account_id if customer_key is not None: - json_payload["customer_key"] = customer_key + params["customer_key"] = customer_key if limit is not None: - json_payload["limit"] = limit + params["limit"] = limit if location_id is not None: - json_payload["location_id"] = location_id + params["location_id"] = location_id if page_cursor is not None: - json_payload["page_cursor"] = page_cursor + params["page_cursor"] = page_cursor if search is not None: - json_payload["search"] = search + params["search"] = search if space_id is not None: - json_payload["space_id"] = space_id + params["space_id"] = space_id - res = self.client.post("/acs/entrances/list", json=json_payload) + res = self.client.get("/acs/entrances/list", params=params) return [AcsEntrance.from_dict(item) for item in res["acs_entrances"]] @@ -277,20 +277,20 @@ def list_credentials_with_access( :returns: OK :raises ValueError: At least one parameter must be provided.""" - json_payload: Dict[str, Any] = {} + params: Dict[str, Any] = {} if acs_entrance_id is not None: - json_payload["acs_entrance_id"] = acs_entrance_id + params["acs_entrance_id"] = acs_entrance_id if include_if is not None: - json_payload["include_if"] = include_if + params["include_if"] = include_if - if not json_payload: + if not params: raise ValueError( "At least one parameter is required for /acs/entrances/list_credentials_with_access" ) - res = self.client.post( - "/acs/entrances/list_credentials_with_access", json=json_payload + res = self.client.get( + "/acs/entrances/list_credentials_with_access", params=params ) return [AcsCredential.from_dict(item) for item in res["acs_credentials"]] diff --git a/seam/routes/action_attempts.py b/seam/routes/action_attempts.py index dc1a147..95f8ea3 100644 --- a/seam/routes/action_attempts.py +++ b/seam/routes/action_attempts.py @@ -119,17 +119,17 @@ def list( :param page_cursor: Identifies the specific page of results to return, obtained from the previous page's ``next_page_cursor``. :returns: OK""" - json_payload: Dict[str, Any] = {} + params: Dict[str, Any] = {} if action_attempt_ids is not None: - json_payload["action_attempt_ids"] = action_attempt_ids + params["action_attempt_ids"] = action_attempt_ids if device_id is not None: - json_payload["device_id"] = device_id + params["device_id"] = device_id if limit is not None: - json_payload["limit"] = limit + params["limit"] = limit if page_cursor is not None: - json_payload["page_cursor"] = page_cursor + params["page_cursor"] = page_cursor - res = self.client.post("/action_attempts/list", json=json_payload) + res = self.client.get("/action_attempts/list", params=params) return [ActionAttempt.from_dict(item) for item in res["action_attempts"]] diff --git a/seam/routes/connect_webviews.py b/seam/routes/connect_webviews.py index 69a0e88..a9f6808 100644 --- a/seam/routes/connect_webviews.py +++ b/seam/routes/connect_webviews.py @@ -273,21 +273,21 @@ def list( :param user_identifier_key: Your user ID for the user by which you want to filter Connect Webviews. :returns: OK""" - json_payload: Dict[str, Any] = {} + params: Dict[str, Any] = {} if custom_metadata_has is not None: - json_payload["custom_metadata_has"] = custom_metadata_has + params["custom_metadata_has"] = custom_metadata_has if customer_key is not None: - json_payload["customer_key"] = customer_key + params["customer_key"] = customer_key if limit is not None: - json_payload["limit"] = limit + params["limit"] = limit if page_cursor is not None: - json_payload["page_cursor"] = page_cursor + params["page_cursor"] = page_cursor if search is not None: - json_payload["search"] = search + params["search"] = search if user_identifier_key is not None: - json_payload["user_identifier_key"] = user_identifier_key + params["user_identifier_key"] = user_identifier_key - res = self.client.post("/connect_webviews/list", json=json_payload) + res = self.client.get("/connect_webviews/list", params=params) return [ConnectWebview.from_dict(item) for item in res["connect_webviews"]] diff --git a/seam/routes/connected_accounts.py b/seam/routes/connected_accounts.py index 8aef31d..268a6ce 100644 --- a/seam/routes/connected_accounts.py +++ b/seam/routes/connected_accounts.py @@ -219,24 +219,24 @@ def list( :param user_identifier_key: Your user ID for the user by which you want to filter connected accounts. :returns: OK""" - json_payload: Dict[str, Any] = {} + params: Dict[str, Any] = {} if custom_metadata_has is not None: - json_payload["custom_metadata_has"] = custom_metadata_has + params["custom_metadata_has"] = custom_metadata_has if customer_key is not None: - json_payload["customer_key"] = customer_key + params["customer_key"] = customer_key if limit is not None: - json_payload["limit"] = limit + params["limit"] = limit if page_cursor is not None: - json_payload["page_cursor"] = page_cursor + params["page_cursor"] = page_cursor if search is not None: - json_payload["search"] = search + params["search"] = search if space_id is not None: - json_payload["space_id"] = space_id + params["space_id"] = space_id if user_identifier_key is not None: - json_payload["user_identifier_key"] = user_identifier_key + params["user_identifier_key"] = user_identifier_key - res = self.client.post("/connected_accounts/list", json=json_payload) + res = self.client.get("/connected_accounts/list", params=params) return [ConnectedAccount.from_dict(item) for item in res["connected_accounts"]] diff --git a/seam/routes/customers.py b/seam/routes/customers.py index 6130f95..79bf921 100644 --- a/seam/routes/customers.py +++ b/seam/routes/customers.py @@ -334,48 +334,48 @@ def delete_data( :param user_identity_keys: List of user identity keys to delete. :param user_keys: List of user keys to delete.""" - json_payload: Dict[str, Any] = {} + params: Dict[str, Any] = {} if access_grant_keys is not None: - json_payload["access_grant_keys"] = access_grant_keys + params["access_grant_keys"] = access_grant_keys if booking_keys is not None: - json_payload["booking_keys"] = booking_keys + params["booking_keys"] = booking_keys if building_keys is not None: - json_payload["building_keys"] = building_keys + params["building_keys"] = building_keys if common_area_keys is not None: - json_payload["common_area_keys"] = common_area_keys + params["common_area_keys"] = common_area_keys if customer_keys is not None: - json_payload["customer_keys"] = customer_keys + params["customer_keys"] = customer_keys if facility_keys is not None: - json_payload["facility_keys"] = facility_keys + params["facility_keys"] = facility_keys if guest_keys is not None: - json_payload["guest_keys"] = guest_keys + params["guest_keys"] = guest_keys if listing_keys is not None: - json_payload["listing_keys"] = listing_keys + params["listing_keys"] = listing_keys if property_keys is not None: - json_payload["property_keys"] = property_keys + params["property_keys"] = property_keys if property_listing_keys is not None: - json_payload["property_listing_keys"] = property_listing_keys + params["property_listing_keys"] = property_listing_keys if reservation_keys is not None: - json_payload["reservation_keys"] = reservation_keys + params["reservation_keys"] = reservation_keys if resident_keys is not None: - json_payload["resident_keys"] = resident_keys + params["resident_keys"] = resident_keys if room_keys is not None: - json_payload["room_keys"] = room_keys + params["room_keys"] = room_keys if space_keys is not None: - json_payload["space_keys"] = space_keys + params["space_keys"] = space_keys if staff_member_keys is not None: - json_payload["staff_member_keys"] = staff_member_keys + params["staff_member_keys"] = staff_member_keys if tenant_keys is not None: - json_payload["tenant_keys"] = tenant_keys + params["tenant_keys"] = tenant_keys if unit_keys is not None: - json_payload["unit_keys"] = unit_keys + params["unit_keys"] = unit_keys if user_identity_keys is not None: - json_payload["user_identity_keys"] = user_identity_keys + params["user_identity_keys"] = user_identity_keys if user_keys is not None: - json_payload["user_keys"] = user_keys + params["user_keys"] = user_keys - self.client.post("/customers/delete_data", json=json_payload) + self.client.delete("/customers/delete_data", params=params) return None diff --git a/seam/routes/devices.py b/seam/routes/devices.py index 7afdaa7..8a0761a 100644 --- a/seam/routes/devices.py +++ b/seam/routes/devices.py @@ -254,42 +254,42 @@ def list( :param user_identifier_key: Your own internal user ID for the user for which you want to list devices. :returns: OK""" - json_payload: Dict[str, Any] = {} + params: Dict[str, Any] = {} if connect_webview_id is not None: - json_payload["connect_webview_id"] = connect_webview_id + params["connect_webview_id"] = connect_webview_id if connected_account_id is not None: - json_payload["connected_account_id"] = connected_account_id + params["connected_account_id"] = connected_account_id if connected_account_ids is not None: - json_payload["connected_account_ids"] = connected_account_ids + params["connected_account_ids"] = connected_account_ids if created_before is not None: - json_payload["created_before"] = created_before + params["created_before"] = created_before if custom_metadata_has is not None: - json_payload["custom_metadata_has"] = custom_metadata_has + params["custom_metadata_has"] = custom_metadata_has if customer_key is not None: - json_payload["customer_key"] = customer_key + params["customer_key"] = customer_key if device_ids is not None: - json_payload["device_ids"] = device_ids + params["device_ids"] = device_ids if device_type is not None: - json_payload["device_type"] = device_type + params["device_type"] = device_type if device_types is not None: - json_payload["device_types"] = device_types + params["device_types"] = device_types if limit is not None: - json_payload["limit"] = limit + params["limit"] = limit if manufacturer is not None: - json_payload["manufacturer"] = manufacturer + params["manufacturer"] = manufacturer if page_cursor is not None: - json_payload["page_cursor"] = page_cursor + params["page_cursor"] = page_cursor if search is not None: - json_payload["search"] = search + params["search"] = search if space_id is not None: - json_payload["space_id"] = space_id + params["space_id"] = space_id if unstable_location_id is not None: - json_payload["unstable_location_id"] = unstable_location_id + params["unstable_location_id"] = unstable_location_id if user_identifier_key is not None: - json_payload["user_identifier_key"] = user_identifier_key + params["user_identifier_key"] = user_identifier_key - res = self.client.post("/devices/list", json=json_payload) + res = self.client.get("/devices/list", params=params) return [Device.from_dict(item) for item in res["devices"]] diff --git a/seam/routes/devices_unmanaged.py b/seam/routes/devices_unmanaged.py index 670e355..79439d6 100644 --- a/seam/routes/devices_unmanaged.py +++ b/seam/routes/devices_unmanaged.py @@ -189,34 +189,34 @@ def list( :param search: String for which to search. Filters returned devices to include all records that satisfy a partial match using ``device_id`` (full or partial UUID prefix, minimum 4 characters), ``connected_account_id``, ``display_name``, ``custom_metadata`` or ``location.location_name``. :returns: OK""" - json_payload: Dict[str, Any] = {} + params: Dict[str, Any] = {} if connect_webview_id is not None: - json_payload["connect_webview_id"] = connect_webview_id + params["connect_webview_id"] = connect_webview_id if connected_account_id is not None: - json_payload["connected_account_id"] = connected_account_id + params["connected_account_id"] = connected_account_id if connected_account_ids is not None: - json_payload["connected_account_ids"] = connected_account_ids + params["connected_account_ids"] = connected_account_ids if created_before is not None: - json_payload["created_before"] = created_before + params["created_before"] = created_before if customer_key is not None: - json_payload["customer_key"] = customer_key + params["customer_key"] = customer_key if device_ids is not None: - json_payload["device_ids"] = device_ids + params["device_ids"] = device_ids if device_type is not None: - json_payload["device_type"] = device_type + params["device_type"] = device_type if device_types is not None: - json_payload["device_types"] = device_types + params["device_types"] = device_types if limit is not None: - json_payload["limit"] = limit + params["limit"] = limit if manufacturer is not None: - json_payload["manufacturer"] = manufacturer + params["manufacturer"] = manufacturer if page_cursor is not None: - json_payload["page_cursor"] = page_cursor + params["page_cursor"] = page_cursor if search is not None: - json_payload["search"] = search + params["search"] = search - res = self.client.post("/devices/unmanaged/list", json=json_payload) + res = self.client.get("/devices/unmanaged/list", params=params) return [UnmanagedDevice.from_dict(item) for item in res["devices"]] diff --git a/seam/routes/events.py b/seam/routes/events.py index 24cf174..9d1e0c5 100644 --- a/seam/routes/events.py +++ b/seam/routes/events.py @@ -263,68 +263,68 @@ def list( :returns: OK :raises ValueError: At least one parameter must be provided.""" - json_payload: Dict[str, Any] = {} + params: Dict[str, Any] = {} if access_code_id is not None: - json_payload["access_code_id"] = access_code_id + params["access_code_id"] = access_code_id if access_code_ids is not None: - json_payload["access_code_ids"] = access_code_ids + params["access_code_ids"] = access_code_ids if access_grant_id is not None: - json_payload["access_grant_id"] = access_grant_id + params["access_grant_id"] = access_grant_id if access_grant_ids is not None: - json_payload["access_grant_ids"] = access_grant_ids + params["access_grant_ids"] = access_grant_ids if access_method_id is not None: - json_payload["access_method_id"] = access_method_id + params["access_method_id"] = access_method_id if access_method_ids is not None: - json_payload["access_method_ids"] = access_method_ids + params["access_method_ids"] = access_method_ids if acs_access_group_id is not None: - json_payload["acs_access_group_id"] = acs_access_group_id + params["acs_access_group_id"] = acs_access_group_id if acs_credential_id is not None: - json_payload["acs_credential_id"] = acs_credential_id + params["acs_credential_id"] = acs_credential_id if acs_encoder_id is not None: - json_payload["acs_encoder_id"] = acs_encoder_id + params["acs_encoder_id"] = acs_encoder_id if acs_entrance_id is not None: - json_payload["acs_entrance_id"] = acs_entrance_id + params["acs_entrance_id"] = acs_entrance_id if acs_system_id is not None: - json_payload["acs_system_id"] = acs_system_id + params["acs_system_id"] = acs_system_id if acs_system_ids is not None: - json_payload["acs_system_ids"] = acs_system_ids + params["acs_system_ids"] = acs_system_ids if acs_user_id is not None: - json_payload["acs_user_id"] = acs_user_id + params["acs_user_id"] = acs_user_id if between is not None: - json_payload["between"] = between + params["between"] = between if connect_webview_id is not None: - json_payload["connect_webview_id"] = connect_webview_id + params["connect_webview_id"] = connect_webview_id if connected_account_id is not None: - json_payload["connected_account_id"] = connected_account_id + params["connected_account_id"] = connected_account_id if customer_key is not None: - json_payload["customer_key"] = customer_key + params["customer_key"] = customer_key if device_id is not None: - json_payload["device_id"] = device_id + params["device_id"] = device_id if device_ids is not None: - json_payload["device_ids"] = device_ids + params["device_ids"] = device_ids if event_ids is not None: - json_payload["event_ids"] = event_ids + params["event_ids"] = event_ids if event_type is not None: - json_payload["event_type"] = event_type + params["event_type"] = event_type if event_types is not None: - json_payload["event_types"] = event_types + params["event_types"] = event_types if limit is not None: - json_payload["limit"] = limit + params["limit"] = limit if since is not None: - json_payload["since"] = since + params["since"] = since if space_id is not None: - json_payload["space_id"] = space_id + params["space_id"] = space_id if space_ids is not None: - json_payload["space_ids"] = space_ids + params["space_ids"] = space_ids if unstable_offset is not None: - json_payload["unstable_offset"] = unstable_offset + params["unstable_offset"] = unstable_offset if user_identity_id is not None: - json_payload["user_identity_id"] = user_identity_id + params["user_identity_id"] = user_identity_id - if not json_payload: + if not params: raise ValueError("At least one parameter is required for /events/list") - res = self.client.post("/events/list", json=json_payload) + res = self.client.get("/events/list", params=params) return [SeamEvent.from_dict(item) for item in res["events"]] diff --git a/seam/routes/locks.py b/seam/routes/locks.py index 2165d26..849ab0f 100644 --- a/seam/routes/locks.py +++ b/seam/routes/locks.py @@ -245,22 +245,22 @@ def list( :param manufacturer: Manufacturer of the locks that you want to list. :returns: OK""" - json_payload: Dict[str, Any] = {} + params: Dict[str, Any] = {} if connect_webview_id is not None: - json_payload["connect_webview_id"] = connect_webview_id + params["connect_webview_id"] = connect_webview_id if connected_account_id is not None: - json_payload["connected_account_id"] = connected_account_id + params["connected_account_id"] = connected_account_id if customer_key is not None: - json_payload["customer_key"] = customer_key + params["customer_key"] = customer_key if device_type is not None: - json_payload["device_type"] = device_type + params["device_type"] = device_type if device_types is not None: - json_payload["device_types"] = device_types + params["device_types"] = device_types if manufacturer is not None: - json_payload["manufacturer"] = manufacturer + params["manufacturer"] = manufacturer - res = self.client.post("/locks/list", json=json_payload) + res = self.client.get("/locks/list", params=params) return [Device.from_dict(item) for item in res["devices"]] diff --git a/seam/routes/noise_sensors.py b/seam/routes/noise_sensors.py index d93c1c7..2de1897 100644 --- a/seam/routes/noise_sensors.py +++ b/seam/routes/noise_sensors.py @@ -96,21 +96,21 @@ def list( :param manufacturer: Manufacturers of the noise sensors that you want to list. :returns: OK""" - json_payload: Dict[str, Any] = {} + params: Dict[str, Any] = {} if connect_webview_id is not None: - json_payload["connect_webview_id"] = connect_webview_id + params["connect_webview_id"] = connect_webview_id if connected_account_id is not None: - json_payload["connected_account_id"] = connected_account_id + params["connected_account_id"] = connected_account_id if customer_key is not None: - json_payload["customer_key"] = customer_key + params["customer_key"] = customer_key if device_type is not None: - json_payload["device_type"] = device_type + params["device_type"] = device_type if device_types is not None: - json_payload["device_types"] = device_types + params["device_types"] = device_types if manufacturer is not None: - json_payload["manufacturer"] = manufacturer + params["manufacturer"] = manufacturer - res = self.client.post("/noise_sensors/list", json=json_payload) + res = self.client.get("/noise_sensors/list", params=params) return [Device.from_dict(item) for item in res["devices"]] diff --git a/seam/routes/spaces.py b/seam/routes/spaces.py index 17b8175..33edcfd 100644 --- a/seam/routes/spaces.py +++ b/seam/routes/spaces.py @@ -438,23 +438,23 @@ def get_related( :returns: OK :raises ValueError: At least one parameter must be provided.""" - json_payload: Dict[str, Any] = {} + params: Dict[str, Any] = {} if exclude is not None: - json_payload["exclude"] = exclude + params["exclude"] = exclude if include is not None: - json_payload["include"] = include + params["include"] = include if space_ids is not None: - json_payload["space_ids"] = space_ids + params["space_ids"] = space_ids if space_keys is not None: - json_payload["space_keys"] = space_keys + params["space_keys"] = space_keys - if not json_payload: + if not params: raise ValueError( "At least one parameter is required for /spaces/get_related" ) - res = self.client.post("/spaces/get_related", json=json_payload) + res = self.client.get("/spaces/get_related", params=params) return Batch.from_dict(res["batch"]) @@ -515,19 +515,19 @@ def remove_acs_entrances( :param space_id: ID of the space from which you want to remove entrances. :raises ValueError: At least one parameter must be provided.""" - json_payload: Dict[str, Any] = {} + params: Dict[str, Any] = {} if acs_entrance_ids is not None: - json_payload["acs_entrance_ids"] = acs_entrance_ids + params["acs_entrance_ids"] = acs_entrance_ids if space_id is not None: - json_payload["space_id"] = space_id + params["space_id"] = space_id - if not json_payload: + if not params: raise ValueError( "At least one parameter is required for /spaces/remove_acs_entrances" ) - self.client.post("/spaces/remove_acs_entrances", json=json_payload) + self.client.delete("/spaces/remove_acs_entrances", params=params) return None @@ -575,19 +575,19 @@ def remove_devices(self, *, device_ids: List[str], space_id: str) -> None: :param space_id: ID of the space from which you want to remove devices. :raises ValueError: At least one parameter must be provided.""" - json_payload: Dict[str, Any] = {} + params: Dict[str, Any] = {} if device_ids is not None: - json_payload["device_ids"] = device_ids + params["device_ids"] = device_ids if space_id is not None: - json_payload["space_id"] = space_id + params["space_id"] = space_id - if not json_payload: + if not params: raise ValueError( "At least one parameter is required for /spaces/remove_devices" ) - self.client.post("/spaces/remove_devices", json=json_payload) + self.client.delete("/spaces/remove_devices", params=params) return None diff --git a/seam/routes/thermostats.py b/seam/routes/thermostats.py index 9273740..4110b1c 100644 --- a/seam/routes/thermostats.py +++ b/seam/routes/thermostats.py @@ -791,22 +791,22 @@ def list( :param manufacturer: Manufacturer by which you want to filter thermostat devices. :returns: OK""" - json_payload: Dict[str, Any] = {} + params: Dict[str, Any] = {} if connect_webview_id is not None: - json_payload["connect_webview_id"] = connect_webview_id + params["connect_webview_id"] = connect_webview_id if connected_account_id is not None: - json_payload["connected_account_id"] = connected_account_id + params["connected_account_id"] = connected_account_id if customer_key is not None: - json_payload["customer_key"] = customer_key + params["customer_key"] = customer_key if device_type is not None: - json_payload["device_type"] = device_type + params["device_type"] = device_type if device_types is not None: - json_payload["device_types"] = device_types + params["device_types"] = device_types if manufacturer is not None: - json_payload["manufacturer"] = manufacturer + params["manufacturer"] = manufacturer - res = self.client.post("/thermostats/list", json=json_payload) + res = self.client.get("/thermostats/list", params=params) return [Device.from_dict(item) for item in res["devices"]] diff --git a/seam/routes/user_identities.py b/seam/routes/user_identities.py index 9f3c1fb..2f42d0a 100644 --- a/seam/routes/user_identities.py +++ b/seam/routes/user_identities.py @@ -507,24 +507,24 @@ def list( :param user_identity_ids: Array of user identity IDs by which to filter the list of user identities. :returns: OK""" - json_payload: Dict[str, Any] = {} + params: Dict[str, Any] = {} if created_before is not None: - json_payload["created_before"] = created_before + params["created_before"] = created_before if credential_manager_acs_system_id is not None: - json_payload["credential_manager_acs_system_id"] = ( + params["credential_manager_acs_system_id"] = ( credential_manager_acs_system_id ) if limit is not None: - json_payload["limit"] = limit + params["limit"] = limit if page_cursor is not None: - json_payload["page_cursor"] = page_cursor + params["page_cursor"] = page_cursor if search is not None: - json_payload["search"] = search + params["search"] = search if user_identity_ids is not None: - json_payload["user_identity_ids"] = user_identity_ids + params["user_identity_ids"] = user_identity_ids - res = self.client.post("/user_identities/list", json=json_payload) + res = self.client.get("/user_identities/list", params=params) return [UserIdentity.from_dict(item) for item in res["user_identities"]] From 95a9bb917447ba1dd30d515835d26daba6ef04b4 Mon Sep 17 00:00:00 2001 From: Evan Sosenko Date: Tue, 18 Aug 2026 21:32:15 -0700 Subject: [PATCH 3/3] test: Update tests for GET routes --- package-lock.json | 30 ++++++------------------------ package.json | 2 +- test/http_error_test.py | 4 ++-- test/retry_test.py | 9 +++------ test/timeout_test.py | 2 +- 5 files changed, 13 insertions(+), 34 deletions(-) diff --git a/package-lock.json b/package-lock.json index dfc7f5a..f4edd7b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,7 +7,7 @@ "name": "@seamapi/python", "devDependencies": { "@seamapi/blueprint": "^1.8.0", - "@seamapi/fake-seam-connect": "1.86.0", + "@seamapi/fake-seam-connect": "2.0.4", "@seamapi/smith": "^1.1.0", "@seamapi/types": "1.1001.0", "change-case": "^5.4.4", @@ -801,38 +801,20 @@ "npm": ">=10.0.0" } }, - "node_modules/@seamapi/fake-devicedb": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@seamapi/fake-devicedb/-/fake-devicedb-1.6.1.tgz", - "integrity": "sha512-w4Ar/s2kPnE5ExJSlpD3sKL8lkF+rLHRROArIRxtR2reHfnDSVwnDt9TzBYkHqgMP/x4o7LUzlRRpobn2xn24A==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=18.12.0", - "npm": ">= 9.0.0" - }, - "optionalDependencies": { - "zod": "^3.21.4", - "zustand": "^4.3.7", - "zustand-hoist": "^2.0.0" - } - }, "node_modules/@seamapi/fake-seam-connect": { - "version": "1.86.0", - "resolved": "https://registry.npmjs.org/@seamapi/fake-seam-connect/-/fake-seam-connect-1.86.0.tgz", - "integrity": "sha512-iO5fwtSIPhzmIiLxrFDtCYF/7HTb+ywcGmc3WzWt8Sr0bLQlmwCyTJ8YYZy++Hx0FsnNpa5AmlJuJGul9Y5gZA==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@seamapi/fake-seam-connect/-/fake-seam-connect-2.0.4.tgz", + "integrity": "sha512-pgPUhIMW462B3jIWTuhH/aK2wUxRuOLjhsjB7YxdXw2g+hTVRJ5w4t01spETu1g2bch3Rzffd0whUVLeC4vjwQ==", "dev": true, "license": "MIT", "bin": { "fake-seam-connect": "dist/server.js" }, "engines": { - "node": ">=18.12.0", - "npm": ">= 9.0.0" + "node": ">=22.12.0", + "npm": ">=10.0.0" }, "optionalDependencies": { - "@seamapi/fake-devicedb": ">=1.0.0-rc.0", "zustand": "^4.3.7", "zustand-hoist": "^2.0.0" } diff --git a/package.json b/package.json index 2bc724a..0b104a8 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ }, "devDependencies": { "@seamapi/blueprint": "^1.8.0", - "@seamapi/fake-seam-connect": "1.86.0", + "@seamapi/fake-seam-connect": "2.0.4", "@seamapi/smith": "^1.1.0", "@seamapi/types": "1.1001.0", "change-case": "^5.4.4", diff --git a/test/http_error_test.py b/test/http_error_test.py index 0042772..40d1d35 100644 --- a/test/http_error_test.py +++ b/test/http_error_test.py @@ -40,7 +40,7 @@ def test_seam_http_throws_invalid_input_error(server): seam = Seam(api_key=seed["seam_apikey1_token"], endpoint=endpoint) with pytest.raises(SeamHttpInvalidInputError) as exc_info: - seam.devices.list(device_ids=4242) + seam.client.post("/devices/list", json={"device_ids": 4242}) err = exc_info.value assert err.status_code == 400 assert err.code == "invalid_input" @@ -56,7 +56,7 @@ def test_seam_http_invalid_input_error_has_no_messages_for_unknown_param(server) seam = Seam(api_key=seed["seam_apikey1_token"], endpoint=endpoint) with pytest.raises(SeamHttpInvalidInputError) as exc_info: - seam.devices.list(device_ids=4242) + seam.client.post("/devices/list", json={"device_ids": 4242}) assert exc_info.value.get_validation_error_messages("non_existent_param") == [] diff --git a/test/retry_test.py b/test/retry_test.py index a9ebdd0..7ae358b 100644 --- a/test/retry_test.py +++ b/test/retry_test.py @@ -47,8 +47,7 @@ def test_seam_retries_service_unavailable_responses(recording_server): endpoint=endpoint, retries=retry_policy(total=expected_retry_count), ) - # TODO: Use seam.devices.list() once the generated SDK route uses GET. - devices = seam.client.get("/devices/list")["devices"] + devices = seam.devices.list() assert len(devices) == 1 assert len(requests) == expected_retry_count + 1 @@ -65,8 +64,7 @@ def test_seam_stops_retrying_once_retries_are_exhausted(recording_server): ) with pytest.raises(HTTPStatusError) as exc_info: - # TODO: Use seam.devices.list() once the generated SDK route uses GET. - seam.client.get("/devices/list") + seam.devices.list() assert exc_info.value.response.status_code == 503 assert len(requests) == expected_retry_count + 1 @@ -79,8 +77,7 @@ def test_seam_does_not_retry_when_retries_are_disabled(recording_server): ) with pytest.raises(HTTPStatusError) as exc_info: - # TODO: Use seam.devices.list() once the generated SDK route uses GET. - seam.client.get("/devices/list") + seam.devices.list() assert exc_info.value.response.status_code == 503 assert len(requests) == 1 diff --git a/test/timeout_test.py b/test/timeout_test.py index a7aff19..ced7e67 100644 --- a/test/timeout_test.py +++ b/test/timeout_test.py @@ -114,7 +114,7 @@ class Handler(BaseHTTPRequestHandler): protocol_version = "HTTP/1.1" # pylint: disable-next=invalid-name - def do_POST(self): + def do_GET(self): time.sleep(5) self.send_response(200) self.send_header("content-length", "0")