pingram-python 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. pingram/__init__.py +395 -0
  2. pingram/api/__init__.py +21 -0
  3. pingram/api/account_api.py +2198 -0
  4. pingram/api/addresses_api.py +860 -0
  5. pingram/api/components_api.py +1681 -0
  6. pingram/api/default_api.py +320 -0
  7. pingram/api/domains_api.py +849 -0
  8. pingram/api/editor_api.py +320 -0
  9. pingram/api/environments_api.py +878 -0
  10. pingram/api/health_api.py +287 -0
  11. pingram/api/insights_api.py +321 -0
  12. pingram/api/keys_api.py +849 -0
  13. pingram/api/logs_api.py +1632 -0
  14. pingram/api/members_api.py +1780 -0
  15. pingram/api/sender_api.py +892 -0
  16. pingram/api/templates_api.py +1889 -0
  17. pingram/api/types_api.py +1411 -0
  18. pingram/api/user_api.py +2534 -0
  19. pingram/api/users_api.py +936 -0
  20. pingram/api_client.py +807 -0
  21. pingram/api_response.py +21 -0
  22. pingram/client_wrapper.py +357 -0
  23. pingram/configuration.py +623 -0
  24. pingram/exceptions.py +219 -0
  25. pingram/models/__init__.py +173 -0
  26. pingram/models/account_addresses_response.py +95 -0
  27. pingram/models/account_addresses_response_addresses_inner.py +104 -0
  28. pingram/models/account_get_response.py +143 -0
  29. pingram/models/account_get_response_pending_downgrade_usage_limit.py +99 -0
  30. pingram/models/address_response.py +91 -0
  31. pingram/models/auto_join_get_response.py +89 -0
  32. pingram/models/auto_join_post_response.py +89 -0
  33. pingram/models/auto_join_request_body.py +87 -0
  34. pingram/models/bee_token_v2.py +89 -0
  35. pingram/models/billing_post_request_body.py +91 -0
  36. pingram/models/billing_post_response_body.py +149 -0
  37. pingram/models/billing_post_response_body_pending_downgrade_usage_limit.py +99 -0
  38. pingram/models/channels_enum.py +42 -0
  39. pingram/models/create_account_request_body.py +87 -0
  40. pingram/models/create_account_response.py +89 -0
  41. pingram/models/create_address_request.py +91 -0
  42. pingram/models/create_key_request.py +98 -0
  43. pingram/models/create_key_response.py +104 -0
  44. pingram/models/delete_key_response.py +87 -0
  45. pingram/models/delete_user_response.py +87 -0
  46. pingram/models/email_auth_token_post_request.py +87 -0
  47. pingram/models/email_component_patch_request.py +93 -0
  48. pingram/models/email_component_post_request.py +95 -0
  49. pingram/models/email_component_response.py +120 -0
  50. pingram/models/email_component_response_referenced_by_inner.py +92 -0
  51. pingram/models/environment.py +96 -0
  52. pingram/models/environment_create_request.py +87 -0
  53. pingram/models/environment_patch_request.py +94 -0
  54. pingram/models/get_account_metadata_response.py +91 -0
  55. pingram/models/get_account_metadata_response_user_account_metadata.py +91 -0
  56. pingram/models/get_email_components_response_inner.py +120 -0
  57. pingram/models/get_environments_response_inner.py +96 -0
  58. pingram/models/get_inapp_notifications_response.py +95 -0
  59. pingram/models/get_inapp_notifications_response_notifications_inner.py +137 -0
  60. pingram/models/get_inapp_notifications_response_notifications_inner_delivery_options.py +106 -0
  61. pingram/models/get_inapp_notifications_response_notifications_inner_delivery_options_instant.py +93 -0
  62. pingram/models/get_inapp_notifications_response_notifications_inner_delivery_options_off.py +87 -0
  63. pingram/models/get_inapp_notifications_response_notifications_inner_replies_inner.py +89 -0
  64. pingram/models/get_inapp_notifications_response_notifications_inner_template.py +136 -0
  65. pingram/models/get_inapp_notifications_response_notifications_inner_template_any_of.py +98 -0
  66. pingram/models/get_keys_response.py +95 -0
  67. pingram/models/get_keys_response_keys_inner.py +110 -0
  68. pingram/models/get_logs_response.py +97 -0
  69. pingram/models/get_logs_response_messages_inner.py +141 -0
  70. pingram/models/get_logs_response_messages_inner_attachments_inner.py +93 -0
  71. pingram/models/get_members_response_inner.py +95 -0
  72. pingram/models/get_metrics_response_inner.py +116 -0
  73. pingram/models/get_metrics_response_inner_messages_inner.py +89 -0
  74. pingram/models/get_notifications_response_inner.py +126 -0
  75. pingram/models/get_notifications_response_inner_deduplication.py +87 -0
  76. pingram/models/get_notifications_response_inner_options.py +122 -0
  77. pingram/models/get_notifications_response_inner_options_email.py +128 -0
  78. pingram/models/get_notifications_response_inner_options_email_daily.py +89 -0
  79. pingram/models/get_notifications_response_inner_options_email_monthly.py +101 -0
  80. pingram/models/get_notifications_response_inner_options_email_weekly.py +91 -0
  81. pingram/models/get_notifications_response_inner_templates_inner.py +90 -0
  82. pingram/models/get_notifications_response_inner_throttling.py +111 -0
  83. pingram/models/get_senders_response_inner.py +128 -0
  84. pingram/models/get_templates_response.py +136 -0
  85. pingram/models/get_users_response.py +99 -0
  86. pingram/models/get_users_response_users_inner.py +133 -0
  87. pingram/models/get_users_response_users_inner_email_suppression_status.py +96 -0
  88. pingram/models/get_users_response_users_inner_push_tokens_inner.py +104 -0
  89. pingram/models/get_users_response_users_inner_push_tokens_inner_device.py +97 -0
  90. pingram/models/get_users_response_users_inner_slack_token.py +140 -0
  91. pingram/models/get_users_response_users_inner_slack_token_authed_user.py +97 -0
  92. pingram/models/get_users_response_users_inner_slack_token_enterprise.py +89 -0
  93. pingram/models/get_users_response_users_inner_slack_token_incoming_webhook.py +93 -0
  94. pingram/models/get_users_response_users_inner_slack_token_response_metadata.py +97 -0
  95. pingram/models/get_users_response_users_inner_web_push_tokens_inner.py +91 -0
  96. pingram/models/get_users_response_users_inner_web_push_tokens_inner_sub.py +93 -0
  97. pingram/models/get_users_response_users_inner_web_push_tokens_inner_sub_keys.py +89 -0
  98. pingram/models/in_app_notification_patch_request.py +112 -0
  99. pingram/models/in_app_notification_unread_clear_request.py +89 -0
  100. pingram/models/inapp_unread_count_response.py +87 -0
  101. pingram/models/inbound_request_body.py +138 -0
  102. pingram/models/inbound_response_body.py +104 -0
  103. pingram/models/inbound_response_body_results_inner.py +103 -0
  104. pingram/models/ingishts_post_request.py +121 -0
  105. pingram/models/ingishts_post_request_label_options.py +87 -0
  106. pingram/models/ingishts_post_request_metric_data_queries_inner.py +103 -0
  107. pingram/models/ingishts_post_request_metric_data_queries_inner_metric_stat.py +107 -0
  108. pingram/models/ingishts_post_request_metric_data_queries_inner_metric_stat_metric.py +99 -0
  109. pingram/models/ingishts_post_request_metric_data_queries_inner_metric_stat_metric_dimensions_inner.py +89 -0
  110. pingram/models/intercom_webhook.py +106 -0
  111. pingram/models/intercom_webhook_data.py +91 -0
  112. pingram/models/intercom_webhook_data_item.py +136 -0
  113. pingram/models/intercom_webhook_data_item_any_of.py +140 -0
  114. pingram/models/intercom_webhook_data_item_any_of_contacts.py +104 -0
  115. pingram/models/intercom_webhook_data_item_any_of_contacts_contacts_inner.py +91 -0
  116. pingram/models/intercom_webhook_data_item_any_of_source.py +101 -0
  117. pingram/models/intercom_webhook_data_item_any_of_source_author.py +93 -0
  118. pingram/models/invite_post_response.py +89 -0
  119. pingram/models/log_query_post_body.py +109 -0
  120. pingram/models/logs_bulk_request.py +87 -0
  121. pingram/models/logs_get_response.py +95 -0
  122. pingram/models/logs_get_response_logs_inner.py +627 -0
  123. pingram/models/logs_query_response.py +87 -0
  124. pingram/models/logs_query_result_response.py +101 -0
  125. pingram/models/logs_retention_response.py +87 -0
  126. pingram/models/logs_tail_response.py +95 -0
  127. pingram/models/member_invite_request.py +89 -0
  128. pingram/models/member_update_request.py +87 -0
  129. pingram/models/message_response.py +87 -0
  130. pingram/models/notification.py +126 -0
  131. pingram/models/notification_create_request.py +97 -0
  132. pingram/models/notification_patch_request.py +112 -0
  133. pingram/models/post_email_test_request.py +99 -0
  134. pingram/models/post_email_test_response.py +89 -0
  135. pingram/models/post_senders_request_body.py +87 -0
  136. pingram/models/post_user_request.py +121 -0
  137. pingram/models/sender_post_body.py +166 -0
  138. pingram/models/sender_post_body_email.py +95 -0
  139. pingram/models/sender_post_body_inapp.py +91 -0
  140. pingram/models/sender_post_body_mobile_push.py +89 -0
  141. pingram/models/sender_post_body_options.py +103 -0
  142. pingram/models/sender_post_body_options_apn.py +99 -0
  143. pingram/models/sender_post_body_options_email.py +107 -0
  144. pingram/models/sender_post_body_options_email_attachments_inner.py +134 -0
  145. pingram/models/sender_post_body_options_email_attachments_inner_any_of.py +89 -0
  146. pingram/models/sender_post_body_options_email_attachments_inner_any_of1.py +91 -0
  147. pingram/models/sender_post_body_options_fcm.py +91 -0
  148. pingram/models/sender_post_body_options_fcm_android.py +103 -0
  149. pingram/models/sender_post_body_slack.py +123 -0
  150. pingram/models/sender_post_body_slack_metadata.py +99 -0
  151. pingram/models/sender_post_body_slack_metadata_entities_inner.py +99 -0
  152. pingram/models/sender_post_body_slack_metadata_entities_inner_external_ref.py +89 -0
  153. pingram/models/sender_post_body_sms.py +93 -0
  154. pingram/models/sender_post_body_sms_auto_reply.py +87 -0
  155. pingram/models/sender_post_body_to.py +133 -0
  156. pingram/models/sender_post_body_user.py +133 -0
  157. pingram/models/sender_post_body_web_push.py +93 -0
  158. pingram/models/sender_post_response.py +89 -0
  159. pingram/models/set_default_template_request.py +97 -0
  160. pingram/models/slack_interactivity_response.py +87 -0
  161. pingram/models/slack_oauth_request.py +89 -0
  162. pingram/models/success_response.py +87 -0
  163. pingram/models/supabase_configure_request.py +93 -0
  164. pingram/models/supabase_configure_response.py +89 -0
  165. pingram/models/supabase_o_auth_request.py +91 -0
  166. pingram/models/supabase_o_auth_response.py +89 -0
  167. pingram/models/supabase_projects_response.py +95 -0
  168. pingram/models/supabase_projects_response_projects_inner.py +95 -0
  169. pingram/models/supabase_status_response.py +93 -0
  170. pingram/models/template.py +98 -0
  171. pingram/models/template_patch_request.py +134 -0
  172. pingram/models/template_patch_request_any_of.py +97 -0
  173. pingram/models/template_patch_request_any_of1.py +103 -0
  174. pingram/models/template_patch_request_any_of1_batch.py +91 -0
  175. pingram/models/template_patch_request_any_of1_instant.py +91 -0
  176. pingram/models/template_post_request.py +131 -0
  177. pingram/models/template_post_request_batch.py +91 -0
  178. pingram/models/template_post_request_instant.py +91 -0
  179. pingram/models/update_address_request.py +91 -0
  180. pingram/models/user.py +133 -0
  181. pingram/models/user_suppression_delete_response.py +91 -0
  182. pingram/models/webhook_response.py +104 -0
  183. pingram/py.typed +0 -0
  184. pingram/rest.py +199 -0
  185. pingram_python-0.1.0.dist-info/METADATA +69 -0
  186. pingram_python-0.1.0.dist-info/RECORD +189 -0
  187. pingram_python-0.1.0.dist-info/WHEEL +5 -0
  188. pingram_python-0.1.0.dist-info/licenses/LICENSE +21 -0
  189. pingram_python-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,21 @@
1
+ """API response object."""
2
+
3
+ from __future__ import annotations
4
+ from typing import Optional, Generic, Mapping, TypeVar
5
+ from pydantic import Field, StrictInt, StrictBytes, BaseModel
6
+
7
+ T = TypeVar("T")
8
+
9
+ class ApiResponse(BaseModel, Generic[T]):
10
+ """
11
+ API response object
12
+ """
13
+
14
+ status_code: StrictInt = Field(description="HTTP status code")
15
+ headers: Optional[Mapping[str, str]] = Field(None, description="HTTP headers")
16
+ data: T = Field(description="Deserialized data given the data type")
17
+ raw_data: StrictBytes = Field(description="Raw data (HTTP response body)")
18
+
19
+ model_config = {
20
+ "arbitrary_types_allowed": True
21
+ }
@@ -0,0 +1,357 @@
1
+ # This file is auto-generated by tools/sdk-codegen/generate-python-wrapper.ts
2
+ # DO NOT EDIT MANUALLY - changes will be overwritten
3
+ # Edit sdks/python/templates/client_wrapper.mustache instead
4
+
5
+ from __future__ import annotations
6
+
7
+ from typing import Literal, Optional, TypedDict, Union
8
+
9
+
10
+ from .api.account_api import AccountApi
11
+
12
+ from .api.addresses_api import AddressesApi
13
+
14
+ from .api.components_api import ComponentsApi
15
+
16
+ from .api.default_api import DefaultApi
17
+
18
+ from .api.domains_api import DomainsApi
19
+
20
+ from .api.editor_api import EditorApi
21
+
22
+ from .api.environments_api import EnvironmentsApi
23
+
24
+ from .api.health_api import HealthApi
25
+
26
+ from .api.insights_api import InsightsApi
27
+
28
+ from .api.keys_api import KeysApi
29
+
30
+ from .api.logs_api import LogsApi
31
+
32
+ from .api.members_api import MembersApi
33
+
34
+ from .api.sender_api import SenderApi
35
+
36
+ from .api.templates_api import TemplatesApi
37
+
38
+ from .api.types_api import TypesApi
39
+
40
+ from .api.user_api import UserApi
41
+
42
+ from .api.users_api import UsersApi
43
+
44
+ from .api_client import ApiClient
45
+ from .configuration import Configuration
46
+ from .models.sender_post_body import SenderPostBody
47
+ from .models.sender_post_response import SenderPostResponse
48
+
49
+ PingramRegion = Literal["us", "eu", "ca"]
50
+
51
+
52
+ class PingramConfig(TypedDict, total=False):
53
+ """Configuration options for the Pingram client."""
54
+
55
+ api_key: str
56
+ region: PingramRegion
57
+ base_url: Optional[str]
58
+
59
+
60
+ _REGION_BASE_URLS: dict[PingramRegion, str] = {
61
+ "us": "https://api.pingram.io",
62
+ "eu": "https://api.eu.pingram.io",
63
+ "ca": "https://api.ca.pingram.io",
64
+ }
65
+
66
+
67
+ def get_region_base_url(region: PingramRegion = "us") -> str:
68
+ """Return the base URL for the given region."""
69
+ return _REGION_BASE_URLS[region]
70
+
71
+
72
+ class Pingram:
73
+ """
74
+ Pingram client: high-level wrapper over the generated API client.
75
+
76
+ Use as an async context manager so the HTTP client is opened and closed correctly:
77
+
78
+ async with Pingram(api_key="pingram_sk_...") as client:
79
+ await client.send(sender_post_body=body)
80
+ user = await client.user.user_get_user(account_id="...", user_id="...")
81
+ """
82
+
83
+ def __init__(
84
+ self,
85
+ config_or_api_key: Optional[Union[PingramConfig, str]] = None,
86
+ region: PingramRegion = "us",
87
+ base_url: Optional[str] = None,
88
+ *,
89
+ api_key: Optional[str] = None,
90
+ ):
91
+ """
92
+ Initialize the Pingram client.
93
+
94
+ :param config_or_api_key: Optional. Either an API key string (e.g. pingram_sk_...) or a config dict with "api_key", optional "region", optional "base_url".
95
+ :param region: Region: "us", "eu", or "ca". Default "us".
96
+ :param base_url: Override base URL (ignores region if set).
97
+ :param api_key: Optional keyword. API key (e.g. pingram_sk_...) or JWT. Use this or pass as first positional arg.
98
+ """
99
+ if api_key is not None:
100
+ config_or_api_key = api_key
101
+ if config_or_api_key is None:
102
+ raise ValueError("api_key or config must be provided")
103
+ if isinstance(config_or_api_key, dict):
104
+ api_key_val = config_or_api_key.get("api_key") or ""
105
+ region = config_or_api_key.get("region", "us")
106
+ base_url = config_or_api_key.get("base_url") or base_url
107
+ else:
108
+ api_key_val = config_or_api_key or ""
109
+ if not api_key_val:
110
+ raise ValueError("api_key must be provided")
111
+
112
+ host = base_url if base_url else get_region_base_url(region)
113
+ self._configuration = Configuration(host=host, access_token=api_key_val)
114
+ self._api_client: Optional[ApiClient] = None
115
+
116
+ self._account: Optional[AccountApi] = None
117
+
118
+ self._addresses: Optional[AddressesApi] = None
119
+
120
+ self._components: Optional[ComponentsApi] = None
121
+
122
+ self._default_api: Optional[DefaultApi] = None
123
+
124
+ self._domains: Optional[DomainsApi] = None
125
+
126
+ self._editor: Optional[EditorApi] = None
127
+
128
+ self._environments: Optional[EnvironmentsApi] = None
129
+
130
+ self._health: Optional[HealthApi] = None
131
+
132
+ self._insights: Optional[InsightsApi] = None
133
+
134
+ self._keys: Optional[KeysApi] = None
135
+
136
+ self._logs: Optional[LogsApi] = None
137
+
138
+ self._members: Optional[MembersApi] = None
139
+
140
+ self._sender: Optional[SenderApi] = None
141
+
142
+ self._templates: Optional[TemplatesApi] = None
143
+
144
+ self._types: Optional[TypesApi] = None
145
+
146
+ self._user: Optional[UserApi] = None
147
+
148
+ self._users: Optional[UsersApi] = None
149
+
150
+
151
+ async def __aenter__(self) -> Pingram:
152
+ self._api_client = ApiClient(self._configuration)
153
+ await self._api_client.__aenter__()
154
+
155
+ self._account = AccountApi(self._api_client)
156
+
157
+ self._addresses = AddressesApi(self._api_client)
158
+
159
+ self._components = ComponentsApi(self._api_client)
160
+
161
+ self._default_api = DefaultApi(self._api_client)
162
+
163
+ self._domains = DomainsApi(self._api_client)
164
+
165
+ self._editor = EditorApi(self._api_client)
166
+
167
+ self._environments = EnvironmentsApi(self._api_client)
168
+
169
+ self._health = HealthApi(self._api_client)
170
+
171
+ self._insights = InsightsApi(self._api_client)
172
+
173
+ self._keys = KeysApi(self._api_client)
174
+
175
+ self._logs = LogsApi(self._api_client)
176
+
177
+ self._members = MembersApi(self._api_client)
178
+
179
+ self._sender = SenderApi(self._api_client)
180
+
181
+ self._templates = TemplatesApi(self._api_client)
182
+
183
+ self._types = TypesApi(self._api_client)
184
+
185
+ self._user = UserApi(self._api_client)
186
+
187
+ self._users = UsersApi(self._api_client)
188
+
189
+ return self
190
+
191
+ async def __aexit__(self, exc_type, exc_val, exc_tb) -> None:
192
+ if self._api_client is not None:
193
+ await self._api_client.__aexit__(exc_type, exc_val, exc_tb)
194
+ self._api_client = None
195
+
196
+ self._account = None
197
+
198
+ self._addresses = None
199
+
200
+ self._components = None
201
+
202
+ self._default_api = None
203
+
204
+ self._domains = None
205
+
206
+ self._editor = None
207
+
208
+ self._environments = None
209
+
210
+ self._health = None
211
+
212
+ self._insights = None
213
+
214
+ self._keys = None
215
+
216
+ self._logs = None
217
+
218
+ self._members = None
219
+
220
+ self._sender = None
221
+
222
+ self._templates = None
223
+
224
+ self._types = None
225
+
226
+ self._user = None
227
+
228
+ self._users = None
229
+
230
+
231
+
232
+ @property
233
+ def account(self) -> AccountApi:
234
+ if self._account is None:
235
+ raise RuntimeError("Pingram must be used as async context manager: async with Pingram(...) as client:")
236
+ return self._account
237
+
238
+
239
+ @property
240
+ def addresses(self) -> AddressesApi:
241
+ if self._addresses is None:
242
+ raise RuntimeError("Pingram must be used as async context manager: async with Pingram(...) as client:")
243
+ return self._addresses
244
+
245
+
246
+ @property
247
+ def components(self) -> ComponentsApi:
248
+ if self._components is None:
249
+ raise RuntimeError("Pingram must be used as async context manager: async with Pingram(...) as client:")
250
+ return self._components
251
+
252
+
253
+ @property
254
+ def default_api(self) -> DefaultApi:
255
+ if self._default_api is None:
256
+ raise RuntimeError("Pingram must be used as async context manager: async with Pingram(...) as client:")
257
+ return self._default_api
258
+
259
+
260
+ @property
261
+ def domains(self) -> DomainsApi:
262
+ if self._domains is None:
263
+ raise RuntimeError("Pingram must be used as async context manager: async with Pingram(...) as client:")
264
+ return self._domains
265
+
266
+
267
+ @property
268
+ def editor(self) -> EditorApi:
269
+ if self._editor is None:
270
+ raise RuntimeError("Pingram must be used as async context manager: async with Pingram(...) as client:")
271
+ return self._editor
272
+
273
+
274
+ @property
275
+ def environments(self) -> EnvironmentsApi:
276
+ if self._environments is None:
277
+ raise RuntimeError("Pingram must be used as async context manager: async with Pingram(...) as client:")
278
+ return self._environments
279
+
280
+
281
+ @property
282
+ def health(self) -> HealthApi:
283
+ if self._health is None:
284
+ raise RuntimeError("Pingram must be used as async context manager: async with Pingram(...) as client:")
285
+ return self._health
286
+
287
+
288
+ @property
289
+ def insights(self) -> InsightsApi:
290
+ if self._insights is None:
291
+ raise RuntimeError("Pingram must be used as async context manager: async with Pingram(...) as client:")
292
+ return self._insights
293
+
294
+
295
+ @property
296
+ def keys(self) -> KeysApi:
297
+ if self._keys is None:
298
+ raise RuntimeError("Pingram must be used as async context manager: async with Pingram(...) as client:")
299
+ return self._keys
300
+
301
+
302
+ @property
303
+ def logs(self) -> LogsApi:
304
+ if self._logs is None:
305
+ raise RuntimeError("Pingram must be used as async context manager: async with Pingram(...) as client:")
306
+ return self._logs
307
+
308
+
309
+ @property
310
+ def members(self) -> MembersApi:
311
+ if self._members is None:
312
+ raise RuntimeError("Pingram must be used as async context manager: async with Pingram(...) as client:")
313
+ return self._members
314
+
315
+
316
+ @property
317
+ def sender(self) -> SenderApi:
318
+ if self._sender is None:
319
+ raise RuntimeError("Pingram must be used as async context manager: async with Pingram(...) as client:")
320
+ return self._sender
321
+
322
+
323
+ @property
324
+ def templates(self) -> TemplatesApi:
325
+ if self._templates is None:
326
+ raise RuntimeError("Pingram must be used as async context manager: async with Pingram(...) as client:")
327
+ return self._templates
328
+
329
+
330
+ @property
331
+ def types(self) -> TypesApi:
332
+ if self._types is None:
333
+ raise RuntimeError("Pingram must be used as async context manager: async with Pingram(...) as client:")
334
+ return self._types
335
+
336
+
337
+ @property
338
+ def user(self) -> UserApi:
339
+ if self._user is None:
340
+ raise RuntimeError("Pingram must be used as async context manager: async with Pingram(...) as client:")
341
+ return self._user
342
+
343
+
344
+ @property
345
+ def users(self) -> UsersApi:
346
+ if self._users is None:
347
+ raise RuntimeError("Pingram must be used as async context manager: async with Pingram(...) as client:")
348
+ return self._users
349
+
350
+
351
+
352
+ async def send(self, sender_post_body: SenderPostBody) -> SenderPostResponse:
353
+ """Send a notification. Delegates to DefaultApi.send."""
354
+ if self._default_api is None:
355
+ raise RuntimeError("Pingram must be used as async context manager: async with Pingram(...) as client:")
356
+ return await self._default_api.send(sender_post_body=sender_post_body)
357
+