From c8085ef8be26472dc5a63bdf038fe1fd377a30e0 Mon Sep 17 00:00:00 2001 From: activitysmith-bot Date: Sat, 7 Nov 2026 08:32:57 +0000 Subject: [PATCH 1/2] chore: regenerate SDK --- activitysmith_openapi/__init__.py | 5 + activitysmith_openapi/api/__init__.py | 1 + activitysmith_openapi/api/devices_api.py | 340 ++++++++++++++++++ .../api/live_activities_api.py | 6 +- .../api/push_notifications_api.py | 275 ++++++++++++++ activitysmith_openapi/docs/AccountDevice.md | 40 +++ .../docs/AccountDeviceListResponse.md | 30 ++ .../docs/AccountDeviceListResponseMeta.md | 34 ++ .../docs/AppIconBadgesApi.md | 12 +- activitysmith_openapi/docs/DevicesApi.md | 93 +++++ .../docs/LiveActivitiesApi.md | 42 +-- activitysmith_openapi/docs/MetricsApi.md | 20 +- .../docs/PushNotificationDismissResponse.md | 32 ++ .../docs/PushNotificationsApi.md | 108 +++++- activitysmith_openapi/models/__init__.py | 4 + .../models/account_device.py | 143 ++++++++ .../models/account_device_list_response.py | 101 ++++++ .../account_device_list_response_meta.py | 102 ++++++ .../push_notification_dismiss_response.py | 92 +++++ activitysmith_openapi/openapi-source.json | 4 +- .../test/test_account_device.py | 76 ++++ .../test/test_account_device_list_response.py | 96 +++++ .../test_account_device_list_response_meta.py | 62 ++++ .../test/test_devices_api.py | 38 ++ ...test_push_notification_dismiss_response.py | 56 +++ .../test/test_push_notifications_api.py | 7 + 26 files changed, 1765 insertions(+), 54 deletions(-) create mode 100644 activitysmith_openapi/api/devices_api.py create mode 100644 activitysmith_openapi/docs/AccountDevice.md create mode 100644 activitysmith_openapi/docs/AccountDeviceListResponse.md create mode 100644 activitysmith_openapi/docs/AccountDeviceListResponseMeta.md create mode 100644 activitysmith_openapi/docs/DevicesApi.md create mode 100644 activitysmith_openapi/docs/PushNotificationDismissResponse.md create mode 100644 activitysmith_openapi/models/account_device.py create mode 100644 activitysmith_openapi/models/account_device_list_response.py create mode 100644 activitysmith_openapi/models/account_device_list_response_meta.py create mode 100644 activitysmith_openapi/models/push_notification_dismiss_response.py create mode 100644 activitysmith_openapi/test/test_account_device.py create mode 100644 activitysmith_openapi/test/test_account_device_list_response.py create mode 100644 activitysmith_openapi/test/test_account_device_list_response_meta.py create mode 100644 activitysmith_openapi/test/test_devices_api.py create mode 100644 activitysmith_openapi/test/test_push_notification_dismiss_response.py diff --git a/activitysmith_openapi/__init__.py b/activitysmith_openapi/__init__.py index 56604b6..3533b9a 100644 --- a/activitysmith_openapi/__init__.py +++ b/activitysmith_openapi/__init__.py @@ -18,6 +18,7 @@ # import apis into sdk package from activitysmith_openapi.api.app_icon_badges_api import AppIconBadgesApi +from activitysmith_openapi.api.devices_api import DevicesApi from activitysmith_openapi.api.live_activities_api import LiveActivitiesApi from activitysmith_openapi.api.metrics_api import MetricsApi from activitysmith_openapi.api.push_notifications_api import PushNotificationsApi @@ -34,6 +35,9 @@ from activitysmith_openapi.exceptions import ApiException # import models into sdk package +from activitysmith_openapi.models.account_device import AccountDevice +from activitysmith_openapi.models.account_device_list_response import AccountDeviceListResponse +from activitysmith_openapi.models.account_device_list_response_meta import AccountDeviceListResponseMeta from activitysmith_openapi.models.activity_metric import ActivityMetric from activitysmith_openapi.models.activity_metric_value import ActivityMetricValue from activitysmith_openapi.models.alert_payload import AlertPayload @@ -79,6 +83,7 @@ from activitysmith_openapi.models.push_interruption_level import PushInterruptionLevel from activitysmith_openapi.models.push_notification_action import PushNotificationAction from activitysmith_openapi.models.push_notification_action_type import PushNotificationActionType +from activitysmith_openapi.models.push_notification_dismiss_response import PushNotificationDismissResponse from activitysmith_openapi.models.push_notification_replace_request import PushNotificationReplaceRequest from activitysmith_openapi.models.push_notification_replace_response import PushNotificationReplaceResponse from activitysmith_openapi.models.push_notification_request import PushNotificationRequest diff --git a/activitysmith_openapi/api/__init__.py b/activitysmith_openapi/api/__init__.py index f70481e..4b47c17 100644 --- a/activitysmith_openapi/api/__init__.py +++ b/activitysmith_openapi/api/__init__.py @@ -2,6 +2,7 @@ # import apis into api package from activitysmith_openapi.api.app_icon_badges_api import AppIconBadgesApi +from activitysmith_openapi.api.devices_api import DevicesApi from activitysmith_openapi.api.live_activities_api import LiveActivitiesApi from activitysmith_openapi.api.metrics_api import MetricsApi from activitysmith_openapi.api.push_notifications_api import PushNotificationsApi diff --git a/activitysmith_openapi/api/devices_api.py b/activitysmith_openapi/api/devices_api.py new file mode 100644 index 0000000..d294278 --- /dev/null +++ b/activitysmith_openapi/api/devices_api.py @@ -0,0 +1,340 @@ +# coding: utf-8 + +""" + ActivitySmith API + + Send push notifications and Live Activities to your own devices via a single API key. + + The version of the OpenAPI document: 1.0.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + +import warnings +from pydantic import validate_call, Field, StrictFloat, StrictStr, StrictInt +from typing import Any, Dict, List, Optional, Tuple, Union +from typing_extensions import Annotated + +from pydantic import Field, StrictBool +from typing import Optional +from typing_extensions import Annotated +from activitysmith_openapi.models.account_device_list_response import AccountDeviceListResponse + +from activitysmith_openapi.api_client import ApiClient, RequestSerialized +from activitysmith_openapi.api_response import ApiResponse +from activitysmith_openapi.rest import RESTResponseType + + +class DevicesApi: + """NOTE: This class is auto generated by OpenAPI Generator + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + def __init__(self, api_client=None) -> None: + if api_client is None: + api_client = ApiClient.get_default() + self.api_client = api_client + + + @validate_call + def list_account_devices( + self, + limit: Annotated[Optional[Annotated[int, Field(le=100, strict=True, ge=1)]], Field(description="Maximum devices to return, 1 to 100. Defaults to 100.")] = None, + offset: Annotated[Optional[Annotated[int, Field(strict=True, ge=0)]], Field(description="Devices to skip. Use meta.next_offset from the previous page.")] = None, + include_inactive: Annotated[Optional[StrictBool], Field(description="Include devices that can no longer receive deliveries, such as unpaired phones.")] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> AccountDeviceListResponse: + """List paired devices + + Lists the iPhones and iPads paired to the account, active devices first. Use it to check that a device is paired before you send, or to find device IDs for Channels. An empty list means no device is paired yet: install the ActivitySmith app from the App Store and sign in. Channel-scoped API keys cannot list devices. + + :param limit: Maximum devices to return, 1 to 100. Defaults to 100. + :type limit: int + :param offset: Devices to skip. Use meta.next_offset from the previous page. + :type offset: int + :param include_inactive: Include devices that can no longer receive deliveries, such as unpaired phones. + :type include_inactive: bool + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_account_devices_serialize( + limit=limit, + offset=offset, + include_inactive=include_inactive, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "AccountDeviceListResponse", + '403': "ForbiddenError", + '429': "RateLimitError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def list_account_devices_with_http_info( + self, + limit: Annotated[Optional[Annotated[int, Field(le=100, strict=True, ge=1)]], Field(description="Maximum devices to return, 1 to 100. Defaults to 100.")] = None, + offset: Annotated[Optional[Annotated[int, Field(strict=True, ge=0)]], Field(description="Devices to skip. Use meta.next_offset from the previous page.")] = None, + include_inactive: Annotated[Optional[StrictBool], Field(description="Include devices that can no longer receive deliveries, such as unpaired phones.")] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[AccountDeviceListResponse]: + """List paired devices + + Lists the iPhones and iPads paired to the account, active devices first. Use it to check that a device is paired before you send, or to find device IDs for Channels. An empty list means no device is paired yet: install the ActivitySmith app from the App Store and sign in. Channel-scoped API keys cannot list devices. + + :param limit: Maximum devices to return, 1 to 100. Defaults to 100. + :type limit: int + :param offset: Devices to skip. Use meta.next_offset from the previous page. + :type offset: int + :param include_inactive: Include devices that can no longer receive deliveries, such as unpaired phones. + :type include_inactive: bool + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_account_devices_serialize( + limit=limit, + offset=offset, + include_inactive=include_inactive, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "AccountDeviceListResponse", + '403': "ForbiddenError", + '429': "RateLimitError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def list_account_devices_without_preload_content( + self, + limit: Annotated[Optional[Annotated[int, Field(le=100, strict=True, ge=1)]], Field(description="Maximum devices to return, 1 to 100. Defaults to 100.")] = None, + offset: Annotated[Optional[Annotated[int, Field(strict=True, ge=0)]], Field(description="Devices to skip. Use meta.next_offset from the previous page.")] = None, + include_inactive: Annotated[Optional[StrictBool], Field(description="Include devices that can no longer receive deliveries, such as unpaired phones.")] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """List paired devices + + Lists the iPhones and iPads paired to the account, active devices first. Use it to check that a device is paired before you send, or to find device IDs for Channels. An empty list means no device is paired yet: install the ActivitySmith app from the App Store and sign in. Channel-scoped API keys cannot list devices. + + :param limit: Maximum devices to return, 1 to 100. Defaults to 100. + :type limit: int + :param offset: Devices to skip. Use meta.next_offset from the previous page. + :type offset: int + :param include_inactive: Include devices that can no longer receive deliveries, such as unpaired phones. + :type include_inactive: bool + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_account_devices_serialize( + limit=limit, + offset=offset, + include_inactive=include_inactive, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "AccountDeviceListResponse", + '403': "ForbiddenError", + '429': "RateLimitError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _list_account_devices_serialize( + self, + limit, + offset, + include_inactive, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[str, Union[str, bytes]] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + if limit is not None: + + _query_params.append(('limit', limit)) + + if offset is not None: + + _query_params.append(('offset', offset)) + + if include_inactive is not None: + + _query_params.append(('include_inactive', include_inactive)) + + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + 'apiKeyAuth' + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/account/devices', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + diff --git a/activitysmith_openapi/api/live_activities_api.py b/activitysmith_openapi/api/live_activities_api.py index db54610..8b971ea 100644 --- a/activitysmith_openapi/api/live_activities_api.py +++ b/activitysmith_openapi/api/live_activities_api.py @@ -67,7 +67,7 @@ def end_live_activity( ) -> LiveActivityEndResponse: """End a Live Activity (legacy manual lifecycle) - Legacy manual lifecycle endpoint. For new integrations, use DELETE /live-activity/stream/{stream_key} to end a managed Live Activity stream. This endpoint remains supported for existing integrations and advanced lifecycle control. Ends a Live Activity and archives its lifecycle. Supports segmented_progress, progress, metrics, stats, alert, timer, and value activity types. For segmented_progress activities, you can send the latest number_of_steps here if the workflow changed after start. Use secondary_action for a second button on alert, progress, segmented_progress, and value Live Activities. + Legacy manual lifecycle endpoint. For new integrations, use DELETE /live-activity/stream/{stream_key} to end a managed Live Activity stream. This endpoint remains supported for existing integrations and advanced lifecycle control. Ends a Live Activity and archives its lifecycle. Supports segmented_progress, progress, metrics, stats, alert, timer, and value activity types. For segmented_progress activities, you can send the latest number_of_steps here if the workflow changed after start. Use secondary_action for a second button on alert, progress, segmented_progress, and value Live Activities. Ending a Live Activity that already ended returns 200 with ignored: true and sends nothing to devices, so retries are safe. :param live_activity_end_request: (required) :type live_activity_end_request: LiveActivityEndRequest @@ -136,7 +136,7 @@ def end_live_activity_with_http_info( ) -> ApiResponse[LiveActivityEndResponse]: """End a Live Activity (legacy manual lifecycle) - Legacy manual lifecycle endpoint. For new integrations, use DELETE /live-activity/stream/{stream_key} to end a managed Live Activity stream. This endpoint remains supported for existing integrations and advanced lifecycle control. Ends a Live Activity and archives its lifecycle. Supports segmented_progress, progress, metrics, stats, alert, timer, and value activity types. For segmented_progress activities, you can send the latest number_of_steps here if the workflow changed after start. Use secondary_action for a second button on alert, progress, segmented_progress, and value Live Activities. + Legacy manual lifecycle endpoint. For new integrations, use DELETE /live-activity/stream/{stream_key} to end a managed Live Activity stream. This endpoint remains supported for existing integrations and advanced lifecycle control. Ends a Live Activity and archives its lifecycle. Supports segmented_progress, progress, metrics, stats, alert, timer, and value activity types. For segmented_progress activities, you can send the latest number_of_steps here if the workflow changed after start. Use secondary_action for a second button on alert, progress, segmented_progress, and value Live Activities. Ending a Live Activity that already ended returns 200 with ignored: true and sends nothing to devices, so retries are safe. :param live_activity_end_request: (required) :type live_activity_end_request: LiveActivityEndRequest @@ -205,7 +205,7 @@ def end_live_activity_without_preload_content( ) -> RESTResponseType: """End a Live Activity (legacy manual lifecycle) - Legacy manual lifecycle endpoint. For new integrations, use DELETE /live-activity/stream/{stream_key} to end a managed Live Activity stream. This endpoint remains supported for existing integrations and advanced lifecycle control. Ends a Live Activity and archives its lifecycle. Supports segmented_progress, progress, metrics, stats, alert, timer, and value activity types. For segmented_progress activities, you can send the latest number_of_steps here if the workflow changed after start. Use secondary_action for a second button on alert, progress, segmented_progress, and value Live Activities. + Legacy manual lifecycle endpoint. For new integrations, use DELETE /live-activity/stream/{stream_key} to end a managed Live Activity stream. This endpoint remains supported for existing integrations and advanced lifecycle control. Ends a Live Activity and archives its lifecycle. Supports segmented_progress, progress, metrics, stats, alert, timer, and value activity types. For segmented_progress activities, you can send the latest number_of_steps here if the workflow changed after start. Use secondary_action for a second button on alert, progress, segmented_progress, and value Live Activities. Ending a Live Activity that already ended returns 200 with ignored: true and sends nothing to devices, so retries are safe. :param live_activity_end_request: (required) :type live_activity_end_request: LiveActivityEndRequest diff --git a/activitysmith_openapi/api/push_notifications_api.py b/activitysmith_openapi/api/push_notifications_api.py index 192d2e7..8a36095 100644 --- a/activitysmith_openapi/api/push_notifications_api.py +++ b/activitysmith_openapi/api/push_notifications_api.py @@ -18,6 +18,7 @@ from pydantic import Field from typing_extensions import Annotated +from activitysmith_openapi.models.push_notification_dismiss_response import PushNotificationDismissResponse from activitysmith_openapi.models.push_notification_replace_request import PushNotificationReplaceRequest from activitysmith_openapi.models.push_notification_replace_response import PushNotificationReplaceResponse from activitysmith_openapi.models.push_notification_request import PushNotificationRequest @@ -41,6 +42,280 @@ def __init__(self, api_client=None) -> None: self.api_client = api_client + @validate_call + def dismiss_push_notification( + self, + notification_id: Annotated[str, Field(min_length=1, strict=True, description="The `notification_id` returned when the Push Notification was sent.")], + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> PushNotificationDismissResponse: + """Dismiss a push notification + + Clears a Push Notification you already sent from the Lock Screen and Notification Center on every device it was sent to, using the `notification_id` from the send response. Notification history keeps it. Devices clear the notification in the background, which can take a moment or wait until the ActivitySmith app next opens. A successful response means the dismissal was recorded, not that every device has cleared it yet. Devices running an ActivitySmith app version before 1.17.0 show a silent notification titled \"Push Notification dismissed\" in its place until the user clears it. Calling this again for the same notification returns the same response and sends nothing. A dismissed notification cannot be replaced. + + :param notification_id: The `notification_id` returned when the Push Notification was sent. (required) + :type notification_id: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._dismiss_push_notification_serialize( + notification_id=notification_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "PushNotificationDismissResponse", + '402': "BillingBlockedError", + '403': "ForbiddenError", + '404': "NotFoundError", + '409': "NotFoundError", + '429': "SendPushNotification429Response", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def dismiss_push_notification_with_http_info( + self, + notification_id: Annotated[str, Field(min_length=1, strict=True, description="The `notification_id` returned when the Push Notification was sent.")], + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[PushNotificationDismissResponse]: + """Dismiss a push notification + + Clears a Push Notification you already sent from the Lock Screen and Notification Center on every device it was sent to, using the `notification_id` from the send response. Notification history keeps it. Devices clear the notification in the background, which can take a moment or wait until the ActivitySmith app next opens. A successful response means the dismissal was recorded, not that every device has cleared it yet. Devices running an ActivitySmith app version before 1.17.0 show a silent notification titled \"Push Notification dismissed\" in its place until the user clears it. Calling this again for the same notification returns the same response and sends nothing. A dismissed notification cannot be replaced. + + :param notification_id: The `notification_id` returned when the Push Notification was sent. (required) + :type notification_id: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._dismiss_push_notification_serialize( + notification_id=notification_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "PushNotificationDismissResponse", + '402': "BillingBlockedError", + '403': "ForbiddenError", + '404': "NotFoundError", + '409': "NotFoundError", + '429': "SendPushNotification429Response", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def dismiss_push_notification_without_preload_content( + self, + notification_id: Annotated[str, Field(min_length=1, strict=True, description="The `notification_id` returned when the Push Notification was sent.")], + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Dismiss a push notification + + Clears a Push Notification you already sent from the Lock Screen and Notification Center on every device it was sent to, using the `notification_id` from the send response. Notification history keeps it. Devices clear the notification in the background, which can take a moment or wait until the ActivitySmith app next opens. A successful response means the dismissal was recorded, not that every device has cleared it yet. Devices running an ActivitySmith app version before 1.17.0 show a silent notification titled \"Push Notification dismissed\" in its place until the user clears it. Calling this again for the same notification returns the same response and sends nothing. A dismissed notification cannot be replaced. + + :param notification_id: The `notification_id` returned when the Push Notification was sent. (required) + :type notification_id: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._dismiss_push_notification_serialize( + notification_id=notification_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "PushNotificationDismissResponse", + '402': "BillingBlockedError", + '403': "ForbiddenError", + '404': "NotFoundError", + '409': "NotFoundError", + '429': "SendPushNotification429Response", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _dismiss_push_notification_serialize( + self, + notification_id, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[str, Union[str, bytes]] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if notification_id is not None: + _path_params['notification_id'] = notification_id + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + 'apiKeyAuth' + ] + + return self.api_client.param_serialize( + method='POST', + resource_path='/push-notification/{notification_id}/dismiss', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + @validate_call def replace_push_notification( self, diff --git a/activitysmith_openapi/docs/AccountDevice.md b/activitysmith_openapi/docs/AccountDevice.md new file mode 100644 index 0000000..7f81013 --- /dev/null +++ b/activitysmith_openapi/docs/AccountDevice.md @@ -0,0 +1,40 @@ +# AccountDevice + +An iPhone or iPad paired to the account, one entry per device and owner. + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**user_email** | **str** | Email of the account member who paired the device. | +**device_id** | **str** | Device ID. Use it to assign the device to Channels. | +**device_type** | **str** | Device platform, such as ios. iPhones and iPads both report ios; use system_name to tell them apart. | +**is_active** | **bool** | True when the device can receive Push Notifications or Live Activities. | +**token_status** | **Dict[str, bool]** | Whether each delivery token is active, keyed by token type (push, start_live_activity). | +**app_version** | **str** | ActivitySmith app version on the device. | +**device_name** | **str** | Device name set on the device. | +**system_name** | **str** | Operating system name, such as iOS or iPadOS. | +**system_version** | **str** | Operating system version. | +**created_at** | **datetime** | When the device was first paired. | +**updated_at** | **datetime** | When the device last updated its pairing. | + +## Example + +```python +from activitysmith_openapi.models.account_device import AccountDevice + +# TODO update the JSON string below +json = "{}" +# create an instance of AccountDevice from a JSON string +account_device_instance = AccountDevice.from_json(json) +# print the JSON string representation of the object +print(AccountDevice.to_json()) + +# convert the object into a dict +account_device_dict = account_device_instance.to_dict() +# create an instance of AccountDevice from a dict +account_device_from_dict = AccountDevice.from_dict(account_device_dict) +``` +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/activitysmith_openapi/docs/AccountDeviceListResponse.md b/activitysmith_openapi/docs/AccountDeviceListResponse.md new file mode 100644 index 0000000..49a5dd2 --- /dev/null +++ b/activitysmith_openapi/docs/AccountDeviceListResponse.md @@ -0,0 +1,30 @@ +# AccountDeviceListResponse + + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**devices** | [**List[AccountDevice]**](AccountDevice.md) | | +**meta** | [**AccountDeviceListResponseMeta**](AccountDeviceListResponseMeta.md) | | + +## Example + +```python +from activitysmith_openapi.models.account_device_list_response import AccountDeviceListResponse + +# TODO update the JSON string below +json = "{}" +# create an instance of AccountDeviceListResponse from a JSON string +account_device_list_response_instance = AccountDeviceListResponse.from_json(json) +# print the JSON string representation of the object +print(AccountDeviceListResponse.to_json()) + +# convert the object into a dict +account_device_list_response_dict = account_device_list_response_instance.to_dict() +# create an instance of AccountDeviceListResponse from a dict +account_device_list_response_from_dict = AccountDeviceListResponse.from_dict(account_device_list_response_dict) +``` +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/activitysmith_openapi/docs/AccountDeviceListResponseMeta.md b/activitysmith_openapi/docs/AccountDeviceListResponseMeta.md new file mode 100644 index 0000000..38ed9dd --- /dev/null +++ b/activitysmith_openapi/docs/AccountDeviceListResponseMeta.md @@ -0,0 +1,34 @@ +# AccountDeviceListResponseMeta + + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**total** | **int** | Devices matching the filter. | +**limit** | **int** | | +**offset** | **int** | | +**has_more** | **bool** | | +**next_offset** | **int** | Offset for the next page, or null on the last page. | +**include_inactive** | **bool** | | + +## Example + +```python +from activitysmith_openapi.models.account_device_list_response_meta import AccountDeviceListResponseMeta + +# TODO update the JSON string below +json = "{}" +# create an instance of AccountDeviceListResponseMeta from a JSON string +account_device_list_response_meta_instance = AccountDeviceListResponseMeta.from_json(json) +# print the JSON string representation of the object +print(AccountDeviceListResponseMeta.to_json()) + +# convert the object into a dict +account_device_list_response_meta_dict = account_device_list_response_meta_instance.to_dict() +# create an instance of AccountDeviceListResponseMeta from a dict +account_device_list_response_meta_from_dict = AccountDeviceListResponseMeta.from_dict(account_device_list_response_meta_dict) +``` +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/activitysmith_openapi/docs/AppIconBadgesApi.md b/activitysmith_openapi/docs/AppIconBadgesApi.md index 8b10987..d302da9 100644 --- a/activitysmith_openapi/docs/AppIconBadgesApi.md +++ b/activitysmith_openapi/docs/AppIconBadgesApi.md @@ -82,13 +82,13 @@ Name | Type | Description | Notes | Status code | Description | Response headers | |-------------|-------------|------------------| -**200** | App Icon Badge updated | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
| -**400** | Bad request | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
| +**200** | App Icon Badge updated | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
| +**400** | Bad request | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
| **402** | Billing access required | - | -**403** | Forbidden | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
| -**422** | No matching devices found, or a targeted device needs to reconnect | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
| -**429** | Rate limit exceeded | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
* Retry-After - Seconds to wait before retrying after a request-rate 429. Live Activity capacity errors are separate and require freeing device capacity; they do not provide a timed retry guarantee.
| -**502** | App Icon Badge could not be updated | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
| +**403** | Forbidden | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
| +**422** | No matching devices found, or a targeted device needs to reconnect | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
| +**429** | Rate limit exceeded | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
* Retry-After - Seconds to wait before retrying after a request-rate 429. Live Activity capacity errors are separate and require freeing device capacity; they do not provide a timed retry guarantee.
| +**502** | App Icon Badge could not be updated | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
| [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) diff --git a/activitysmith_openapi/docs/DevicesApi.md b/activitysmith_openapi/docs/DevicesApi.md new file mode 100644 index 0000000..1b188f2 --- /dev/null +++ b/activitysmith_openapi/docs/DevicesApi.md @@ -0,0 +1,93 @@ +# activitysmith_openapi.DevicesApi + +All URIs are relative to *https://activitysmith.com/api* + +Method | HTTP request | Description +------------- | ------------- | ------------- +[**list_account_devices**](DevicesApi.md#list_account_devices) | **GET** /account/devices | List paired devices + + +# **list_account_devices** +> AccountDeviceListResponse list_account_devices(limit=limit, offset=offset, include_inactive=include_inactive) + +List paired devices + +Lists the iPhones and iPads paired to the account, active devices first. Use it to check that a device is paired before you send, or to find device IDs for Channels. An empty list means no device is paired yet: install the ActivitySmith app from the App Store and sign in. Channel-scoped API keys cannot list devices. + +### Example + +* Bearer (API Key) Authentication (apiKeyAuth): + +```python +import activitysmith_openapi +from activitysmith_openapi.models.account_device_list_response import AccountDeviceListResponse +from activitysmith_openapi.rest import ApiException +from pprint import pprint + +# Defining the host is optional and defaults to https://activitysmith.com/api +# See configuration.py for a list of all supported configuration parameters. +configuration = activitysmith_openapi.Configuration( + host = "https://activitysmith.com/api" +) + +# The client must configure the authentication and authorization parameters +# in accordance with the API server security policy. +# Examples for each auth method are provided below, use the example that +# satisfies your auth use case. + +# Configure Bearer authorization (API Key): apiKeyAuth +configuration = activitysmith_openapi.Configuration( + access_token = os.environ["BEARER_TOKEN"] +) + +# Enter a context with an instance of the API client +with activitysmith_openapi.ApiClient(configuration) as api_client: + # Create an instance of the API class + api_instance = activitysmith_openapi.DevicesApi(api_client) + limit = 100 # int | Maximum devices to return, 1 to 100. Defaults to 100. (optional) (default to 100) + offset = 0 # int | Devices to skip. Use meta.next_offset from the previous page. (optional) (default to 0) + include_inactive = False # bool | Include devices that can no longer receive deliveries, such as unpaired phones. (optional) (default to False) + + try: + # List paired devices + api_response = api_instance.list_account_devices(limit=limit, offset=offset, include_inactive=include_inactive) + print("The response of DevicesApi->list_account_devices:\n") + pprint(api_response) + except Exception as e: + print("Exception when calling DevicesApi->list_account_devices: %s\n" % e) +``` + + + +### Parameters + + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **limit** | **int**| Maximum devices to return, 1 to 100. Defaults to 100. | [optional] [default to 100] + **offset** | **int**| Devices to skip. Use meta.next_offset from the previous page. | [optional] [default to 0] + **include_inactive** | **bool**| Include devices that can no longer receive deliveries, such as unpaired phones. | [optional] [default to False] + +### Return type + +[**AccountDeviceListResponse**](AccountDeviceListResponse.md) + +### Authorization + +[apiKeyAuth](../README.md#apiKeyAuth) + +### HTTP request headers + + - **Content-Type**: Not defined + - **Accept**: application/json + +### HTTP response details + +| Status code | Description | Response headers | +|-------------|-------------|------------------| +**200** | Paired devices | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
| +**403** | The API key is limited to Channels | - | +**429** | Rate limit exceeded | - | + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + diff --git a/activitysmith_openapi/docs/LiveActivitiesApi.md b/activitysmith_openapi/docs/LiveActivitiesApi.md index 6cc0b7f..32004df 100644 --- a/activitysmith_openapi/docs/LiveActivitiesApi.md +++ b/activitysmith_openapi/docs/LiveActivitiesApi.md @@ -16,7 +16,7 @@ Method | HTTP request | Description End a Live Activity (legacy manual lifecycle) -Legacy manual lifecycle endpoint. For new integrations, use DELETE /live-activity/stream/{stream_key} to end a managed Live Activity stream. This endpoint remains supported for existing integrations and advanced lifecycle control. Ends a Live Activity and archives its lifecycle. Supports segmented_progress, progress, metrics, stats, alert, timer, and value activity types. For segmented_progress activities, you can send the latest number_of_steps here if the workflow changed after start. Use secondary_action for a second button on alert, progress, segmented_progress, and value Live Activities. +Legacy manual lifecycle endpoint. For new integrations, use DELETE /live-activity/stream/{stream_key} to end a managed Live Activity stream. This endpoint remains supported for existing integrations and advanced lifecycle control. Ends a Live Activity and archives its lifecycle. Supports segmented_progress, progress, metrics, stats, alert, timer, and value activity types. For segmented_progress activities, you can send the latest number_of_steps here if the workflow changed after start. Use secondary_action for a second button on alert, progress, segmented_progress, and value Live Activities. Ending a Live Activity that already ended returns 200 with ignored: true and sends nothing to devices, so retries are safe. ### Example @@ -86,9 +86,9 @@ Name | Type | Description | Notes | Status code | Description | Response headers | |-------------|-------------|------------------| -**200** | Live Activity ended | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
| -**403** | Forbidden (activity not owned by this API key account) | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
| -**429** | Rate limit exceeded | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
* Retry-After - Seconds to wait before retrying after a request-rate 429. Live Activity capacity errors are separate and require freeing device capacity; they do not provide a timed retry guarantee.
| +**200** | Live Activity ended | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
| +**403** | Forbidden (activity not owned by this API key account) | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
| +**429** | Rate limit exceeded | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
* Retry-After - Seconds to wait before retrying after a request-rate 429. Live Activity capacity errors are separate and require freeing device capacity; they do not provide a timed retry guarantee.
| [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) @@ -169,10 +169,10 @@ Name | Type | Description | Notes | Status code | Description | Response headers | |-------------|-------------|------------------| -**200** | Managed stream ended | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
| -**400** | Bad request (invalid stream_key or action) | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
| -**404** | Managed stream not found | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
| -**429** | Rate limit exceeded | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
* Retry-After - Seconds to wait before retrying after a request-rate 429. Live Activity capacity errors are separate and require freeing device capacity; they do not provide a timed retry guarantee.
| +**200** | Managed stream ended | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
| +**400** | Bad request (invalid stream_key or action) | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
| +**404** | Managed stream not found | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
| +**429** | Rate limit exceeded | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
* Retry-After - Seconds to wait before retrying after a request-rate 429. Live Activity capacity errors are separate and require freeing device capacity; they do not provide a timed retry guarantee.
| [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) @@ -253,12 +253,12 @@ Name | Type | Description | Notes | Status code | Description | Response headers | |-------------|-------------|------------------| -**200** | Stream reconciled | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
| -**400** | Bad request (invalid stream_key, payload, action, or channel targeting input) | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
| +**200** | Stream reconciled | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
| +**400** | Bad request (invalid stream_key, payload, action, or channel targeting input) | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
| **402** | Trial expired, trial allowance exhausted, or paid usage cap reached | - | -**403** | Forbidden (API key scope or channel assignment violation) | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
| -**422** | No paired devices on the account, or no devices matched the effective channel target | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
| -**429** | Rate limit exceeded | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
* Retry-After - Seconds to wait before retrying after a request-rate 429. Live Activity capacity errors are separate and require freeing device capacity; they do not provide a timed retry guarantee.
| +**403** | Forbidden (API key scope or channel assignment violation) | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
| +**422** | No paired devices on the account, or no devices matched the effective channel target | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
| +**429** | Rate limit exceeded | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
* Retry-After - Seconds to wait before retrying after a request-rate 429. Live Activity capacity errors are separate and require freeing device capacity; they do not provide a timed retry guarantee.
| [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) @@ -337,12 +337,12 @@ Name | Type | Description | Notes | Status code | Description | Response headers | |-------------|-------------|------------------| -**200** | Live Activity started | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
| -**400** | Bad request (invalid payload or channel targeting input) | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
| +**200** | Live Activity started | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
| +**400** | Bad request (invalid payload or channel targeting input) | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
| **402** | Billing access required | - | -**403** | Forbidden (API key scope or channel assignment violation) | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
| -**422** | No paired devices on the account, or no devices matched the effective channel target | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
| -**429** | Rate limit exceeded | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
* Retry-After - Seconds to wait before retrying after a request-rate 429. Live Activity capacity errors are separate and require freeing device capacity; they do not provide a timed retry guarantee.
| +**403** | Forbidden (API key scope or channel assignment violation) | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
| +**422** | No paired devices on the account, or no devices matched the effective channel target | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
| +**429** | Rate limit exceeded | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
* Retry-After - Seconds to wait before retrying after a request-rate 429. Live Activity capacity errors are separate and require freeing device capacity; they do not provide a timed retry guarantee.
| [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) @@ -421,9 +421,9 @@ Name | Type | Description | Notes | Status code | Description | Response headers | |-------------|-------------|------------------| -**200** | Live Activity updated (or queued) | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
| -**403** | Forbidden (activity not owned by this API key account) | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
| -**429** | Rate limit exceeded | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
* Retry-After - Seconds to wait before retrying after a request-rate 429. Live Activity capacity errors are separate and require freeing device capacity; they do not provide a timed retry guarantee.
| +**200** | Live Activity updated (or queued) | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
| +**403** | Forbidden (activity not owned by this API key account) | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
| +**429** | Rate limit exceeded | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
* Retry-After - Seconds to wait before retrying after a request-rate 429. Live Activity capacity errors are separate and require freeing device capacity; they do not provide a timed retry guarantee.
| [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) diff --git a/activitysmith_openapi/docs/MetricsApi.md b/activitysmith_openapi/docs/MetricsApi.md index 930b6df..a76b437 100644 --- a/activitysmith_openapi/docs/MetricsApi.md +++ b/activitysmith_openapi/docs/MetricsApi.md @@ -85,11 +85,11 @@ Name | Type | Description | Notes | Status code | Description | Response headers | |-------------|-------------|------------------| -**200** | Metric value updated | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
| -**400** | Bad request (invalid key or value) | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
| -**404** | Metric deleted or not found | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
| -**409** | Metric limit reached | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
| -**429** | Rate limit exceeded | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
* Retry-After - Seconds to wait before retrying after a request-rate 429. Live Activity capacity errors are separate and require freeing device capacity; they do not provide a timed retry guarantee.
| +**200** | Metric value updated | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
| +**400** | Bad request (invalid key or value) | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
| +**404** | Metric deleted or not found | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
| +**409** | Metric limit reached | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
| +**429** | Rate limit exceeded | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
* Retry-After - Seconds to wait before retrying after a request-rate 429. Live Activity capacity errors are separate and require freeing device capacity; they do not provide a timed retry guarantee.
| [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) @@ -170,11 +170,11 @@ Name | Type | Description | Notes | Status code | Description | Response headers | |-------------|-------------|------------------| -**200** | Metric updated | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
| -**201** | Metric created | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
| -**400** | Bad request (invalid key or definition) | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
| -**409** | Metric limit reached | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
| -**429** | Rate limit exceeded | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
* Retry-After - Seconds to wait before retrying after a request-rate 429. Live Activity capacity errors are separate and require freeing device capacity; they do not provide a timed retry guarantee.
| +**200** | Metric updated | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
| +**201** | Metric created | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
| +**400** | Bad request (invalid key or definition) | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
| +**409** | Metric limit reached | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
| +**429** | Rate limit exceeded | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
* Retry-After - Seconds to wait before retrying after a request-rate 429. Live Activity capacity errors are separate and require freeing device capacity; they do not provide a timed retry guarantee.
| [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) diff --git a/activitysmith_openapi/docs/PushNotificationDismissResponse.md b/activitysmith_openapi/docs/PushNotificationDismissResponse.md new file mode 100644 index 0000000..6adfab5 --- /dev/null +++ b/activitysmith_openapi/docs/PushNotificationDismissResponse.md @@ -0,0 +1,32 @@ +# PushNotificationDismissResponse + +Dismissal result. Devices clear the notification after this response, so it does not confirm that any device has cleared it. + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**success** | **bool** | True when the dismissal is recorded. | +**notification_id** | **str** | ID of the dismissed Push Notification. | +**dismissed_at** | **datetime** | When the notification was first dismissed. Repeat calls return the same time. | + +## Example + +```python +from activitysmith_openapi.models.push_notification_dismiss_response import PushNotificationDismissResponse + +# TODO update the JSON string below +json = "{}" +# create an instance of PushNotificationDismissResponse from a JSON string +push_notification_dismiss_response_instance = PushNotificationDismissResponse.from_json(json) +# print the JSON string representation of the object +print(PushNotificationDismissResponse.to_json()) + +# convert the object into a dict +push_notification_dismiss_response_dict = push_notification_dismiss_response_instance.to_dict() +# create an instance of PushNotificationDismissResponse from a dict +push_notification_dismiss_response_from_dict = PushNotificationDismissResponse.from_dict(push_notification_dismiss_response_dict) +``` +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/activitysmith_openapi/docs/PushNotificationsApi.md b/activitysmith_openapi/docs/PushNotificationsApi.md index b1452ec..5c481cf 100644 --- a/activitysmith_openapi/docs/PushNotificationsApi.md +++ b/activitysmith_openapi/docs/PushNotificationsApi.md @@ -4,10 +4,94 @@ All URIs are relative to *https://activitysmith.com/api* Method | HTTP request | Description ------------- | ------------- | ------------- +[**dismiss_push_notification**](PushNotificationsApi.md#dismiss_push_notification) | **POST** /push-notification/{notification_id}/dismiss | Dismiss a push notification [**replace_push_notification**](PushNotificationsApi.md#replace_push_notification) | **PUT** /push-notification/{notification_id} | Replace a push notification [**send_push_notification**](PushNotificationsApi.md#send_push_notification) | **POST** /push-notification | Send a push notification +# **dismiss_push_notification** +> PushNotificationDismissResponse dismiss_push_notification(notification_id) + +Dismiss a push notification + +Clears a Push Notification you already sent from the Lock Screen and Notification Center on every device it was sent to, using the `notification_id` from the send response. Notification history keeps it. Devices clear the notification in the background, which can take a moment or wait until the ActivitySmith app next opens. A successful response means the dismissal was recorded, not that every device has cleared it yet. Devices running an ActivitySmith app version before 1.17.0 show a silent notification titled \"Push Notification dismissed\" in its place until the user clears it. Calling this again for the same notification returns the same response and sends nothing. A dismissed notification cannot be replaced. + +### Example + +* Bearer (API Key) Authentication (apiKeyAuth): + +```python +import activitysmith_openapi +from activitysmith_openapi.models.push_notification_dismiss_response import PushNotificationDismissResponse +from activitysmith_openapi.rest import ApiException +from pprint import pprint + +# Defining the host is optional and defaults to https://activitysmith.com/api +# See configuration.py for a list of all supported configuration parameters. +configuration = activitysmith_openapi.Configuration( + host = "https://activitysmith.com/api" +) + +# The client must configure the authentication and authorization parameters +# in accordance with the API server security policy. +# Examples for each auth method are provided below, use the example that +# satisfies your auth use case. + +# Configure Bearer authorization (API Key): apiKeyAuth +configuration = activitysmith_openapi.Configuration( + access_token = os.environ["BEARER_TOKEN"] +) + +# Enter a context with an instance of the API client +with activitysmith_openapi.ApiClient(configuration) as api_client: + # Create an instance of the API class + api_instance = activitysmith_openapi.PushNotificationsApi(api_client) + notification_id = 'notification_id_example' # str | The `notification_id` returned when the Push Notification was sent. + + try: + # Dismiss a push notification + api_response = api_instance.dismiss_push_notification(notification_id) + print("The response of PushNotificationsApi->dismiss_push_notification:\n") + pprint(api_response) + except Exception as e: + print("Exception when calling PushNotificationsApi->dismiss_push_notification: %s\n" % e) +``` + + + +### Parameters + + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **notification_id** | **str**| The `notification_id` returned when the Push Notification was sent. | + +### Return type + +[**PushNotificationDismissResponse**](PushNotificationDismissResponse.md) + +### Authorization + +[apiKeyAuth](../README.md#apiKeyAuth) + +### HTTP request headers + + - **Content-Type**: Not defined + - **Accept**: application/json + +### HTTP response details + +| Status code | Description | Response headers | +|-------------|-------------|------------------| +**200** | Push notification dismissal recorded | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
| +**402** | Billing access required | - | +**403** | Forbidden (API key scope or channel assignment violation) | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
| +**404** | Push notification not found | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
| +**409** | Push notification was sent before dismissal support | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
| +**429** | Rate limit exceeded | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
* Retry-After - Seconds to wait before retrying after a request-rate 429. Live Activity capacity errors are separate and require freeing device capacity; they do not provide a timed retry guarantee.
| + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + # **replace_push_notification** > PushNotificationReplaceResponse replace_push_notification(notification_id, push_notification_replace_request) @@ -85,14 +169,14 @@ Name | Type | Description | Notes | Status code | Description | Response headers | |-------------|-------------|------------------| -**200** | Push notification replaced | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
| -**400** | Bad request (invalid payload or channel targeting input) | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
| +**200** | Push notification replaced | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
| +**400** | Bad request (invalid payload or channel targeting input) | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
| **402** | Billing access required | - | -**403** | Forbidden (API key scope or channel assignment violation) | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
| -**404** | Push notification not found | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
| -**409** | Push notification was sent before replacement support | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
| -**422** | No recipients of the original Push Notification are still available | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
| -**429** | Rate limit exceeded | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
* Retry-After - Seconds to wait before retrying after a request-rate 429. Live Activity capacity errors are separate and require freeing device capacity; they do not provide a timed retry guarantee.
| +**403** | Forbidden (API key scope or channel assignment violation) | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
| +**404** | Push notification not found | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
| +**409** | Push notification cannot be replaced (sent before replacement support, or dismissed) | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
| +**422** | No recipients of the original Push Notification are still available | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
| +**429** | Rate limit exceeded | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
* Retry-After - Seconds to wait before retrying after a request-rate 429. Live Activity capacity errors are separate and require freeing device capacity; they do not provide a timed retry guarantee.
| [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) @@ -171,12 +255,12 @@ Name | Type | Description | Notes | Status code | Description | Response headers | |-------------|-------------|------------------| -**200** | Push notification sent | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
| -**400** | Bad request (invalid payload or channel targeting input) | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
| +**200** | Push notification sent | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
| +**400** | Bad request (invalid payload or channel targeting input) | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
| **402** | Billing access required | - | -**403** | Forbidden (API key scope or channel assignment violation) | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
| -**422** | No paired devices on the account, or no devices matched the effective channel target | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
| -**429** | Rate limit exceeded | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Each feature has an independent IP limit of 600 requests per 60 seconds. Independent account limits per 60 seconds are: Push Notifications 60, badges 60, Live Activities 300, and metric updates 300.
* Retry-After - Seconds to wait before retrying after a request-rate 429. Live Activity capacity errors are separate and require freeing device capacity; they do not provide a timed retry guarantee.
| +**403** | Forbidden (API key scope or channel assignment violation) | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
| +**422** | No paired devices on the account, or no devices matched the effective channel target | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
| +**429** | Rate limit exceeded | * RateLimit - Current request quotas using IETF draft-8 structured fields. Each named policy includes r (remaining requests) and t (seconds until reset). Multiple policies may apply.
* RateLimit-Policy - Each named policy includes q (request quota) and w (window in seconds). Listing devices has an IP limit of 600 requests and an account limit of 60 requests per 60 seconds.
* Retry-After - Seconds to wait before retrying after a request-rate 429. Live Activity capacity errors are separate and require freeing device capacity; they do not provide a timed retry guarantee.
| [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) diff --git a/activitysmith_openapi/models/__init__.py b/activitysmith_openapi/models/__init__.py index 7cbeb2a..8557384 100644 --- a/activitysmith_openapi/models/__init__.py +++ b/activitysmith_openapi/models/__init__.py @@ -14,6 +14,9 @@ # import models into model package +from activitysmith_openapi.models.account_device import AccountDevice +from activitysmith_openapi.models.account_device_list_response import AccountDeviceListResponse +from activitysmith_openapi.models.account_device_list_response_meta import AccountDeviceListResponseMeta from activitysmith_openapi.models.activity_metric import ActivityMetric from activitysmith_openapi.models.activity_metric_value import ActivityMetricValue from activitysmith_openapi.models.alert_payload import AlertPayload @@ -59,6 +62,7 @@ from activitysmith_openapi.models.push_interruption_level import PushInterruptionLevel from activitysmith_openapi.models.push_notification_action import PushNotificationAction from activitysmith_openapi.models.push_notification_action_type import PushNotificationActionType +from activitysmith_openapi.models.push_notification_dismiss_response import PushNotificationDismissResponse from activitysmith_openapi.models.push_notification_replace_request import PushNotificationReplaceRequest from activitysmith_openapi.models.push_notification_replace_response import PushNotificationReplaceResponse from activitysmith_openapi.models.push_notification_request import PushNotificationRequest diff --git a/activitysmith_openapi/models/account_device.py b/activitysmith_openapi/models/account_device.py new file mode 100644 index 0000000..8fa971f --- /dev/null +++ b/activitysmith_openapi/models/account_device.py @@ -0,0 +1,143 @@ +# coding: utf-8 + +""" + ActivitySmith API + + Send push notifications and Live Activities to your own devices via a single API key. + + The version of the OpenAPI document: 1.0.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from datetime import datetime +from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self + +class AccountDevice(BaseModel): + """ + An iPhone or iPad paired to the account, one entry per device and owner. + """ # noqa: E501 + user_email: StrictStr = Field(description="Email of the account member who paired the device.") + device_id: StrictStr = Field(description="Device ID. Use it to assign the device to Channels.") + device_type: Optional[StrictStr] = Field(description="Device platform, such as ios. iPhones and iPads both report ios; use system_name to tell them apart.") + is_active: StrictBool = Field(description="True when the device can receive Push Notifications or Live Activities.") + token_status: Dict[str, StrictBool] = Field(description="Whether each delivery token is active, keyed by token type (push, start_live_activity).") + app_version: Optional[StrictStr] = Field(description="ActivitySmith app version on the device.") + device_name: Optional[StrictStr] = Field(description="Device name set on the device.") + system_name: Optional[StrictStr] = Field(description="Operating system name, such as iOS or iPadOS.") + system_version: Optional[StrictStr] = Field(description="Operating system version.") + created_at: Optional[datetime] = Field(description="When the device was first paired.") + updated_at: Optional[datetime] = Field(description="When the device last updated its pairing.") + __properties: ClassVar[List[str]] = ["user_email", "device_id", "device_type", "is_active", "token_status", "app_version", "device_name", "system_name", "system_version", "created_at", "updated_at"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of AccountDevice from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # set to None if device_type (nullable) is None + # and model_fields_set contains the field + if self.device_type is None and "device_type" in self.model_fields_set: + _dict['device_type'] = None + + # set to None if app_version (nullable) is None + # and model_fields_set contains the field + if self.app_version is None and "app_version" in self.model_fields_set: + _dict['app_version'] = None + + # set to None if device_name (nullable) is None + # and model_fields_set contains the field + if self.device_name is None and "device_name" in self.model_fields_set: + _dict['device_name'] = None + + # set to None if system_name (nullable) is None + # and model_fields_set contains the field + if self.system_name is None and "system_name" in self.model_fields_set: + _dict['system_name'] = None + + # set to None if system_version (nullable) is None + # and model_fields_set contains the field + if self.system_version is None and "system_version" in self.model_fields_set: + _dict['system_version'] = None + + # set to None if created_at (nullable) is None + # and model_fields_set contains the field + if self.created_at is None and "created_at" in self.model_fields_set: + _dict['created_at'] = None + + # set to None if updated_at (nullable) is None + # and model_fields_set contains the field + if self.updated_at is None and "updated_at" in self.model_fields_set: + _dict['updated_at'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of AccountDevice from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "user_email": obj.get("user_email"), + "device_id": obj.get("device_id"), + "device_type": obj.get("device_type"), + "is_active": obj.get("is_active"), + "token_status": obj.get("token_status"), + "app_version": obj.get("app_version"), + "device_name": obj.get("device_name"), + "system_name": obj.get("system_name"), + "system_version": obj.get("system_version"), + "created_at": obj.get("created_at"), + "updated_at": obj.get("updated_at") + }) + return _obj + + diff --git a/activitysmith_openapi/models/account_device_list_response.py b/activitysmith_openapi/models/account_device_list_response.py new file mode 100644 index 0000000..0974244 --- /dev/null +++ b/activitysmith_openapi/models/account_device_list_response.py @@ -0,0 +1,101 @@ +# coding: utf-8 + +""" + ActivitySmith API + + Send push notifications and Live Activities to your own devices via a single API key. + + The version of the OpenAPI document: 1.0.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict +from typing import Any, ClassVar, Dict, List +from activitysmith_openapi.models.account_device import AccountDevice +from activitysmith_openapi.models.account_device_list_response_meta import AccountDeviceListResponseMeta +from typing import Optional, Set +from typing_extensions import Self + +class AccountDeviceListResponse(BaseModel): + """ + AccountDeviceListResponse + """ # noqa: E501 + devices: List[AccountDevice] + meta: AccountDeviceListResponseMeta + __properties: ClassVar[List[str]] = ["devices", "meta"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of AccountDeviceListResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in devices (list) + _items = [] + if self.devices: + for _item in self.devices: + if _item: + _items.append(_item.to_dict()) + _dict['devices'] = _items + # override the default output from pydantic by calling `to_dict()` of meta + if self.meta: + _dict['meta'] = self.meta.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of AccountDeviceListResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "devices": [AccountDevice.from_dict(_item) for _item in obj["devices"]] if obj.get("devices") is not None else None, + "meta": AccountDeviceListResponseMeta.from_dict(obj["meta"]) if obj.get("meta") is not None else None + }) + return _obj + + diff --git a/activitysmith_openapi/models/account_device_list_response_meta.py b/activitysmith_openapi/models/account_device_list_response_meta.py new file mode 100644 index 0000000..43525ee --- /dev/null +++ b/activitysmith_openapi/models/account_device_list_response_meta.py @@ -0,0 +1,102 @@ +# coding: utf-8 + +""" + ActivitySmith API + + Send push notifications and Live Activities to your own devices via a single API key. + + The version of the OpenAPI document: 1.0.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictInt +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self + +class AccountDeviceListResponseMeta(BaseModel): + """ + AccountDeviceListResponseMeta + """ # noqa: E501 + total: StrictInt = Field(description="Devices matching the filter.") + limit: StrictInt + offset: StrictInt + has_more: StrictBool + next_offset: Optional[StrictInt] = Field(description="Offset for the next page, or null on the last page.") + include_inactive: StrictBool + __properties: ClassVar[List[str]] = ["total", "limit", "offset", "has_more", "next_offset", "include_inactive"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of AccountDeviceListResponseMeta from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # set to None if next_offset (nullable) is None + # and model_fields_set contains the field + if self.next_offset is None and "next_offset" in self.model_fields_set: + _dict['next_offset'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of AccountDeviceListResponseMeta from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "total": obj.get("total"), + "limit": obj.get("limit"), + "offset": obj.get("offset"), + "has_more": obj.get("has_more"), + "next_offset": obj.get("next_offset"), + "include_inactive": obj.get("include_inactive") + }) + return _obj + + diff --git a/activitysmith_openapi/models/push_notification_dismiss_response.py b/activitysmith_openapi/models/push_notification_dismiss_response.py new file mode 100644 index 0000000..7576350 --- /dev/null +++ b/activitysmith_openapi/models/push_notification_dismiss_response.py @@ -0,0 +1,92 @@ +# coding: utf-8 + +""" + ActivitySmith API + + Send push notifications and Live Activities to your own devices via a single API key. + + The version of the OpenAPI document: 1.0.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from datetime import datetime +from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictStr +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self + +class PushNotificationDismissResponse(BaseModel): + """ + Dismissal result. Devices clear the notification after this response, so it does not confirm that any device has cleared it. + """ # noqa: E501 + success: StrictBool = Field(description="True when the dismissal is recorded.") + notification_id: StrictStr = Field(description="ID of the dismissed Push Notification.") + dismissed_at: datetime = Field(description="When the notification was first dismissed. Repeat calls return the same time.") + __properties: ClassVar[List[str]] = ["success", "notification_id", "dismissed_at"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of PushNotificationDismissResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of PushNotificationDismissResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "success": obj.get("success"), + "notification_id": obj.get("notification_id"), + "dismissed_at": obj.get("dismissed_at") + }) + return _obj + + diff --git a/activitysmith_openapi/openapi-source.json b/activitysmith_openapi/openapi-source.json index 498433c..6f55ecd 100644 --- a/activitysmith_openapi/openapi-source.json +++ b/activitysmith_openapi/openapi-source.json @@ -1,6 +1,6 @@ { "repository": "ActivitySmithHQ/activitysmith-backend", - "commit": "7bf9c3d88459fe3f122810979a45da0a1e6fd2d6", + "commit": "278d980633d4b1fc735ca96948fdd8ff8fd27642", "path": "openapi.json", - "sha256": "6987f90b106e28a0ab8058f43309e7a9f045c7c54d27ce90bbdd5966c3f99f7a" + "sha256": "0dbbba13bf497eceea4de0759943481a6e085cdf9a9a5445a60cf2b27457de40" } diff --git a/activitysmith_openapi/test/test_account_device.py b/activitysmith_openapi/test/test_account_device.py new file mode 100644 index 0000000..ffa892d --- /dev/null +++ b/activitysmith_openapi/test/test_account_device.py @@ -0,0 +1,76 @@ +# coding: utf-8 + +""" + ActivitySmith API + + Send push notifications and Live Activities to your own devices via a single API key. + + The version of the OpenAPI document: 1.0.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest + +from activitysmith_openapi.models.account_device import AccountDevice + +class TestAccountDevice(unittest.TestCase): + """AccountDevice unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional) -> AccountDevice: + """Test AccountDevice + include_optional is a boolean, when False only required + params are included, when True both required and + optional params are included """ + # uncomment below to create an instance of `AccountDevice` + """ + model = AccountDevice() + if include_optional: + return AccountDevice( + user_email = '', + device_id = '', + device_type = '', + is_active = True, + token_status = { + 'key' : True + }, + app_version = '', + device_name = '', + system_name = '', + system_version = '', + created_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), + updated_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f') + ) + else: + return AccountDevice( + user_email = '', + device_id = '', + device_type = '', + is_active = True, + token_status = { + 'key' : True + }, + app_version = '', + device_name = '', + system_name = '', + system_version = '', + created_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), + updated_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), + ) + """ + + def testAccountDevice(self): + """Test AccountDevice""" + # inst_req_only = self.make_instance(include_optional=False) + # inst_req_and_optional = self.make_instance(include_optional=True) + +if __name__ == '__main__': + unittest.main() diff --git a/activitysmith_openapi/test/test_account_device_list_response.py b/activitysmith_openapi/test/test_account_device_list_response.py new file mode 100644 index 0000000..dcc70ac --- /dev/null +++ b/activitysmith_openapi/test/test_account_device_list_response.py @@ -0,0 +1,96 @@ +# coding: utf-8 + +""" + ActivitySmith API + + Send push notifications and Live Activities to your own devices via a single API key. + + The version of the OpenAPI document: 1.0.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest + +from activitysmith_openapi.models.account_device_list_response import AccountDeviceListResponse + +class TestAccountDeviceListResponse(unittest.TestCase): + """AccountDeviceListResponse unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional) -> AccountDeviceListResponse: + """Test AccountDeviceListResponse + include_optional is a boolean, when False only required + params are included, when True both required and + optional params are included """ + # uncomment below to create an instance of `AccountDeviceListResponse` + """ + model = AccountDeviceListResponse() + if include_optional: + return AccountDeviceListResponse( + devices = [ + activitysmith_openapi.models.account_device.AccountDevice( + user_email = '', + device_id = '', + device_type = '', + is_active = True, + token_status = { + 'key' : True + }, + app_version = '', + device_name = '', + system_name = '', + system_version = '', + created_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), + updated_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), ) + ], + meta = activitysmith_openapi.models.account_device_list_response_meta.AccountDeviceListResponse_meta( + total = 56, + limit = 56, + offset = 56, + has_more = True, + next_offset = 56, + include_inactive = True, ) + ) + else: + return AccountDeviceListResponse( + devices = [ + activitysmith_openapi.models.account_device.AccountDevice( + user_email = '', + device_id = '', + device_type = '', + is_active = True, + token_status = { + 'key' : True + }, + app_version = '', + device_name = '', + system_name = '', + system_version = '', + created_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), + updated_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), ) + ], + meta = activitysmith_openapi.models.account_device_list_response_meta.AccountDeviceListResponse_meta( + total = 56, + limit = 56, + offset = 56, + has_more = True, + next_offset = 56, + include_inactive = True, ), + ) + """ + + def testAccountDeviceListResponse(self): + """Test AccountDeviceListResponse""" + # inst_req_only = self.make_instance(include_optional=False) + # inst_req_and_optional = self.make_instance(include_optional=True) + +if __name__ == '__main__': + unittest.main() diff --git a/activitysmith_openapi/test/test_account_device_list_response_meta.py b/activitysmith_openapi/test/test_account_device_list_response_meta.py new file mode 100644 index 0000000..db3858e --- /dev/null +++ b/activitysmith_openapi/test/test_account_device_list_response_meta.py @@ -0,0 +1,62 @@ +# coding: utf-8 + +""" + ActivitySmith API + + Send push notifications and Live Activities to your own devices via a single API key. + + The version of the OpenAPI document: 1.0.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest + +from activitysmith_openapi.models.account_device_list_response_meta import AccountDeviceListResponseMeta + +class TestAccountDeviceListResponseMeta(unittest.TestCase): + """AccountDeviceListResponseMeta unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional) -> AccountDeviceListResponseMeta: + """Test AccountDeviceListResponseMeta + include_optional is a boolean, when False only required + params are included, when True both required and + optional params are included """ + # uncomment below to create an instance of `AccountDeviceListResponseMeta` + """ + model = AccountDeviceListResponseMeta() + if include_optional: + return AccountDeviceListResponseMeta( + total = 56, + limit = 56, + offset = 56, + has_more = True, + next_offset = 56, + include_inactive = True + ) + else: + return AccountDeviceListResponseMeta( + total = 56, + limit = 56, + offset = 56, + has_more = True, + next_offset = 56, + include_inactive = True, + ) + """ + + def testAccountDeviceListResponseMeta(self): + """Test AccountDeviceListResponseMeta""" + # inst_req_only = self.make_instance(include_optional=False) + # inst_req_and_optional = self.make_instance(include_optional=True) + +if __name__ == '__main__': + unittest.main() diff --git a/activitysmith_openapi/test/test_devices_api.py b/activitysmith_openapi/test/test_devices_api.py new file mode 100644 index 0000000..d6b0025 --- /dev/null +++ b/activitysmith_openapi/test/test_devices_api.py @@ -0,0 +1,38 @@ +# coding: utf-8 + +""" + ActivitySmith API + + Send push notifications and Live Activities to your own devices via a single API key. + + The version of the OpenAPI document: 1.0.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest + +from activitysmith_openapi.api.devices_api import DevicesApi + + +class TestDevicesApi(unittest.TestCase): + """DevicesApi unit test stubs""" + + def setUp(self) -> None: + self.api = DevicesApi() + + def tearDown(self) -> None: + pass + + def test_list_account_devices(self) -> None: + """Test case for list_account_devices + + List paired devices + """ + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/activitysmith_openapi/test/test_push_notification_dismiss_response.py b/activitysmith_openapi/test/test_push_notification_dismiss_response.py new file mode 100644 index 0000000..e7a4340 --- /dev/null +++ b/activitysmith_openapi/test/test_push_notification_dismiss_response.py @@ -0,0 +1,56 @@ +# coding: utf-8 + +""" + ActivitySmith API + + Send push notifications and Live Activities to your own devices via a single API key. + + The version of the OpenAPI document: 1.0.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest + +from activitysmith_openapi.models.push_notification_dismiss_response import PushNotificationDismissResponse + +class TestPushNotificationDismissResponse(unittest.TestCase): + """PushNotificationDismissResponse unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional) -> PushNotificationDismissResponse: + """Test PushNotificationDismissResponse + include_optional is a boolean, when False only required + params are included, when True both required and + optional params are included """ + # uncomment below to create an instance of `PushNotificationDismissResponse` + """ + model = PushNotificationDismissResponse() + if include_optional: + return PushNotificationDismissResponse( + success = True, + notification_id = '', + dismissed_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f') + ) + else: + return PushNotificationDismissResponse( + success = True, + notification_id = '', + dismissed_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), + ) + """ + + def testPushNotificationDismissResponse(self): + """Test PushNotificationDismissResponse""" + # inst_req_only = self.make_instance(include_optional=False) + # inst_req_and_optional = self.make_instance(include_optional=True) + +if __name__ == '__main__': + unittest.main() diff --git a/activitysmith_openapi/test/test_push_notifications_api.py b/activitysmith_openapi/test/test_push_notifications_api.py index dea2be8..8df1841 100644 --- a/activitysmith_openapi/test/test_push_notifications_api.py +++ b/activitysmith_openapi/test/test_push_notifications_api.py @@ -26,6 +26,13 @@ def setUp(self) -> None: def tearDown(self) -> None: pass + def test_dismiss_push_notification(self) -> None: + """Test case for dismiss_push_notification + + Dismiss a push notification + """ + pass + def test_replace_push_notification(self) -> None: """Test case for replace_push_notification From 1ffe788977920d42efec688fe896b04315242d2d Mon Sep 17 00:00:00 2001 From: bardonadam Date: Sat, 7 Nov 2026 18:14:16 +0700 Subject: [PATCH 2/2] Release 1.15.0: dismiss Push Notifications and list devices Add notifications.dismiss(notification_id) with a dismiss_push_notification alias, and a devices resource with devices.list(limit, offset, include_inactive) and a list_account_devices alias. Bump the version to 1.15.0 and add the changelog entry, which also covers metrics.create. Tests mock the HTTP layer below the generated client, so they check the real request paths, query strings, and parsed responses without network access, and run the release doc examples as written. Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 4 + activitysmith/client.py | 42 ++++++- pyproject.toml | 2 +- tests/test_resources.py | 45 +++++++ tests/test_value_serialization.py | 187 ++++++++++++++++++++++++++++++ 5 files changed, 278 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cb78d18..2ed8882 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.15.0 + +Adds Push Notification dismissal. Pass a `notification_id` to `notifications.dismiss` to clear a Push Notification you already sent from the Lock Screen and Notification Center. History keeps it. Also adds `metrics.create` to create a Lock Screen Widget metric and set its label and format, such as currency or percent, and `devices.list` to list the iPhones and iPads paired to your account. + ## 1.14.0 Adds the ability to replace a Push Notification you already sent with a new one. diff --git a/activitysmith/client.py b/activitysmith/client.py index 4efd3ec..7983960 100644 --- a/activitysmith/client.py +++ b/activitysmith/client.py @@ -11,12 +11,13 @@ from activitysmith_openapi.api.metrics_api import MetricsApi from activitysmith_openapi.api.push_notifications_api import PushNotificationsApi from activitysmith_openapi.api.app_icon_badges_api import AppIconBadgesApi +from activitysmith_openapi.api.devices_api import DevicesApi from activitysmith_openapi.models.metric_value_update_request import MetricValueUpdateRequest from .normalization import normalize_live_activity_request, normalize_metric_request -SDK_VERSION = "1.14.0" +SDK_VERSION = "1.15.0" SDK_HEADER_NAME = "X-ActivitySmith-SDK" SDK_HEADER_VALUE = f"python-v{SDK_VERSION}" @@ -480,6 +481,17 @@ def replace_push_notification( ): return self.replace(notification_id, push_notification_replace_request, **fields) + def dismiss(self, notification_id: str): + """Clear a sent Push Notification from the Lock Screen and Notification Center. + + Pass the notification_id returned by send(). History keeps the notification. + """ + return self._api.dismiss_push_notification(notification_id=notification_id) + + # Generated-style alias. + def dismiss_push_notification(self, notification_id: str): + return self.dismiss(notification_id) + class LiveActivitiesResource: TYPE_SEGMENTED_PROGRESS = "segmented_progress" @@ -870,6 +882,33 @@ def update_metric_value(self, key: str, metric_value_update_request: Any): ) +class DevicesResource: + def __init__(self, api: DevicesApi) -> None: + self._api = api + + def list( + self, + limit: int | None = None, + offset: int | None = None, + include_inactive: bool | None = None, + ): + """List the iPhones and iPads paired to the account, active devices first.""" + return self._api.list_account_devices( + limit=limit, + offset=offset, + include_inactive=include_inactive, + ) + + # Generated-style alias. + def list_account_devices( + self, + limit: int | None = None, + offset: int | None = None, + include_inactive: bool | None = None, + ): + return self.list(limit=limit, offset=offset, include_inactive=include_inactive) + + @dataclass class ActivitySmith: api_key: str @@ -887,6 +926,7 @@ def __post_init__(self) -> None: self.notifications = NotificationsResource(PushNotificationsApi(api_client)) self.live_activities = LiveActivitiesResource(LiveActivitiesApi(api_client)) self.metrics = MetricsResource(MetricsApi(api_client)) + self.devices = DevicesResource(DevicesApi(api_client)) self._app_icon_badges = AppIconBadgesApi(api_client) def badge_count(self, value: int, *, channels: Any | None = None): diff --git a/pyproject.toml b/pyproject.toml index 4061457..a5799fc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "activitysmith" -version = "1.14.0" +version = "1.15.0" description = "Official ActivitySmith Python SDK" readme = "README.md" requires-python = ">=3.9" diff --git a/tests/test_resources.py b/tests/test_resources.py index 98a9a30..e35823c 100644 --- a/tests/test_resources.py +++ b/tests/test_resources.py @@ -18,6 +18,20 @@ def replace_push_notification(self, **kwargs): self.calls.append(kwargs) return kwargs + def dismiss_push_notification(self, **kwargs): + self.calls.append(kwargs) + return kwargs + + +class FakeDevicesApi: + def __init__(self, _api_client): + self._api_client = _api_client + self.calls = [] + + def list_account_devices(self, **kwargs): + self.calls.append(kwargs) + return kwargs + class FakeLiveActivitiesApi: def __init__(self, _api_client): @@ -860,6 +874,37 @@ def test_notifications_replace_and_alias(monkeypatch): } +def test_notifications_dismiss_and_alias(monkeypatch): + monkeypatch.setattr(client_module, "PushNotificationsApi", FakePushNotificationsApi) + + client = ActivitySmith(api_key="x") + + short = client.notifications.dismiss("pn1") + legacy = client.notifications.dismiss_push_notification("pn1") + + assert short == {"notification_id": "pn1"} + assert legacy == {"notification_id": "pn1"} + assert client.notifications._api.calls == [{"notification_id": "pn1"}, {"notification_id": "pn1"}] + + +def test_devices_list_and_alias(monkeypatch): + monkeypatch.setattr(client_module, "DevicesApi", FakeDevicesApi) + + client = ActivitySmith(api_key="x") + + client.devices.list() + client.devices.list(include_inactive=True, limit=10) + client.devices.list(10, 20, True) + client.devices.list_account_devices(offset=5) + + assert client.devices._api.calls == [ + {"limit": None, "offset": None, "include_inactive": None}, + {"limit": 10, "offset": None, "include_inactive": True}, + {"limit": 10, "offset": 20, "include_inactive": True}, + {"limit": None, "offset": 5, "include_inactive": None}, + ] + + def test_notifications_replace_rejects_media_and_actions(monkeypatch): monkeypatch.setattr(client_module, "PushNotificationsApi", FakePushNotificationsApi) client = ActivitySmith(api_key="x") diff --git a/tests/test_value_serialization.py b/tests/test_value_serialization.py index cb01daa..fc108fa 100644 --- a/tests/test_value_serialization.py +++ b/tests/test_value_serialization.py @@ -1,10 +1,15 @@ +import json from copy import deepcopy +from urllib.parse import parse_qs, urlsplit import pytest from activitysmith import ActivitySmith from activitysmith.client import content_state, metric from activitysmith_openapi.api_client import ApiClient +from activitysmith_openapi.models.account_device_list_response import AccountDeviceListResponse +from activitysmith_openapi.models.push_notification_dismiss_response import PushNotificationDismissResponse +from activitysmith_openapi.rest import RESTClientObject, RESTResponse from activitysmith_openapi.models.activity_metric_value import ActivityMetricValue from activitysmith_openapi.models.metric_value_update_request_value import MetricValueUpdateRequestValue from activitysmith_openapi.models.metric_value_update_request import MetricValueUpdateRequest @@ -263,3 +268,185 @@ def capture(self, method, url, header_params=None, body=None, post_params=None, assert captured[0][2] == {"label": "MRR", "format": "currency", "currency_code": "USD"} assert captured[1][2] == {"format": "unit", "unit": "ms", "unit_spacing": "space"} assert captured[2][2] is None + + +class FakeHTTPResponse: + def __init__(self, status, body): + self.status = status + self.reason = "OK" + self.data = json.dumps(body).encode("utf-8") + self.headers = {"content-type": "application/json; charset=utf-8"} + + +DEVICE = { + "user_email": "owner@example.com", + "device_id": "dev_1", + "device_type": "ios", + "is_active": True, + "token_status": {"push": True, "start_live_activity": True}, + "app_version": "1.17.0", + "device_name": "Work iPhone", + "system_name": "iOS", + "system_version": "27.0", + "created_at": "2026-10-01T09:00:00Z", + "updated_at": "2026-11-07T09:00:00Z", +} +INACTIVE_DEVICE = dict( + DEVICE, + device_id="dev_2", + is_active=False, + token_status={"push": False, "start_live_activity": False}, + device_name="Old iPad", + system_name="iPadOS", +) + + +def _fake_api_response(method, path, query): + if method == "POST" and path == "/push-notification": + return { + "success": True, + "notification_id": "Xk3pQ8mV2nR7tL9wB4yZ", + "devices_notified": 1, + "timestamp": "2026-11-07T09:00:00Z", + } + if method == "POST" and path.startswith("/push-notification/") and path.endswith("/dismiss"): + return { + "success": True, + "notification_id": path.split("/")[2], + "dismissed_at": "2026-11-07T09:01:00Z", + } + if method == "GET" and path == "/account/devices": + include_inactive = query.get("include_inactive") == ["true"] + devices = [DEVICE, INACTIVE_DEVICE] if include_inactive else [DEVICE] + return { + "devices": devices, + "meta": { + "total": len(devices), + "limit": int(query.get("limit", ["100"])[0]), + "offset": 0, + "has_more": False, + "next_offset": None, + "include_inactive": include_inactive, + }, + } + if method == "PUT" and path.startswith("/metrics/"): + return { + "metric": { + "public_id": "met_1", + "key": path.split("/")[2], + "label": "MRR", + "format": "currency", + "currency_code": "USD", + "unit": None, + "unit_spacing": "none", + "latest_value": None, + "latest_value_at": None, + "created_at": "2026-11-07T09:00:00Z", + "updated_at": "2026-11-07T09:00:00Z", + } + } + if method == "POST" and path.startswith("/metrics/") and path.endswith("/value"): + return {"success": True} + raise AssertionError(f"unexpected request {method} {path}") + + +@pytest.fixture +def transport(monkeypatch): + """Mock the HTTP layer below the generated client, so nothing reaches the network.""" + sent = [] + + def request(self, method, url, headers=None, body=None, post_params=None, _request_timeout=None): + parsed = urlsplit(url) + path = parsed.path.split("/api", 1)[1] + query = parse_qs(parsed.query) + sent.append({"method": method, "path": path, "query": query, "raw_query": parsed.query, "body": body}) + return RESTResponse(FakeHTTPResponse(200, _fake_api_response(method, path, query))) + + monkeypatch.setattr(RESTClientObject, "request", request) + return sent + + +def test_push_dismiss_sends_post_and_returns_parsed_body(transport): + activitysmith = ActivitySmith(api_key="test") + + result = activitysmith.notifications.dismiss("Xk3pQ8mV2nR7tL9wB4yZ") + alias = activitysmith.notifications.dismiss_push_notification("Xk3pQ8mV2nR7tL9wB4yZ") + + assert [(r["method"], r["path"], r["body"]) for r in transport] == [ + ("POST", "/push-notification/Xk3pQ8mV2nR7tL9wB4yZ/dismiss", None), + ("POST", "/push-notification/Xk3pQ8mV2nR7tL9wB4yZ/dismiss", None), + ] + assert isinstance(result, PushNotificationDismissResponse) + assert result.success is True + assert result.notification_id == "Xk3pQ8mV2nR7tL9wB4yZ" + assert result.dismissed_at.isoformat() == "2026-11-07T09:01:00+00:00" + assert alias == result + + +def test_push_dismiss_rejects_empty_notification_id(transport): + activitysmith = ActivitySmith(api_key="test") + with pytest.raises(ValueError): + activitysmith.notifications.dismiss("") + assert transport == [] + + +def test_devices_list_sends_get_without_query(transport): + activitysmith = ActivitySmith(api_key="test") + + result = activitysmith.devices.list() + + assert [(r["method"], r["path"], r["raw_query"], r["body"]) for r in transport] == [ + ("GET", "/account/devices", "", None), + ] + assert isinstance(result, AccountDeviceListResponse) + assert [device.device_id for device in result.devices] == ["dev_1"] + assert result.devices[0].token_status == {"push": True, "start_live_activity": True} + assert result.meta.next_offset is None + + +def test_devices_list_sends_query_params(transport): + activitysmith = ActivitySmith(api_key="test") + + result = activitysmith.devices.list(include_inactive=True, limit=10) + activitysmith.devices.list_account_devices(limit=5, offset=10, include_inactive=False) + + assert transport[0]["method"] == "GET" + assert transport[0]["path"] == "/account/devices" + assert transport[0]["query"] == {"limit": ["10"], "include_inactive": ["true"]} + assert transport[1]["query"] == {"limit": ["5"], "offset": ["10"], "include_inactive": ["false"]} + assert [device.is_active for device in result.devices] == [True, False] + assert result.meta.include_inactive is True + + +@pytest.mark.parametrize("fields", [{"limit": 0}, {"limit": 101}, {"offset": -1}, {"include_inactive": "yes"}]) +def test_devices_list_rejects_invalid_query_before_transport(transport, fields): + activitysmith = ActivitySmith(api_key="test") + with pytest.raises(ValueError): + activitysmith.devices.list(**fields) + assert transport == [] + + +def test_release_doc_examples_run_as_written(transport, capsys): + activitysmith = ActivitySmith(api_key="test") + + sent = activitysmith.notifications.send(title="🙋 Agent needs your input", message="Approve the database migration?") + activitysmith.notifications.dismiss(sent.notification_id) + result = activitysmith.devices.list() + for device in result.devices: + print(device.device_name, device.system_name, device.is_active) + activitysmith.devices.list(include_inactive=True) + activitysmith.metrics.create("mrr", label="MRR", format="currency", currency_code="USD") + activitysmith.metrics.update("mrr", 12450) + + assert [(r["method"], r["path"], r["raw_query"]) for r in transport] == [ + ("POST", "/push-notification", ""), + ("POST", "/push-notification/Xk3pQ8mV2nR7tL9wB4yZ/dismiss", ""), + ("GET", "/account/devices", ""), + ("GET", "/account/devices", "include_inactive=true"), + ("PUT", "/metrics/mrr", ""), + ("POST", "/metrics/mrr/value", ""), + ] + assert transport[0]["body"] == {"title": "🙋 Agent needs your input", "message": "Approve the database migration?"} + assert transport[4]["body"] == {"label": "MRR", "format": "currency", "currency_code": "USD"} + assert transport[5]["body"] == {"value": 12450} + assert capsys.readouterr().out == "Work iPhone iOS True\n"