archastro.platform.v1.resources.notifications
1# Copyright (c) 2026 ArchAstro Inc. All Rights Reserved. 2# This file is auto-generated by @archastro/sdk-generator. Do not edit. 3# Content hash: 2bcf17d5c7e8 4 5from __future__ import annotations 6 7from datetime import datetime 8from typing import Any, Required, TypedDict 9 10from pydantic import BaseModel, Field 11 12from ...runtime.http_client import HttpClient, SyncHttpClient 13from ...types.notifications import Notification 14 15 16class NotificationSendInput(TypedDict, total=False): 17 "Send a custom notification to a user" 18 19 data: dict[str, Any] | None 20 "Arbitrary key-value payload merged with platform-provided context (recipient, app, org, brand) when rendering the notification's display fields. Defaults to an empty object when omitted." 21 idempotency_key: str | None 22 "Optional deduplication key. A second call with the same `idempotency_key` for the same recipient returns the originally-created notification without inserting a new record. Scoped per calling app." 23 type: Required[str] 24 'Custom notification type identifier in the form `"custom:<lookup_key>"`, where `<lookup_key>` matches a `NotificationType` config declared in the calling app\'s bundle.' 25 user: Required[str] 26 "Recipient user ID (`usr_...`). Must be a member of the calling app's tenant." 27 28 29class NotificationListResponseDataItem(BaseModel): 30 archived_at: datetime | None = Field( 31 default=None, 32 description="When the recipient archived this notification. `null` if the notification has not been archived.", 33 ) 34 created_at: datetime = Field(..., description="When the notification was sent (ISO 8601).") 35 id: str = Field(..., description="Notification ID (`ntf_...`).") 36 read_at: datetime | None = Field( 37 default=None, 38 description="When the recipient marked this notification read. `null` if the notification has not been read.", 39 ) 40 rendered: dict[str, Any] = Field( 41 ..., 42 description='Type-specific render spec resolved at request time. All types include `title`, `kind`, and `actions`; custom types may add their own keys. Notifications whose type is no longer registered render with `kind: "unknown"`.', 43 ) 44 status: str = Field( 45 ..., 46 description='Current read state of the notification. One of `"unread"`, `"read"`, or `"archived"`.', 47 ) 48 type: str = Field( 49 ..., 50 description='Notification type slug, e.g. `"app_info"` for a built-in type or `"custom:deploy_complete"` for a custom type.', 51 ) 52 53 54class NotificationListResponse(BaseModel): 55 """ 56 Successful response 57 """ 58 59 after_cursor: str | None = Field( 60 default=None, 61 description="Opaque cursor to pass as `after_cursor` on the next request to fetch older notifications. `null` when this is the last page.", 62 ) 63 before_cursor: str | None = Field( 64 default=None, 65 description="Always `null` inbox pagination is forward-only and does not support fetching newer pages via cursor.", 66 ) 67 data: list[NotificationListResponseDataItem] = Field( 68 ..., description="Array of notification objects for the current page, ordered newest first." 69 ) 70 has_more: bool = Field( 71 ..., 72 description="`true` if additional (older) notifications exist beyond this page; `false` if this is the last page.", 73 ) 74 75 76class NotificationUnreadCountResponse(BaseModel): 77 """ 78 Successful response 79 """ 80 81 count: int = Field( 82 ..., 83 description='Total number of notifications with `"unread"` status belonging to the authenticated user.', 84 ) 85 86 87class AsyncNotificationResource: 88 def __init__(self, http: HttpClient): 89 self._http = http 90 91 async def list( 92 self, 93 *, 94 status: str | None = None, 95 limit: int | None = None, 96 after_cursor: str | None = None, 97 ) -> NotificationListResponse: 98 """ 99 List a user's notifications 100 Returns a cursor-paginated list of inbox notifications for the authenticated 101 user, ordered by creation time descending (newest first). All status groups 102 are included by default; pass `status` to narrow results to a specific group. 103 Each notification's `rendered` field contains type-specific display data 104 resolved at request time. Notifications whose type is no longer registered 105 in the platform are rendered with `kind: "unknown"` rather than being omitted. 106 Pagination is forward-only: supply `after_cursor` from a previous response to 107 fetch the next (older) page. The `before_cursor` field is always `null` for 108 this endpoint. Requires an app-scoped token. 109 110 Args: 111 status: Filter by notification status. One of `"all"`, `"active"`, `"unread"`, `"read"`, or `"archived"`. Defaults to `"all"` when omitted. 112 limit: Maximum number of notifications to return per page. Defaults to 20; maximum is 100. 113 after_cursor: Opaque pagination cursor from a previous response's `after_cursor` field. Omit to fetch the most recent notifications. 114 115 Returns: 116 Successful response 117 """ 118 query: dict[str, object] = {} 119 if status is not None: 120 query["status"] = status 121 if limit is not None: 122 query["limit"] = limit 123 if after_cursor is not None: 124 query["after_cursor"] = after_cursor 125 return await self._http.request( 126 "/api/v1/notifications", 127 query=query, 128 response_type=NotificationListResponse, 129 ) 130 131 async def read_all(self) -> None: 132 """ 133 Mark all notifications as read 134 Marks every `"unread"` notification belonging to the authenticated user as 135 `"read"` in a single operation. Notifications that are already `"read"` or 136 `"archived"` are not affected. 137 This call is safe to retry if there are no unread notifications, it 138 succeeds without error. Requires an app-scoped token. Returns 204 No Content 139 on success. 140 141 Returns: 142 No content 143 """ 144 await self._http.request("/api/v1/notifications/read_all", method="POST") 145 146 async def send(self, input: NotificationSendInput) -> Notification: 147 """ 148 Send a custom notification to a user 149 Delivers a custom-typed notification to one of the calling app's users. 150 Apps define notification types by declaring `NotificationType` config objects 151 in their bundle (one per `lookup_key`). Supply the type as 152 `"custom:<lookup_key>"` and provide a `data` map that is merged with 153 platform-provided context to render the notification's display fields. 154 Only app-scoped tokens may call this endpoint user tokens are rejected with 155 403. The app scope is stamped onto the notification automatically; an app 156 cannot target recipients outside its tenant. Built-in platform types such as 157 `"app_info"` and `"billing_alert"` are not accepted here. 158 Pass `idempotency_key` to deduplicate sends. If you call this endpoint twice 159 with the same `idempotency_key` for the same recipient, the second call 160 returns the original notification without creating a duplicate. The key is 161 scoped to the calling app, so the same raw key used by different apps cannot 162 collide. 163 164 Args: 165 input: Request body. 166 input.data: Arbitrary key-value payload merged with platform-provided context (recipient, app, org, brand) when rendering the notification's display fields. Defaults to an empty object when omitted. 167 input.idempotency_key: Optional deduplication key. A second call with the same `idempotency_key` for the same recipient returns the originally-created notification without inserting a new record. Scoped per calling app. 168 input.type: Custom notification type identifier in the form `"custom:<lookup_key>"`, where `<lookup_key>` matches a `NotificationType` config declared in the calling app's bundle. 169 input.user: Recipient user ID (`usr_...`). Must be a member of the calling app's tenant. 170 171 Returns: 172 The created notification, or the existing notification when deduplicated by `idempotency_key`. 173 """ 174 return await self._http.request( 175 "/api/v1/notifications/send", 176 method="POST", 177 body=input, 178 response_type=Notification, 179 ) 180 181 async def unread_count(self) -> NotificationUnreadCountResponse: 182 """ 183 Get the unread notification count 184 Returns the total number of `"unread"` notifications for the authenticated 185 user. Useful for displaying a badge or indicator in your UI without 186 fetching the full notification list. 187 Notifications with `"read"` or `"archived"` status are not included in the 188 count. Requires an app-scoped token. 189 190 Returns: 191 Successful response 192 """ 193 return await self._http.request( 194 "/api/v1/notifications/unread_count", 195 response_type=NotificationUnreadCountResponse, 196 ) 197 198 async def archive(self, notification: str) -> None: 199 """ 200 Archive a notification 201 Moves a notification to `"archived"` status regardless of whether it is 202 currently `"unread"` or `"read"`. Archived notifications are excluded from 203 the default inbox view but remain retrievable by passing `status: "archived"` 204 to the list endpoint. 205 The authenticated user must own the notification. Passing a notification ID 206 that belongs to a different user returns a 404. If the notification is 207 already archived this call succeeds without error (idempotent). 208 Requires an app-scoped token. Returns 204 No Content on success. 209 210 Args: 211 notification: Notification ID (`ntf_...`) to archive. Must belong to the authenticated user. 212 213 Returns: 214 No content 215 """ 216 await self._http.request(f"/api/v1/notifications/{notification}/archive", method="POST") 217 218 async def read(self, notification: str) -> None: 219 """ 220 Mark a notification as read 221 Transitions a notification from `"unread"` to `"read"` status. If the 222 notification is already `"read"` or `"archived"`, the call succeeds without 223 changing its status (idempotent). 224 The authenticated user must own the notification. Passing a notification ID 225 that belongs to a different user returns a 404. Requires an app-scoped token. 226 Returns 204 No Content on success. 227 228 Args: 229 notification: Notification ID (`ntf_...`) to mark as read. Must belong to the authenticated user. 230 231 Returns: 232 No content 233 """ 234 await self._http.request(f"/api/v1/notifications/{notification}/read", method="POST") 235 236 async def unarchive(self, notification: str) -> None: 237 """ 238 Unarchive a notification 239 Restores an `"archived"` notification to its previous active status: 240 `"read"` if the notification had been read before archiving, or `"unread"` 241 otherwise. The notification will appear again in the default inbox view. 242 The authenticated user must own the notification. Passing a notification ID 243 that belongs to a different user returns a 404. If the notification is not 244 currently archived this call succeeds without changing its status (idempotent). 245 Requires an app-scoped token. Returns 204 No Content on success. 246 247 Args: 248 notification: Notification ID (`ntf_...`) to unarchive. Must belong to the authenticated user. 249 250 Returns: 251 No content 252 """ 253 await self._http.request(f"/api/v1/notifications/{notification}/unarchive", method="POST") 254 255 256class NotificationResource: 257 def __init__(self, http: SyncHttpClient): 258 self._http = http 259 260 def list( 261 self, 262 *, 263 status: str | None = None, 264 limit: int | None = None, 265 after_cursor: str | None = None, 266 ) -> NotificationListResponse: 267 """ 268 List a user's notifications 269 Returns a cursor-paginated list of inbox notifications for the authenticated 270 user, ordered by creation time descending (newest first). All status groups 271 are included by default; pass `status` to narrow results to a specific group. 272 Each notification's `rendered` field contains type-specific display data 273 resolved at request time. Notifications whose type is no longer registered 274 in the platform are rendered with `kind: "unknown"` rather than being omitted. 275 Pagination is forward-only: supply `after_cursor` from a previous response to 276 fetch the next (older) page. The `before_cursor` field is always `null` for 277 this endpoint. Requires an app-scoped token. 278 279 Args: 280 status: Filter by notification status. One of `"all"`, `"active"`, `"unread"`, `"read"`, or `"archived"`. Defaults to `"all"` when omitted. 281 limit: Maximum number of notifications to return per page. Defaults to 20; maximum is 100. 282 after_cursor: Opaque pagination cursor from a previous response's `after_cursor` field. Omit to fetch the most recent notifications. 283 284 Returns: 285 Successful response 286 """ 287 query: dict[str, object] = {} 288 if status is not None: 289 query["status"] = status 290 if limit is not None: 291 query["limit"] = limit 292 if after_cursor is not None: 293 query["after_cursor"] = after_cursor 294 return self._http.request( 295 "/api/v1/notifications", 296 query=query, 297 response_type=NotificationListResponse, 298 ) 299 300 def read_all(self) -> None: 301 """ 302 Mark all notifications as read 303 Marks every `"unread"` notification belonging to the authenticated user as 304 `"read"` in a single operation. Notifications that are already `"read"` or 305 `"archived"` are not affected. 306 This call is safe to retry if there are no unread notifications, it 307 succeeds without error. Requires an app-scoped token. Returns 204 No Content 308 on success. 309 310 Returns: 311 No content 312 """ 313 self._http.request("/api/v1/notifications/read_all", method="POST") 314 315 def send(self, input: NotificationSendInput) -> Notification: 316 """ 317 Send a custom notification to a user 318 Delivers a custom-typed notification to one of the calling app's users. 319 Apps define notification types by declaring `NotificationType` config objects 320 in their bundle (one per `lookup_key`). Supply the type as 321 `"custom:<lookup_key>"` and provide a `data` map that is merged with 322 platform-provided context to render the notification's display fields. 323 Only app-scoped tokens may call this endpoint user tokens are rejected with 324 403. The app scope is stamped onto the notification automatically; an app 325 cannot target recipients outside its tenant. Built-in platform types such as 326 `"app_info"` and `"billing_alert"` are not accepted here. 327 Pass `idempotency_key` to deduplicate sends. If you call this endpoint twice 328 with the same `idempotency_key` for the same recipient, the second call 329 returns the original notification without creating a duplicate. The key is 330 scoped to the calling app, so the same raw key used by different apps cannot 331 collide. 332 333 Args: 334 input: Request body. 335 input.data: Arbitrary key-value payload merged with platform-provided context (recipient, app, org, brand) when rendering the notification's display fields. Defaults to an empty object when omitted. 336 input.idempotency_key: Optional deduplication key. A second call with the same `idempotency_key` for the same recipient returns the originally-created notification without inserting a new record. Scoped per calling app. 337 input.type: Custom notification type identifier in the form `"custom:<lookup_key>"`, where `<lookup_key>` matches a `NotificationType` config declared in the calling app's bundle. 338 input.user: Recipient user ID (`usr_...`). Must be a member of the calling app's tenant. 339 340 Returns: 341 The created notification, or the existing notification when deduplicated by `idempotency_key`. 342 """ 343 return self._http.request( 344 "/api/v1/notifications/send", 345 method="POST", 346 body=input, 347 response_type=Notification, 348 ) 349 350 def unread_count(self) -> NotificationUnreadCountResponse: 351 """ 352 Get the unread notification count 353 Returns the total number of `"unread"` notifications for the authenticated 354 user. Useful for displaying a badge or indicator in your UI without 355 fetching the full notification list. 356 Notifications with `"read"` or `"archived"` status are not included in the 357 count. Requires an app-scoped token. 358 359 Returns: 360 Successful response 361 """ 362 return self._http.request( 363 "/api/v1/notifications/unread_count", 364 response_type=NotificationUnreadCountResponse, 365 ) 366 367 def archive(self, notification: str) -> None: 368 """ 369 Archive a notification 370 Moves a notification to `"archived"` status regardless of whether it is 371 currently `"unread"` or `"read"`. Archived notifications are excluded from 372 the default inbox view but remain retrievable by passing `status: "archived"` 373 to the list endpoint. 374 The authenticated user must own the notification. Passing a notification ID 375 that belongs to a different user returns a 404. If the notification is 376 already archived this call succeeds without error (idempotent). 377 Requires an app-scoped token. Returns 204 No Content on success. 378 379 Args: 380 notification: Notification ID (`ntf_...`) to archive. Must belong to the authenticated user. 381 382 Returns: 383 No content 384 """ 385 self._http.request(f"/api/v1/notifications/{notification}/archive", method="POST") 386 387 def read(self, notification: str) -> None: 388 """ 389 Mark a notification as read 390 Transitions a notification from `"unread"` to `"read"` status. If the 391 notification is already `"read"` or `"archived"`, the call succeeds without 392 changing its status (idempotent). 393 The authenticated user must own the notification. Passing a notification ID 394 that belongs to a different user returns a 404. Requires an app-scoped token. 395 Returns 204 No Content on success. 396 397 Args: 398 notification: Notification ID (`ntf_...`) to mark as read. Must belong to the authenticated user. 399 400 Returns: 401 No content 402 """ 403 self._http.request(f"/api/v1/notifications/{notification}/read", method="POST") 404 405 def unarchive(self, notification: str) -> None: 406 """ 407 Unarchive a notification 408 Restores an `"archived"` notification to its previous active status: 409 `"read"` if the notification had been read before archiving, or `"unread"` 410 otherwise. The notification will appear again in the default inbox view. 411 The authenticated user must own the notification. Passing a notification ID 412 that belongs to a different user returns a 404. If the notification is not 413 currently archived this call succeeds without changing its status (idempotent). 414 Requires an app-scoped token. Returns 204 No Content on success. 415 416 Args: 417 notification: Notification ID (`ntf_...`) to unarchive. Must belong to the authenticated user. 418 419 Returns: 420 No content 421 """ 422 self._http.request(f"/api/v1/notifications/{notification}/unarchive", method="POST")
17class NotificationSendInput(TypedDict, total=False): 18 "Send a custom notification to a user" 19 20 data: dict[str, Any] | None 21 "Arbitrary key-value payload merged with platform-provided context (recipient, app, org, brand) when rendering the notification's display fields. Defaults to an empty object when omitted." 22 idempotency_key: str | None 23 "Optional deduplication key. A second call with the same `idempotency_key` for the same recipient returns the originally-created notification without inserting a new record. Scoped per calling app." 24 type: Required[str] 25 'Custom notification type identifier in the form `"custom:<lookup_key>"`, where `<lookup_key>` matches a `NotificationType` config declared in the calling app\'s bundle.' 26 user: Required[str] 27 "Recipient user ID (`usr_...`). Must be a member of the calling app's tenant."
Send a custom notification to a user
Arbitrary key-value payload merged with platform-provided context (recipient, app, org, brand) when rendering the notification's display fields. Defaults to an empty object when omitted.
Optional deduplication key. A second call with the same idempotency_key for the same recipient returns the originally-created notification without inserting a new record. Scoped per calling app.
30class NotificationListResponseDataItem(BaseModel): 31 archived_at: datetime | None = Field( 32 default=None, 33 description="When the recipient archived this notification. `null` if the notification has not been archived.", 34 ) 35 created_at: datetime = Field(..., description="When the notification was sent (ISO 8601).") 36 id: str = Field(..., description="Notification ID (`ntf_...`).") 37 read_at: datetime | None = Field( 38 default=None, 39 description="When the recipient marked this notification read. `null` if the notification has not been read.", 40 ) 41 rendered: dict[str, Any] = Field( 42 ..., 43 description='Type-specific render spec resolved at request time. All types include `title`, `kind`, and `actions`; custom types may add their own keys. Notifications whose type is no longer registered render with `kind: "unknown"`.', 44 ) 45 status: str = Field( 46 ..., 47 description='Current read state of the notification. One of `"unread"`, `"read"`, or `"archived"`.', 48 ) 49 type: str = Field( 50 ..., 51 description='Notification type slug, e.g. `"app_info"` for a built-in type or `"custom:deploy_complete"` for a custom type.', 52 )
!!! abstract "Usage Documentation" Models
A base class for creating Pydantic models.
Attributes:
- __class_vars__: The names of the class variables defined on the model.
- __private_attributes__: Metadata about the private attributes of the model.
- __signature__: The synthesized
__init__[Signature][inspect.Signature] of the model. - __pydantic_complete__: Whether model building is completed, or if there are still undefined fields.
- __pydantic_core_schema__: The core schema of the model.
- __pydantic_custom_init__: Whether the model has a custom
__init__function. - __pydantic_decorators__: Metadata containing the decorators defined on the model.
This replaces
Model.__validators__andModel.__root_validators__from Pydantic V1. - __pydantic_generic_metadata__: A dictionary containing metadata about generic Pydantic models.
The
originandargsitems map to the [__origin__][genericalias.__origin__] and [__args__][genericalias.__args__] attributes of [generic aliases][types-genericalias], and theparameteritem maps to the__parameter__attribute of generic classes. - __pydantic_parent_namespace__: Parent namespace of the model, used for automatic rebuilding of models.
- __pydantic_post_init__: The name of the post-init method for the model, if defined.
- __pydantic_root_model__: Whether the model is a [
RootModel][pydantic.root_model.RootModel]. - __pydantic_serializer__: The
pydantic-coreSchemaSerializerused to dump instances of the model. - __pydantic_validator__: The
pydantic-coreSchemaValidatorused to validate instances of the model. - __pydantic_fields__: A dictionary of field names and their corresponding [
FieldInfo][pydantic.fields.FieldInfo] objects. - __pydantic_computed_fields__: A dictionary of computed field names and their corresponding [
ComputedFieldInfo][pydantic.fields.ComputedFieldInfo] objects. - __pydantic_extra__: A dictionary containing extra values, if [
extra][pydantic.config.ConfigDict.extra] is set to'allow'. - __pydantic_fields_set__: The names of fields explicitly set during instantiation.
- __pydantic_private__: Values of private attributes set on the model instance.
When the recipient archived this notification. null if the notification has not been archived.
When the recipient marked this notification read. null if the notification has not been read.
Type-specific render spec resolved at request time. All types include title, kind, and actions; custom types may add their own keys. Notifications whose type is no longer registered render with kind: "unknown".
55class NotificationListResponse(BaseModel): 56 """ 57 Successful response 58 """ 59 60 after_cursor: str | None = Field( 61 default=None, 62 description="Opaque cursor to pass as `after_cursor` on the next request to fetch older notifications. `null` when this is the last page.", 63 ) 64 before_cursor: str | None = Field( 65 default=None, 66 description="Always `null` inbox pagination is forward-only and does not support fetching newer pages via cursor.", 67 ) 68 data: list[NotificationListResponseDataItem] = Field( 69 ..., description="Array of notification objects for the current page, ordered newest first." 70 ) 71 has_more: bool = Field( 72 ..., 73 description="`true` if additional (older) notifications exist beyond this page; `false` if this is the last page.", 74 )
Successful response
Opaque cursor to pass as after_cursor on the next request to fetch older notifications. null when this is the last page.
Always null inbox pagination is forward-only and does not support fetching newer pages via cursor.
77class NotificationUnreadCountResponse(BaseModel): 78 """ 79 Successful response 80 """ 81 82 count: int = Field( 83 ..., 84 description='Total number of notifications with `"unread"` status belonging to the authenticated user.', 85 )
Successful response
88class AsyncNotificationResource: 89 def __init__(self, http: HttpClient): 90 self._http = http 91 92 async def list( 93 self, 94 *, 95 status: str | None = None, 96 limit: int | None = None, 97 after_cursor: str | None = None, 98 ) -> NotificationListResponse: 99 """ 100 List a user's notifications 101 Returns a cursor-paginated list of inbox notifications for the authenticated 102 user, ordered by creation time descending (newest first). All status groups 103 are included by default; pass `status` to narrow results to a specific group. 104 Each notification's `rendered` field contains type-specific display data 105 resolved at request time. Notifications whose type is no longer registered 106 in the platform are rendered with `kind: "unknown"` rather than being omitted. 107 Pagination is forward-only: supply `after_cursor` from a previous response to 108 fetch the next (older) page. The `before_cursor` field is always `null` for 109 this endpoint. Requires an app-scoped token. 110 111 Args: 112 status: Filter by notification status. One of `"all"`, `"active"`, `"unread"`, `"read"`, or `"archived"`. Defaults to `"all"` when omitted. 113 limit: Maximum number of notifications to return per page. Defaults to 20; maximum is 100. 114 after_cursor: Opaque pagination cursor from a previous response's `after_cursor` field. Omit to fetch the most recent notifications. 115 116 Returns: 117 Successful response 118 """ 119 query: dict[str, object] = {} 120 if status is not None: 121 query["status"] = status 122 if limit is not None: 123 query["limit"] = limit 124 if after_cursor is not None: 125 query["after_cursor"] = after_cursor 126 return await self._http.request( 127 "/api/v1/notifications", 128 query=query, 129 response_type=NotificationListResponse, 130 ) 131 132 async def read_all(self) -> None: 133 """ 134 Mark all notifications as read 135 Marks every `"unread"` notification belonging to the authenticated user as 136 `"read"` in a single operation. Notifications that are already `"read"` or 137 `"archived"` are not affected. 138 This call is safe to retry if there are no unread notifications, it 139 succeeds without error. Requires an app-scoped token. Returns 204 No Content 140 on success. 141 142 Returns: 143 No content 144 """ 145 await self._http.request("/api/v1/notifications/read_all", method="POST") 146 147 async def send(self, input: NotificationSendInput) -> Notification: 148 """ 149 Send a custom notification to a user 150 Delivers a custom-typed notification to one of the calling app's users. 151 Apps define notification types by declaring `NotificationType` config objects 152 in their bundle (one per `lookup_key`). Supply the type as 153 `"custom:<lookup_key>"` and provide a `data` map that is merged with 154 platform-provided context to render the notification's display fields. 155 Only app-scoped tokens may call this endpoint user tokens are rejected with 156 403. The app scope is stamped onto the notification automatically; an app 157 cannot target recipients outside its tenant. Built-in platform types such as 158 `"app_info"` and `"billing_alert"` are not accepted here. 159 Pass `idempotency_key` to deduplicate sends. If you call this endpoint twice 160 with the same `idempotency_key` for the same recipient, the second call 161 returns the original notification without creating a duplicate. The key is 162 scoped to the calling app, so the same raw key used by different apps cannot 163 collide. 164 165 Args: 166 input: Request body. 167 input.data: Arbitrary key-value payload merged with platform-provided context (recipient, app, org, brand) when rendering the notification's display fields. Defaults to an empty object when omitted. 168 input.idempotency_key: Optional deduplication key. A second call with the same `idempotency_key` for the same recipient returns the originally-created notification without inserting a new record. Scoped per calling app. 169 input.type: Custom notification type identifier in the form `"custom:<lookup_key>"`, where `<lookup_key>` matches a `NotificationType` config declared in the calling app's bundle. 170 input.user: Recipient user ID (`usr_...`). Must be a member of the calling app's tenant. 171 172 Returns: 173 The created notification, or the existing notification when deduplicated by `idempotency_key`. 174 """ 175 return await self._http.request( 176 "/api/v1/notifications/send", 177 method="POST", 178 body=input, 179 response_type=Notification, 180 ) 181 182 async def unread_count(self) -> NotificationUnreadCountResponse: 183 """ 184 Get the unread notification count 185 Returns the total number of `"unread"` notifications for the authenticated 186 user. Useful for displaying a badge or indicator in your UI without 187 fetching the full notification list. 188 Notifications with `"read"` or `"archived"` status are not included in the 189 count. Requires an app-scoped token. 190 191 Returns: 192 Successful response 193 """ 194 return await self._http.request( 195 "/api/v1/notifications/unread_count", 196 response_type=NotificationUnreadCountResponse, 197 ) 198 199 async def archive(self, notification: str) -> None: 200 """ 201 Archive a notification 202 Moves a notification to `"archived"` status regardless of whether it is 203 currently `"unread"` or `"read"`. Archived notifications are excluded from 204 the default inbox view but remain retrievable by passing `status: "archived"` 205 to the list endpoint. 206 The authenticated user must own the notification. Passing a notification ID 207 that belongs to a different user returns a 404. If the notification is 208 already archived this call succeeds without error (idempotent). 209 Requires an app-scoped token. Returns 204 No Content on success. 210 211 Args: 212 notification: Notification ID (`ntf_...`) to archive. Must belong to the authenticated user. 213 214 Returns: 215 No content 216 """ 217 await self._http.request(f"/api/v1/notifications/{notification}/archive", method="POST") 218 219 async def read(self, notification: str) -> None: 220 """ 221 Mark a notification as read 222 Transitions a notification from `"unread"` to `"read"` status. If the 223 notification is already `"read"` or `"archived"`, the call succeeds without 224 changing its status (idempotent). 225 The authenticated user must own the notification. Passing a notification ID 226 that belongs to a different user returns a 404. Requires an app-scoped token. 227 Returns 204 No Content on success. 228 229 Args: 230 notification: Notification ID (`ntf_...`) to mark as read. Must belong to the authenticated user. 231 232 Returns: 233 No content 234 """ 235 await self._http.request(f"/api/v1/notifications/{notification}/read", method="POST") 236 237 async def unarchive(self, notification: str) -> None: 238 """ 239 Unarchive a notification 240 Restores an `"archived"` notification to its previous active status: 241 `"read"` if the notification had been read before archiving, or `"unread"` 242 otherwise. The notification will appear again in the default inbox view. 243 The authenticated user must own the notification. Passing a notification ID 244 that belongs to a different user returns a 404. If the notification is not 245 currently archived this call succeeds without changing its status (idempotent). 246 Requires an app-scoped token. Returns 204 No Content on success. 247 248 Args: 249 notification: Notification ID (`ntf_...`) to unarchive. Must belong to the authenticated user. 250 251 Returns: 252 No content 253 """ 254 await self._http.request(f"/api/v1/notifications/{notification}/unarchive", method="POST")
92 async def list( 93 self, 94 *, 95 status: str | None = None, 96 limit: int | None = None, 97 after_cursor: str | None = None, 98 ) -> NotificationListResponse: 99 """ 100 List a user's notifications 101 Returns a cursor-paginated list of inbox notifications for the authenticated 102 user, ordered by creation time descending (newest first). All status groups 103 are included by default; pass `status` to narrow results to a specific group. 104 Each notification's `rendered` field contains type-specific display data 105 resolved at request time. Notifications whose type is no longer registered 106 in the platform are rendered with `kind: "unknown"` rather than being omitted. 107 Pagination is forward-only: supply `after_cursor` from a previous response to 108 fetch the next (older) page. The `before_cursor` field is always `null` for 109 this endpoint. Requires an app-scoped token. 110 111 Args: 112 status: Filter by notification status. One of `"all"`, `"active"`, `"unread"`, `"read"`, or `"archived"`. Defaults to `"all"` when omitted. 113 limit: Maximum number of notifications to return per page. Defaults to 20; maximum is 100. 114 after_cursor: Opaque pagination cursor from a previous response's `after_cursor` field. Omit to fetch the most recent notifications. 115 116 Returns: 117 Successful response 118 """ 119 query: dict[str, object] = {} 120 if status is not None: 121 query["status"] = status 122 if limit is not None: 123 query["limit"] = limit 124 if after_cursor is not None: 125 query["after_cursor"] = after_cursor 126 return await self._http.request( 127 "/api/v1/notifications", 128 query=query, 129 response_type=NotificationListResponse, 130 )
List a user's notifications
Returns a cursor-paginated list of inbox notifications for the authenticated
user, ordered by creation time descending (newest first). All status groups
are included by default; pass status to narrow results to a specific group.
Each notification's rendered field contains type-specific display data
resolved at request time. Notifications whose type is no longer registered
in the platform are rendered with kind: "unknown" rather than being omitted.
Pagination is forward-only: supply after_cursor from a previous response to
fetch the next (older) page. The before_cursor field is always null for
this endpoint. Requires an app-scoped token.
Arguments:
- status: Filter by notification status. One of
"all","active","unread","read", or"archived". Defaults to"all"when omitted. - limit: Maximum number of notifications to return per page. Defaults to 20; maximum is 100.
- after_cursor: Opaque pagination cursor from a previous response's
after_cursorfield. Omit to fetch the most recent notifications.
Returns:
Successful response
132 async def read_all(self) -> None: 133 """ 134 Mark all notifications as read 135 Marks every `"unread"` notification belonging to the authenticated user as 136 `"read"` in a single operation. Notifications that are already `"read"` or 137 `"archived"` are not affected. 138 This call is safe to retry if there are no unread notifications, it 139 succeeds without error. Requires an app-scoped token. Returns 204 No Content 140 on success. 141 142 Returns: 143 No content 144 """ 145 await self._http.request("/api/v1/notifications/read_all", method="POST")
Mark all notifications as read
Marks every "unread" notification belonging to the authenticated user as
"read" in a single operation. Notifications that are already "read" or
"archived" are not affected.
This call is safe to retry if there are no unread notifications, it
succeeds without error. Requires an app-scoped token. Returns 204 No Content
on success.
Returns:
No content
147 async def send(self, input: NotificationSendInput) -> Notification: 148 """ 149 Send a custom notification to a user 150 Delivers a custom-typed notification to one of the calling app's users. 151 Apps define notification types by declaring `NotificationType` config objects 152 in their bundle (one per `lookup_key`). Supply the type as 153 `"custom:<lookup_key>"` and provide a `data` map that is merged with 154 platform-provided context to render the notification's display fields. 155 Only app-scoped tokens may call this endpoint user tokens are rejected with 156 403. The app scope is stamped onto the notification automatically; an app 157 cannot target recipients outside its tenant. Built-in platform types such as 158 `"app_info"` and `"billing_alert"` are not accepted here. 159 Pass `idempotency_key` to deduplicate sends. If you call this endpoint twice 160 with the same `idempotency_key` for the same recipient, the second call 161 returns the original notification without creating a duplicate. The key is 162 scoped to the calling app, so the same raw key used by different apps cannot 163 collide. 164 165 Args: 166 input: Request body. 167 input.data: Arbitrary key-value payload merged with platform-provided context (recipient, app, org, brand) when rendering the notification's display fields. Defaults to an empty object when omitted. 168 input.idempotency_key: Optional deduplication key. A second call with the same `idempotency_key` for the same recipient returns the originally-created notification without inserting a new record. Scoped per calling app. 169 input.type: Custom notification type identifier in the form `"custom:<lookup_key>"`, where `<lookup_key>` matches a `NotificationType` config declared in the calling app's bundle. 170 input.user: Recipient user ID (`usr_...`). Must be a member of the calling app's tenant. 171 172 Returns: 173 The created notification, or the existing notification when deduplicated by `idempotency_key`. 174 """ 175 return await self._http.request( 176 "/api/v1/notifications/send", 177 method="POST", 178 body=input, 179 response_type=Notification, 180 )
Send a custom notification to a user
Delivers a custom-typed notification to one of the calling app's users.
Apps define notification types by declaring NotificationType config objects
in their bundle (one per lookup_key). Supply the type as
"custom:<lookup_key>" and provide a data map that is merged with
platform-provided context to render the notification's display fields.
Only app-scoped tokens may call this endpoint user tokens are rejected with
- The app scope is stamped onto the notification automatically; an app
cannot target recipients outside its tenant. Built-in platform types such as
"app_info"and"billing_alert"are not accepted here. Passidempotency_keyto deduplicate sends. If you call this endpoint twice with the sameidempotency_keyfor the same recipient, the second call returns the original notification without creating a duplicate. The key is scoped to the calling app, so the same raw key used by different apps cannot collide.
Arguments:
- input: Request body.
- input.data: Arbitrary key-value payload merged with platform-provided context (recipient, app, org, brand) when rendering the notification's display fields. Defaults to an empty object when omitted.
- input.idempotency_key: Optional deduplication key. A second call with the same
idempotency_keyfor the same recipient returns the originally-created notification without inserting a new record. Scoped per calling app. - input.type: Custom notification type identifier in the form
"custom:<lookup_key>", where<lookup_key>matches aNotificationTypeconfig declared in the calling app's bundle. - input.user: Recipient user ID (
usr_...). Must be a member of the calling app's tenant.
Returns:
The created notification, or the existing notification when deduplicated by
idempotency_key.
182 async def unread_count(self) -> NotificationUnreadCountResponse: 183 """ 184 Get the unread notification count 185 Returns the total number of `"unread"` notifications for the authenticated 186 user. Useful for displaying a badge or indicator in your UI without 187 fetching the full notification list. 188 Notifications with `"read"` or `"archived"` status are not included in the 189 count. Requires an app-scoped token. 190 191 Returns: 192 Successful response 193 """ 194 return await self._http.request( 195 "/api/v1/notifications/unread_count", 196 response_type=NotificationUnreadCountResponse, 197 )
Get the unread notification count
Returns the total number of "unread" notifications for the authenticated
user. Useful for displaying a badge or indicator in your UI without
fetching the full notification list.
Notifications with "read" or "archived" status are not included in the
count. Requires an app-scoped token.
Returns:
Successful response
199 async def archive(self, notification: str) -> None: 200 """ 201 Archive a notification 202 Moves a notification to `"archived"` status regardless of whether it is 203 currently `"unread"` or `"read"`. Archived notifications are excluded from 204 the default inbox view but remain retrievable by passing `status: "archived"` 205 to the list endpoint. 206 The authenticated user must own the notification. Passing a notification ID 207 that belongs to a different user returns a 404. If the notification is 208 already archived this call succeeds without error (idempotent). 209 Requires an app-scoped token. Returns 204 No Content on success. 210 211 Args: 212 notification: Notification ID (`ntf_...`) to archive. Must belong to the authenticated user. 213 214 Returns: 215 No content 216 """ 217 await self._http.request(f"/api/v1/notifications/{notification}/archive", method="POST")
Archive a notification
Moves a notification to "archived" status regardless of whether it is
currently "unread" or "read". Archived notifications are excluded from
the default inbox view but remain retrievable by passing status: "archived"
to the list endpoint.
The authenticated user must own the notification. Passing a notification ID
that belongs to a different user returns a 404. If the notification is
already archived this call succeeds without error (idempotent).
Requires an app-scoped token. Returns 204 No Content on success.
Arguments:
- notification: Notification ID (
ntf_...) to archive. Must belong to the authenticated user.
Returns:
No content
219 async def read(self, notification: str) -> None: 220 """ 221 Mark a notification as read 222 Transitions a notification from `"unread"` to `"read"` status. If the 223 notification is already `"read"` or `"archived"`, the call succeeds without 224 changing its status (idempotent). 225 The authenticated user must own the notification. Passing a notification ID 226 that belongs to a different user returns a 404. Requires an app-scoped token. 227 Returns 204 No Content on success. 228 229 Args: 230 notification: Notification ID (`ntf_...`) to mark as read. Must belong to the authenticated user. 231 232 Returns: 233 No content 234 """ 235 await self._http.request(f"/api/v1/notifications/{notification}/read", method="POST")
Mark a notification as read
Transitions a notification from "unread" to "read" status. If the
notification is already "read" or "archived", the call succeeds without
changing its status (idempotent).
The authenticated user must own the notification. Passing a notification ID
that belongs to a different user returns a 404. Requires an app-scoped token.
Returns 204 No Content on success.
Arguments:
- notification: Notification ID (
ntf_...) to mark as read. Must belong to the authenticated user.
Returns:
No content
237 async def unarchive(self, notification: str) -> None: 238 """ 239 Unarchive a notification 240 Restores an `"archived"` notification to its previous active status: 241 `"read"` if the notification had been read before archiving, or `"unread"` 242 otherwise. The notification will appear again in the default inbox view. 243 The authenticated user must own the notification. Passing a notification ID 244 that belongs to a different user returns a 404. If the notification is not 245 currently archived this call succeeds without changing its status (idempotent). 246 Requires an app-scoped token. Returns 204 No Content on success. 247 248 Args: 249 notification: Notification ID (`ntf_...`) to unarchive. Must belong to the authenticated user. 250 251 Returns: 252 No content 253 """ 254 await self._http.request(f"/api/v1/notifications/{notification}/unarchive", method="POST")
Unarchive a notification
Restores an "archived" notification to its previous active status:
"read" if the notification had been read before archiving, or "unread"
otherwise. The notification will appear again in the default inbox view.
The authenticated user must own the notification. Passing a notification ID
that belongs to a different user returns a 404. If the notification is not
currently archived this call succeeds without changing its status (idempotent).
Requires an app-scoped token. Returns 204 No Content on success.
Arguments:
- notification: Notification ID (
ntf_...) to unarchive. Must belong to the authenticated user.
Returns:
No content
257class NotificationResource: 258 def __init__(self, http: SyncHttpClient): 259 self._http = http 260 261 def list( 262 self, 263 *, 264 status: str | None = None, 265 limit: int | None = None, 266 after_cursor: str | None = None, 267 ) -> NotificationListResponse: 268 """ 269 List a user's notifications 270 Returns a cursor-paginated list of inbox notifications for the authenticated 271 user, ordered by creation time descending (newest first). All status groups 272 are included by default; pass `status` to narrow results to a specific group. 273 Each notification's `rendered` field contains type-specific display data 274 resolved at request time. Notifications whose type is no longer registered 275 in the platform are rendered with `kind: "unknown"` rather than being omitted. 276 Pagination is forward-only: supply `after_cursor` from a previous response to 277 fetch the next (older) page. The `before_cursor` field is always `null` for 278 this endpoint. Requires an app-scoped token. 279 280 Args: 281 status: Filter by notification status. One of `"all"`, `"active"`, `"unread"`, `"read"`, or `"archived"`. Defaults to `"all"` when omitted. 282 limit: Maximum number of notifications to return per page. Defaults to 20; maximum is 100. 283 after_cursor: Opaque pagination cursor from a previous response's `after_cursor` field. Omit to fetch the most recent notifications. 284 285 Returns: 286 Successful response 287 """ 288 query: dict[str, object] = {} 289 if status is not None: 290 query["status"] = status 291 if limit is not None: 292 query["limit"] = limit 293 if after_cursor is not None: 294 query["after_cursor"] = after_cursor 295 return self._http.request( 296 "/api/v1/notifications", 297 query=query, 298 response_type=NotificationListResponse, 299 ) 300 301 def read_all(self) -> None: 302 """ 303 Mark all notifications as read 304 Marks every `"unread"` notification belonging to the authenticated user as 305 `"read"` in a single operation. Notifications that are already `"read"` or 306 `"archived"` are not affected. 307 This call is safe to retry if there are no unread notifications, it 308 succeeds without error. Requires an app-scoped token. Returns 204 No Content 309 on success. 310 311 Returns: 312 No content 313 """ 314 self._http.request("/api/v1/notifications/read_all", method="POST") 315 316 def send(self, input: NotificationSendInput) -> Notification: 317 """ 318 Send a custom notification to a user 319 Delivers a custom-typed notification to one of the calling app's users. 320 Apps define notification types by declaring `NotificationType` config objects 321 in their bundle (one per `lookup_key`). Supply the type as 322 `"custom:<lookup_key>"` and provide a `data` map that is merged with 323 platform-provided context to render the notification's display fields. 324 Only app-scoped tokens may call this endpoint user tokens are rejected with 325 403. The app scope is stamped onto the notification automatically; an app 326 cannot target recipients outside its tenant. Built-in platform types such as 327 `"app_info"` and `"billing_alert"` are not accepted here. 328 Pass `idempotency_key` to deduplicate sends. If you call this endpoint twice 329 with the same `idempotency_key` for the same recipient, the second call 330 returns the original notification without creating a duplicate. The key is 331 scoped to the calling app, so the same raw key used by different apps cannot 332 collide. 333 334 Args: 335 input: Request body. 336 input.data: Arbitrary key-value payload merged with platform-provided context (recipient, app, org, brand) when rendering the notification's display fields. Defaults to an empty object when omitted. 337 input.idempotency_key: Optional deduplication key. A second call with the same `idempotency_key` for the same recipient returns the originally-created notification without inserting a new record. Scoped per calling app. 338 input.type: Custom notification type identifier in the form `"custom:<lookup_key>"`, where `<lookup_key>` matches a `NotificationType` config declared in the calling app's bundle. 339 input.user: Recipient user ID (`usr_...`). Must be a member of the calling app's tenant. 340 341 Returns: 342 The created notification, or the existing notification when deduplicated by `idempotency_key`. 343 """ 344 return self._http.request( 345 "/api/v1/notifications/send", 346 method="POST", 347 body=input, 348 response_type=Notification, 349 ) 350 351 def unread_count(self) -> NotificationUnreadCountResponse: 352 """ 353 Get the unread notification count 354 Returns the total number of `"unread"` notifications for the authenticated 355 user. Useful for displaying a badge or indicator in your UI without 356 fetching the full notification list. 357 Notifications with `"read"` or `"archived"` status are not included in the 358 count. Requires an app-scoped token. 359 360 Returns: 361 Successful response 362 """ 363 return self._http.request( 364 "/api/v1/notifications/unread_count", 365 response_type=NotificationUnreadCountResponse, 366 ) 367 368 def archive(self, notification: str) -> None: 369 """ 370 Archive a notification 371 Moves a notification to `"archived"` status regardless of whether it is 372 currently `"unread"` or `"read"`. Archived notifications are excluded from 373 the default inbox view but remain retrievable by passing `status: "archived"` 374 to the list endpoint. 375 The authenticated user must own the notification. Passing a notification ID 376 that belongs to a different user returns a 404. If the notification is 377 already archived this call succeeds without error (idempotent). 378 Requires an app-scoped token. Returns 204 No Content on success. 379 380 Args: 381 notification: Notification ID (`ntf_...`) to archive. Must belong to the authenticated user. 382 383 Returns: 384 No content 385 """ 386 self._http.request(f"/api/v1/notifications/{notification}/archive", method="POST") 387 388 def read(self, notification: str) -> None: 389 """ 390 Mark a notification as read 391 Transitions a notification from `"unread"` to `"read"` status. If the 392 notification is already `"read"` or `"archived"`, the call succeeds without 393 changing its status (idempotent). 394 The authenticated user must own the notification. Passing a notification ID 395 that belongs to a different user returns a 404. Requires an app-scoped token. 396 Returns 204 No Content on success. 397 398 Args: 399 notification: Notification ID (`ntf_...`) to mark as read. Must belong to the authenticated user. 400 401 Returns: 402 No content 403 """ 404 self._http.request(f"/api/v1/notifications/{notification}/read", method="POST") 405 406 def unarchive(self, notification: str) -> None: 407 """ 408 Unarchive a notification 409 Restores an `"archived"` notification to its previous active status: 410 `"read"` if the notification had been read before archiving, or `"unread"` 411 otherwise. The notification will appear again in the default inbox view. 412 The authenticated user must own the notification. Passing a notification ID 413 that belongs to a different user returns a 404. If the notification is not 414 currently archived this call succeeds without changing its status (idempotent). 415 Requires an app-scoped token. Returns 204 No Content on success. 416 417 Args: 418 notification: Notification ID (`ntf_...`) to unarchive. Must belong to the authenticated user. 419 420 Returns: 421 No content 422 """ 423 self._http.request(f"/api/v1/notifications/{notification}/unarchive", method="POST")
261 def list( 262 self, 263 *, 264 status: str | None = None, 265 limit: int | None = None, 266 after_cursor: str | None = None, 267 ) -> NotificationListResponse: 268 """ 269 List a user's notifications 270 Returns a cursor-paginated list of inbox notifications for the authenticated 271 user, ordered by creation time descending (newest first). All status groups 272 are included by default; pass `status` to narrow results to a specific group. 273 Each notification's `rendered` field contains type-specific display data 274 resolved at request time. Notifications whose type is no longer registered 275 in the platform are rendered with `kind: "unknown"` rather than being omitted. 276 Pagination is forward-only: supply `after_cursor` from a previous response to 277 fetch the next (older) page. The `before_cursor` field is always `null` for 278 this endpoint. Requires an app-scoped token. 279 280 Args: 281 status: Filter by notification status. One of `"all"`, `"active"`, `"unread"`, `"read"`, or `"archived"`. Defaults to `"all"` when omitted. 282 limit: Maximum number of notifications to return per page. Defaults to 20; maximum is 100. 283 after_cursor: Opaque pagination cursor from a previous response's `after_cursor` field. Omit to fetch the most recent notifications. 284 285 Returns: 286 Successful response 287 """ 288 query: dict[str, object] = {} 289 if status is not None: 290 query["status"] = status 291 if limit is not None: 292 query["limit"] = limit 293 if after_cursor is not None: 294 query["after_cursor"] = after_cursor 295 return self._http.request( 296 "/api/v1/notifications", 297 query=query, 298 response_type=NotificationListResponse, 299 )
List a user's notifications
Returns a cursor-paginated list of inbox notifications for the authenticated
user, ordered by creation time descending (newest first). All status groups
are included by default; pass status to narrow results to a specific group.
Each notification's rendered field contains type-specific display data
resolved at request time. Notifications whose type is no longer registered
in the platform are rendered with kind: "unknown" rather than being omitted.
Pagination is forward-only: supply after_cursor from a previous response to
fetch the next (older) page. The before_cursor field is always null for
this endpoint. Requires an app-scoped token.
Arguments:
- status: Filter by notification status. One of
"all","active","unread","read", or"archived". Defaults to"all"when omitted. - limit: Maximum number of notifications to return per page. Defaults to 20; maximum is 100.
- after_cursor: Opaque pagination cursor from a previous response's
after_cursorfield. Omit to fetch the most recent notifications.
Returns:
Successful response
301 def read_all(self) -> None: 302 """ 303 Mark all notifications as read 304 Marks every `"unread"` notification belonging to the authenticated user as 305 `"read"` in a single operation. Notifications that are already `"read"` or 306 `"archived"` are not affected. 307 This call is safe to retry if there are no unread notifications, it 308 succeeds without error. Requires an app-scoped token. Returns 204 No Content 309 on success. 310 311 Returns: 312 No content 313 """ 314 self._http.request("/api/v1/notifications/read_all", method="POST")
Mark all notifications as read
Marks every "unread" notification belonging to the authenticated user as
"read" in a single operation. Notifications that are already "read" or
"archived" are not affected.
This call is safe to retry if there are no unread notifications, it
succeeds without error. Requires an app-scoped token. Returns 204 No Content
on success.
Returns:
No content
316 def send(self, input: NotificationSendInput) -> Notification: 317 """ 318 Send a custom notification to a user 319 Delivers a custom-typed notification to one of the calling app's users. 320 Apps define notification types by declaring `NotificationType` config objects 321 in their bundle (one per `lookup_key`). Supply the type as 322 `"custom:<lookup_key>"` and provide a `data` map that is merged with 323 platform-provided context to render the notification's display fields. 324 Only app-scoped tokens may call this endpoint user tokens are rejected with 325 403. The app scope is stamped onto the notification automatically; an app 326 cannot target recipients outside its tenant. Built-in platform types such as 327 `"app_info"` and `"billing_alert"` are not accepted here. 328 Pass `idempotency_key` to deduplicate sends. If you call this endpoint twice 329 with the same `idempotency_key` for the same recipient, the second call 330 returns the original notification without creating a duplicate. The key is 331 scoped to the calling app, so the same raw key used by different apps cannot 332 collide. 333 334 Args: 335 input: Request body. 336 input.data: Arbitrary key-value payload merged with platform-provided context (recipient, app, org, brand) when rendering the notification's display fields. Defaults to an empty object when omitted. 337 input.idempotency_key: Optional deduplication key. A second call with the same `idempotency_key` for the same recipient returns the originally-created notification without inserting a new record. Scoped per calling app. 338 input.type: Custom notification type identifier in the form `"custom:<lookup_key>"`, where `<lookup_key>` matches a `NotificationType` config declared in the calling app's bundle. 339 input.user: Recipient user ID (`usr_...`). Must be a member of the calling app's tenant. 340 341 Returns: 342 The created notification, or the existing notification when deduplicated by `idempotency_key`. 343 """ 344 return self._http.request( 345 "/api/v1/notifications/send", 346 method="POST", 347 body=input, 348 response_type=Notification, 349 )
Send a custom notification to a user
Delivers a custom-typed notification to one of the calling app's users.
Apps define notification types by declaring NotificationType config objects
in their bundle (one per lookup_key). Supply the type as
"custom:<lookup_key>" and provide a data map that is merged with
platform-provided context to render the notification's display fields.
Only app-scoped tokens may call this endpoint user tokens are rejected with
- The app scope is stamped onto the notification automatically; an app
cannot target recipients outside its tenant. Built-in platform types such as
"app_info"and"billing_alert"are not accepted here. Passidempotency_keyto deduplicate sends. If you call this endpoint twice with the sameidempotency_keyfor the same recipient, the second call returns the original notification without creating a duplicate. The key is scoped to the calling app, so the same raw key used by different apps cannot collide.
Arguments:
- input: Request body.
- input.data: Arbitrary key-value payload merged with platform-provided context (recipient, app, org, brand) when rendering the notification's display fields. Defaults to an empty object when omitted.
- input.idempotency_key: Optional deduplication key. A second call with the same
idempotency_keyfor the same recipient returns the originally-created notification without inserting a new record. Scoped per calling app. - input.type: Custom notification type identifier in the form
"custom:<lookup_key>", where<lookup_key>matches aNotificationTypeconfig declared in the calling app's bundle. - input.user: Recipient user ID (
usr_...). Must be a member of the calling app's tenant.
Returns:
The created notification, or the existing notification when deduplicated by
idempotency_key.
351 def unread_count(self) -> NotificationUnreadCountResponse: 352 """ 353 Get the unread notification count 354 Returns the total number of `"unread"` notifications for the authenticated 355 user. Useful for displaying a badge or indicator in your UI without 356 fetching the full notification list. 357 Notifications with `"read"` or `"archived"` status are not included in the 358 count. Requires an app-scoped token. 359 360 Returns: 361 Successful response 362 """ 363 return self._http.request( 364 "/api/v1/notifications/unread_count", 365 response_type=NotificationUnreadCountResponse, 366 )
Get the unread notification count
Returns the total number of "unread" notifications for the authenticated
user. Useful for displaying a badge or indicator in your UI without
fetching the full notification list.
Notifications with "read" or "archived" status are not included in the
count. Requires an app-scoped token.
Returns:
Successful response
368 def archive(self, notification: str) -> None: 369 """ 370 Archive a notification 371 Moves a notification to `"archived"` status regardless of whether it is 372 currently `"unread"` or `"read"`. Archived notifications are excluded from 373 the default inbox view but remain retrievable by passing `status: "archived"` 374 to the list endpoint. 375 The authenticated user must own the notification. Passing a notification ID 376 that belongs to a different user returns a 404. If the notification is 377 already archived this call succeeds without error (idempotent). 378 Requires an app-scoped token. Returns 204 No Content on success. 379 380 Args: 381 notification: Notification ID (`ntf_...`) to archive. Must belong to the authenticated user. 382 383 Returns: 384 No content 385 """ 386 self._http.request(f"/api/v1/notifications/{notification}/archive", method="POST")
Archive a notification
Moves a notification to "archived" status regardless of whether it is
currently "unread" or "read". Archived notifications are excluded from
the default inbox view but remain retrievable by passing status: "archived"
to the list endpoint.
The authenticated user must own the notification. Passing a notification ID
that belongs to a different user returns a 404. If the notification is
already archived this call succeeds without error (idempotent).
Requires an app-scoped token. Returns 204 No Content on success.
Arguments:
- notification: Notification ID (
ntf_...) to archive. Must belong to the authenticated user.
Returns:
No content
388 def read(self, notification: str) -> None: 389 """ 390 Mark a notification as read 391 Transitions a notification from `"unread"` to `"read"` status. If the 392 notification is already `"read"` or `"archived"`, the call succeeds without 393 changing its status (idempotent). 394 The authenticated user must own the notification. Passing a notification ID 395 that belongs to a different user returns a 404. Requires an app-scoped token. 396 Returns 204 No Content on success. 397 398 Args: 399 notification: Notification ID (`ntf_...`) to mark as read. Must belong to the authenticated user. 400 401 Returns: 402 No content 403 """ 404 self._http.request(f"/api/v1/notifications/{notification}/read", method="POST")
Mark a notification as read
Transitions a notification from "unread" to "read" status. If the
notification is already "read" or "archived", the call succeeds without
changing its status (idempotent).
The authenticated user must own the notification. Passing a notification ID
that belongs to a different user returns a 404. Requires an app-scoped token.
Returns 204 No Content on success.
Arguments:
- notification: Notification ID (
ntf_...) to mark as read. Must belong to the authenticated user.
Returns:
No content
406 def unarchive(self, notification: str) -> None: 407 """ 408 Unarchive a notification 409 Restores an `"archived"` notification to its previous active status: 410 `"read"` if the notification had been read before archiving, or `"unread"` 411 otherwise. The notification will appear again in the default inbox view. 412 The authenticated user must own the notification. Passing a notification ID 413 that belongs to a different user returns a 404. If the notification is not 414 currently archived this call succeeds without changing its status (idempotent). 415 Requires an app-scoped token. Returns 204 No Content on success. 416 417 Args: 418 notification: Notification ID (`ntf_...`) to unarchive. Must belong to the authenticated user. 419 420 Returns: 421 No content 422 """ 423 self._http.request(f"/api/v1/notifications/{notification}/unarchive", method="POST")
Unarchive a notification
Restores an "archived" notification to its previous active status:
"read" if the notification had been read before archiving, or "unread"
otherwise. The notification will appear again in the default inbox view.
The authenticated user must own the notification. Passing a notification ID
that belongs to a different user returns a 404. If the notification is not
currently archived this call succeeds without changing its status (idempotent).
Requires an app-scoped token. Returns 204 No Content on success.
Arguments:
- notification: Notification ID (
ntf_...) to unarchive. Must belong to the authenticated user.
Returns:
No content