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/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
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"