airwallex-sdk 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 (39) hide show
  1. airwallex/__init__.py +74 -0
  2. airwallex/api/__init__.py +37 -0
  3. airwallex/api/account.py +107 -0
  4. airwallex/api/account_detail.py +469 -0
  5. airwallex/api/base.py +488 -0
  6. airwallex/api/beneficiary.py +156 -0
  7. airwallex/api/financial_transaction.py +123 -0
  8. airwallex/api/invoice.py +257 -0
  9. airwallex/api/issuing_authorization.py +313 -0
  10. airwallex/api/issuing_card.py +411 -0
  11. airwallex/api/issuing_cardholder.py +234 -0
  12. airwallex/api/issuing_config.py +80 -0
  13. airwallex/api/issuing_digital_wallet_token.py +249 -0
  14. airwallex/api/issuing_transaction.py +231 -0
  15. airwallex/api/issuing_transaction_dispute.py +339 -0
  16. airwallex/api/payment.py +148 -0
  17. airwallex/client.py +396 -0
  18. airwallex/exceptions.py +222 -0
  19. airwallex/models/__init__.py +69 -0
  20. airwallex/models/account.py +51 -0
  21. airwallex/models/account_detail.py +259 -0
  22. airwallex/models/base.py +121 -0
  23. airwallex/models/beneficiary.py +70 -0
  24. airwallex/models/financial_transaction.py +30 -0
  25. airwallex/models/fx.py +58 -0
  26. airwallex/models/invoice.py +102 -0
  27. airwallex/models/issuing_authorization.py +41 -0
  28. airwallex/models/issuing_card.py +135 -0
  29. airwallex/models/issuing_cardholder.py +52 -0
  30. airwallex/models/issuing_common.py +83 -0
  31. airwallex/models/issuing_config.py +62 -0
  32. airwallex/models/issuing_digital_wallet_token.py +38 -0
  33. airwallex/models/issuing_transaction.py +42 -0
  34. airwallex/models/issuing_transaction_dispute.py +59 -0
  35. airwallex/models/payment.py +81 -0
  36. airwallex/utils.py +107 -0
  37. airwallex_sdk-0.1.0.dist-info/METADATA +202 -0
  38. airwallex_sdk-0.1.0.dist-info/RECORD +39 -0
  39. airwallex_sdk-0.1.0.dist-info/WHEEL +4 -0
airwallex/__init__.py ADDED
@@ -0,0 +1,74 @@
1
+ """
2
+ Airwallex Python SDK.
3
+
4
+ A fully-featured SDK for interacting with the Airwallex API.
5
+ """
6
+ from .client import AirwallexClient, AirwallexAsyncClient
7
+ from .exceptions import (
8
+ AirwallexAPIError,
9
+ AuthenticationError,
10
+ RateLimitError,
11
+ ResourceNotFoundError,
12
+ ValidationError,
13
+ ServerError
14
+ )
15
+
16
+ # Import models
17
+ from .models import AirwallexModel
18
+ from .models.account import Account as AccountModel
19
+ from .models.payment import Payment as PaymentModel
20
+ from .models.beneficiary import Beneficiary as BeneficiaryModel
21
+ from .models.invoice import Invoice as InvoiceModel, InvoiceItem
22
+ from .models.financial_transaction import FinancialTransaction as FinancialTransactionModel
23
+ from .models.fx import FXConversion, FXQuote
24
+ from .models.account_detail import (
25
+ AccountDetailModel, AccountCreateRequest, AccountUpdateRequest,
26
+ Amendment, AmendmentCreateRequest, WalletInfo, TermsAndConditionsRequest
27
+ )
28
+
29
+ # Issuing API Models
30
+ from .models.issuing_authorization import Authorization as IssuingAuthorizationModel
31
+ from .models.issuing_cardholder import Cardholder as IssuingCardholderModel
32
+ from .models.issuing_card import Card as IssuingCardModel, CardDetails
33
+ from .models.issuing_digital_wallet_token import DigitalWalletToken as IssuingDigitalWalletTokenModel
34
+ from .models.issuing_transaction_dispute import TransactionDispute as IssuingTransactionDisputeModel
35
+ from .models.issuing_transaction import Transaction as IssuingTransactionModel
36
+ from .models.issuing_config import IssuingConfig as IssuingConfigModel
37
+
38
+ __all__ = [
39
+ "AirwallexClient",
40
+ "AirwallexAsyncClient",
41
+ "AirwallexAPIError",
42
+ "AuthenticationError",
43
+ "RateLimitError",
44
+ "ResourceNotFoundError",
45
+ "ValidationError",
46
+ "ServerError",
47
+ "AirwallexModel",
48
+ "AccountModel",
49
+ "PaymentModel",
50
+ "BeneficiaryModel",
51
+ "InvoiceModel",
52
+ "InvoiceItem",
53
+ "FinancialTransactionModel",
54
+ "FXConversion",
55
+ "FXQuote",
56
+ "AccountDetailModel",
57
+ "AccountCreateRequest",
58
+ "AccountUpdateRequest",
59
+ "Amendment",
60
+ "AmendmentCreateRequest",
61
+ "WalletInfo",
62
+ "TermsAndConditionsRequest",
63
+ # Issuing API
64
+ "IssuingAuthorizationModel",
65
+ "IssuingCardholderModel",
66
+ "IssuingCardModel",
67
+ "CardDetails",
68
+ "IssuingDigitalWalletTokenModel",
69
+ "IssuingTransactionDisputeModel",
70
+ "IssuingTransactionModel",
71
+ "IssuingConfigModel",
72
+ ]
73
+
74
+ __version__ = "0.2.0"
@@ -0,0 +1,37 @@
1
+ """
2
+ API modules for the Airwallex SDK.
3
+ """
4
+ from .base import AirwallexAPIBase
5
+ from .account import Account
6
+ from .payment import Payment
7
+ from .beneficiary import Beneficiary
8
+ from .invoice import Invoice
9
+ from .financial_transaction import FinancialTransaction
10
+ from .account_detail import AccountDetail
11
+
12
+ # Issuing API
13
+ from .issuing_authorization import IssuingAuthorization
14
+ from .issuing_cardholder import IssuingCardholder
15
+ from .issuing_card import IssuingCard
16
+ from .issuing_digital_wallet_token import IssuingDigitalWalletToken
17
+ from .issuing_transaction_dispute import IssuingTransactionDispute
18
+ from .issuing_transaction import IssuingTransaction
19
+ from .issuing_config import IssuingConfig
20
+
21
+ __all__ = [
22
+ "AirwallexAPIBase",
23
+ "Account",
24
+ "Payment",
25
+ "Beneficiary",
26
+ "Invoice",
27
+ "FinancialTransaction",
28
+ "AccountDetail",
29
+ # Issuing API
30
+ "IssuingAuthorization",
31
+ "IssuingCardholder",
32
+ "IssuingCard",
33
+ "IssuingDigitalWalletToken",
34
+ "IssuingTransactionDispute",
35
+ "IssuingTransaction",
36
+ "IssuingConfig",
37
+ ]
@@ -0,0 +1,107 @@
1
+ """
2
+ Airwallex Account API.
3
+ """
4
+ from typing import Dict, Any, List, Optional, Type, TypeVar, cast
5
+ from ..models.account import Account, AccountCreateRequest, AccountUpdateRequest
6
+ from .base import AirwallexAPIBase
7
+
8
+ T = TypeVar("T", bound=Account)
9
+
10
+
11
+ class Account(AirwallexAPIBase[Account]):
12
+ """
13
+ Operations for Airwallex accounts.
14
+
15
+ Accounts represent the global accounts that can hold balances
16
+ in multiple currencies.
17
+ """
18
+ endpoint = "accounts"
19
+ model_class = cast(Type[Account], Account)
20
+
21
+ def fetch_balance(self, account_id: str) -> Account:
22
+ """
23
+ Fetch the balance for a specific account.
24
+
25
+ Args:
26
+ account_id: The ID of the account to fetch the balance for.
27
+
28
+ Returns:
29
+ Account: Account with balance information.
30
+ """
31
+ url = self._build_url(account_id, "balance")
32
+ if not self.client.__class__.__name__.startswith('Async'):
33
+ response = self.client._request("GET", url)
34
+ data = response.json()
35
+ account_data = {"id": account_id, "balance": data}
36
+ return self.model_class.from_api_response(account_data)
37
+ else:
38
+ raise ValueError("Use fetch_balance_async for async clients")
39
+
40
+ async def fetch_balance_async(self, account_id: str) -> Account:
41
+ """
42
+ Fetch the balance for a specific account asynchronously.
43
+
44
+ Args:
45
+ account_id: The ID of the account to fetch the balance for.
46
+
47
+ Returns:
48
+ Account: Account with balance information.
49
+ """
50
+ url = self._build_url(account_id, "balance")
51
+ if self.client.__class__.__name__.startswith('Async'):
52
+ response = await self.client._request("GET", url)
53
+ data = response.json()
54
+ account_data = {"id": account_id, "balance": data}
55
+ return self.model_class.from_api_response(account_data)
56
+ else:
57
+ raise ValueError("Use fetch_balance for sync clients")
58
+
59
+ def create_from_model(self, account: AccountCreateRequest) -> Account:
60
+ """
61
+ Create a new account using a Pydantic model.
62
+
63
+ Args:
64
+ account: AccountCreateRequest model with account creation details.
65
+
66
+ Returns:
67
+ Account: The newly created account.
68
+ """
69
+ return self.create(account)
70
+
71
+ async def create_from_model_async(self, account: AccountCreateRequest) -> Account:
72
+ """
73
+ Create a new account using a Pydantic model asynchronously.
74
+
75
+ Args:
76
+ account: AccountCreateRequest model with account creation details.
77
+
78
+ Returns:
79
+ Account: The newly created account.
80
+ """
81
+ return await self.create_async(account)
82
+
83
+ def update_from_model(self, account_id: str, account: AccountUpdateRequest) -> Account:
84
+ """
85
+ Update an account using a Pydantic model.
86
+
87
+ Args:
88
+ account_id: The ID of the account to update.
89
+ account: AccountUpdateRequest model with account update details.
90
+
91
+ Returns:
92
+ Account: The updated account.
93
+ """
94
+ return self.update(account_id, account)
95
+
96
+ async def update_from_model_async(self, account_id: str, account: AccountUpdateRequest) -> Account:
97
+ """
98
+ Update an account using a Pydantic model asynchronously.
99
+
100
+ Args:
101
+ account_id: The ID of the account to update.
102
+ account: AccountUpdateRequest model with account update details.
103
+
104
+ Returns:
105
+ Account: The updated account.
106
+ """
107
+ return await self.update_async(account_id, account)
@@ -0,0 +1,469 @@
1
+ """
2
+ Airwallex Account Detail API.
3
+ """
4
+ from typing import Dict, Any, List, Optional, Type, TypeVar, Union, cast
5
+ from datetime import datetime
6
+ from ..models.account_detail import (
7
+ AccountDetailModel, AccountCreateRequest, AccountUpdateRequest,
8
+ Amendment, AmendmentCreateRequest, WalletInfo, TermsAndConditionsRequest
9
+ )
10
+ from .base import AirwallexAPIBase
11
+
12
+ T = TypeVar("T", bound=AccountDetailModel)
13
+
14
+
15
+ class AccountDetail(AirwallexAPIBase[AccountDetailModel]):
16
+ """
17
+ Operations for Airwallex account details.
18
+
19
+ Account details represent the complete information about an Airwallex account,
20
+ including business details, persons, and compliance information.
21
+ """
22
+ endpoint = "accounts"
23
+ model_class = cast(Type[AccountDetailModel], AccountDetailModel)
24
+
25
+ def get_my_account(self) -> AccountDetailModel:
26
+ """
27
+ Retrieve account details for your own Airwallex account.
28
+
29
+ Returns:
30
+ AccountDetailModel: Your account details.
31
+ """
32
+ url = "/api/v1/account"
33
+
34
+ if not self.client.__class__.__name__.startswith('Async'):
35
+ response = self.client._request("GET", url)
36
+ return self.model_class.from_api_response(response.json())
37
+ else:
38
+ raise ValueError("Use get_my_account_async for async clients")
39
+
40
+ async def get_my_account_async(self) -> AccountDetailModel:
41
+ """
42
+ Retrieve account details for your own Airwallex account asynchronously.
43
+
44
+ Returns:
45
+ AccountDetailModel: Your account details.
46
+ """
47
+ url = "/api/v1/account"
48
+
49
+ if self.client.__class__.__name__.startswith('Async'):
50
+ response = await self.client._request("GET", url)
51
+ return self.model_class.from_api_response(response.json())
52
+ else:
53
+ raise ValueError("Use get_my_account for sync clients")
54
+
55
+ def get_amendment(self, amendment_id: str) -> Amendment:
56
+ """
57
+ Get an account amendment.
58
+
59
+ Args:
60
+ amendment_id: The ID of the amendment to retrieve.
61
+
62
+ Returns:
63
+ Amendment: The amendment.
64
+ """
65
+ url = f"/api/v1/account/amendments/{amendment_id}"
66
+
67
+ if not self.client.__class__.__name__.startswith('Async'):
68
+ response = self.client._request("GET", url)
69
+ return Amendment.from_api_response(response.json())
70
+ else:
71
+ raise ValueError("Use get_amendment_async for async clients")
72
+
73
+ async def get_amendment_async(self, amendment_id: str) -> Amendment:
74
+ """
75
+ Get an account amendment asynchronously.
76
+
77
+ Args:
78
+ amendment_id: The ID of the amendment to retrieve.
79
+
80
+ Returns:
81
+ Amendment: The amendment.
82
+ """
83
+ url = f"/api/v1/account/amendments/{amendment_id}"
84
+
85
+ if self.client.__class__.__name__.startswith('Async'):
86
+ response = await self.client._request("GET", url)
87
+ return Amendment.from_api_response(response.json())
88
+ else:
89
+ raise ValueError("Use get_amendment for sync clients")
90
+
91
+ def create_amendment(self, amendment: AmendmentCreateRequest) -> Amendment:
92
+ """
93
+ Create an account amendment.
94
+
95
+ Args:
96
+ amendment: AmendmentCreateRequest model with amendment details.
97
+
98
+ Returns:
99
+ Amendment: The created amendment.
100
+ """
101
+ url = "/api/v1/account/amendments/create"
102
+
103
+ if not self.client.__class__.__name__.startswith('Async'):
104
+ response = self.client._request("POST", url, json=amendment.to_api_dict())
105
+ return Amendment.from_api_response(response.json())
106
+ else:
107
+ raise ValueError("Use create_amendment_async for async clients")
108
+
109
+ async def create_amendment_async(self, amendment: AmendmentCreateRequest) -> Amendment:
110
+ """
111
+ Create an account amendment asynchronously.
112
+
113
+ Args:
114
+ amendment: AmendmentCreateRequest model with amendment details.
115
+
116
+ Returns:
117
+ Amendment: The created amendment.
118
+ """
119
+ url = "/api/v1/account/amendments/create"
120
+
121
+ if self.client.__class__.__name__.startswith('Async'):
122
+ response = await self.client._request("POST", url, json=amendment.to_api_dict())
123
+ return Amendment.from_api_response(response.json())
124
+ else:
125
+ raise ValueError("Use create_amendment for sync clients")
126
+
127
+ def get_wallet_info(self) -> WalletInfo:
128
+ """
129
+ Retrieve account wallet information.
130
+
131
+ Returns:
132
+ WalletInfo: The wallet information.
133
+ """
134
+ url = "/api/v1/account/wallet_info"
135
+
136
+ if not self.client.__class__.__name__.startswith('Async'):
137
+ response = self.client._request("GET", url)
138
+ return WalletInfo.from_api_response(response.json())
139
+ else:
140
+ raise ValueError("Use get_wallet_info_async for async clients")
141
+
142
+ async def get_wallet_info_async(self) -> WalletInfo:
143
+ """
144
+ Retrieve account wallet information asynchronously.
145
+
146
+ Returns:
147
+ WalletInfo: The wallet information.
148
+ """
149
+ url = "/api/v1/account/wallet_info"
150
+
151
+ if self.client.__class__.__name__.startswith('Async'):
152
+ response = await self.client._request("GET", url)
153
+ return WalletInfo.from_api_response(response.json())
154
+ else:
155
+ raise ValueError("Use get_wallet_info for sync clients")
156
+
157
+ def create_account(self, account: AccountCreateRequest) -> AccountDetailModel:
158
+ """
159
+ Create a new Airwallex account.
160
+
161
+ Args:
162
+ account: AccountCreateRequest model with account creation details.
163
+
164
+ Returns:
165
+ AccountDetailModel: The created account.
166
+ """
167
+ url = "/api/v1/accounts/create"
168
+
169
+ if not self.client.__class__.__name__.startswith('Async'):
170
+ response = self.client._request("POST", url, json=account.to_api_dict())
171
+ return self.model_class.from_api_response(response.json())
172
+ else:
173
+ raise ValueError("Use create_account_async for async clients")
174
+
175
+ async def create_account_async(self, account: AccountCreateRequest) -> AccountDetailModel:
176
+ """
177
+ Create a new Airwallex account asynchronously.
178
+
179
+ Args:
180
+ account: AccountCreateRequest model with account creation details.
181
+
182
+ Returns:
183
+ AccountDetailModel: The created account.
184
+ """
185
+ url = "/api/v1/accounts/create"
186
+
187
+ if self.client.__class__.__name__.startswith('Async'):
188
+ response = await self.client._request("POST", url, json=account.to_api_dict())
189
+ return self.model_class.from_api_response(response.json())
190
+ else:
191
+ raise ValueError("Use create_account for sync clients")
192
+
193
+ def update_account(self, account_id: str, account: AccountUpdateRequest) -> AccountDetailModel:
194
+ """
195
+ Update a connected account.
196
+
197
+ Args:
198
+ account_id: The ID of the account to update.
199
+ account: AccountUpdateRequest model with account update details.
200
+
201
+ Returns:
202
+ AccountDetailModel: The updated account.
203
+ """
204
+ url = f"/api/v1/accounts/{account_id}/update"
205
+
206
+ if not self.client.__class__.__name__.startswith('Async'):
207
+ response = self.client._request("POST", url, json=account.to_api_dict())
208
+ return self.model_class.from_api_response(response.json())
209
+ else:
210
+ raise ValueError("Use update_account_async for async clients")
211
+
212
+ async def update_account_async(self, account_id: str, account: AccountUpdateRequest) -> AccountDetailModel:
213
+ """
214
+ Update a connected account asynchronously.
215
+
216
+ Args:
217
+ account_id: The ID of the account to update.
218
+ account: AccountUpdateRequest model with account update details.
219
+
220
+ Returns:
221
+ AccountDetailModel: The updated account.
222
+ """
223
+ url = f"/api/v1/accounts/{account_id}/update"
224
+
225
+ if self.client.__class__.__name__.startswith('Async'):
226
+ response = await self.client._request("POST", url, json=account.to_api_dict())
227
+ return self.model_class.from_api_response(response.json())
228
+ else:
229
+ raise ValueError("Use update_account for sync clients")
230
+
231
+ def submit_account(self, account_id: str) -> AccountDetailModel:
232
+ """
233
+ Submit account for activation.
234
+
235
+ Args:
236
+ account_id: The ID of the account to submit.
237
+
238
+ Returns:
239
+ AccountDetailModel: The submitted account.
240
+ """
241
+ url = f"/api/v1/accounts/{account_id}/submit"
242
+
243
+ if not self.client.__class__.__name__.startswith('Async'):
244
+ response = self.client._request("POST", url)
245
+ return self.model_class.from_api_response(response.json())
246
+ else:
247
+ raise ValueError("Use submit_account_async for async clients")
248
+
249
+ async def submit_account_async(self, account_id: str) -> AccountDetailModel:
250
+ """
251
+ Submit account for activation asynchronously.
252
+
253
+ Args:
254
+ account_id: The ID of the account to submit.
255
+
256
+ Returns:
257
+ AccountDetailModel: The submitted account.
258
+ """
259
+ url = f"/api/v1/accounts/{account_id}/submit"
260
+
261
+ if self.client.__class__.__name__.startswith('Async'):
262
+ response = await self.client._request("POST", url)
263
+ return self.model_class.from_api_response(response.json())
264
+ else:
265
+ raise ValueError("Use submit_account for sync clients")
266
+
267
+ def get_account(self, account_id: str) -> AccountDetailModel:
268
+ """
269
+ Get account by ID.
270
+
271
+ Args:
272
+ account_id: The ID of the account to retrieve.
273
+
274
+ Returns:
275
+ AccountDetailModel: The account.
276
+ """
277
+ url = f"/api/v1/accounts/{account_id}"
278
+
279
+ if not self.client.__class__.__name__.startswith('Async'):
280
+ response = self.client._request("GET", url)
281
+ return self.model_class.from_api_response(response.json())
282
+ else:
283
+ raise ValueError("Use get_account_async for async clients")
284
+
285
+ async def get_account_async(self, account_id: str) -> AccountDetailModel:
286
+ """
287
+ Get account by ID asynchronously.
288
+
289
+ Args:
290
+ account_id: The ID of the account to retrieve.
291
+
292
+ Returns:
293
+ AccountDetailModel: The account.
294
+ """
295
+ url = f"/api/v1/accounts/{account_id}"
296
+
297
+ if self.client.__class__.__name__.startswith('Async'):
298
+ response = await self.client._request("GET", url)
299
+ return self.model_class.from_api_response(response.json())
300
+ else:
301
+ raise ValueError("Use get_account for sync clients")
302
+
303
+ def list_accounts(
304
+ self,
305
+ account_status: Optional[str] = None,
306
+ email: Optional[str] = None,
307
+ from_created_at: Optional[Union[str, datetime]] = None,
308
+ identifier: Optional[str] = None,
309
+ metadata: Optional[str] = None,
310
+ page_num: Optional[int] = None,
311
+ page_size: Optional[int] = None,
312
+ to_created_at: Optional[Union[str, datetime]] = None
313
+ ) -> List[AccountDetailModel]:
314
+ """
315
+ Get list of connected accounts with filtering options.
316
+
317
+ Args:
318
+ account_status: Filter by account status (CREATED, SUBMITTED, ACTION_REQUIRED, ACTIVE, SUSPENDED)
319
+ email: Filter by email
320
+ from_created_at: Filter by creation date (start, inclusive)
321
+ identifier: Filter by identifier
322
+ metadata: Filter by metadata (key:value format)
323
+ page_num: Page number (0-indexed)
324
+ page_size: Number of results per page (default 100, max 500)
325
+ to_created_at: Filter by creation date (end, inclusive)
326
+
327
+ Returns:
328
+ List[AccountDetailModel]: List of matching accounts.
329
+ """
330
+ url = "/api/v1/accounts"
331
+ params = {}
332
+
333
+ if account_status:
334
+ params["account_status"] = account_status
335
+
336
+ if email:
337
+ params["email"] = email
338
+
339
+ if from_created_at:
340
+ if isinstance(from_created_at, datetime):
341
+ from_created_at = from_created_at.isoformat()
342
+ params["from_created_at"] = from_created_at
343
+
344
+ if identifier:
345
+ params["identifier"] = identifier
346
+
347
+ if metadata:
348
+ params["metadata"] = metadata
349
+
350
+ if page_num is not None:
351
+ params["page_num"] = page_num
352
+
353
+ if page_size is not None:
354
+ params["page_size"] = page_size
355
+
356
+ if to_created_at:
357
+ if isinstance(to_created_at, datetime):
358
+ to_created_at = to_created_at.isoformat()
359
+ params["to_created_at"] = to_created_at
360
+
361
+ if not self.client.__class__.__name__.startswith('Async'):
362
+ response = self.client._request("GET", url, params=params)
363
+ data = response.json()
364
+ return [self.model_class.from_api_response(item) for item in data.get("items", [])]
365
+ else:
366
+ raise ValueError("Use list_accounts_async for async clients")
367
+
368
+ async def list_accounts_async(
369
+ self,
370
+ account_status: Optional[str] = None,
371
+ email: Optional[str] = None,
372
+ from_created_at: Optional[Union[str, datetime]] = None,
373
+ identifier: Optional[str] = None,
374
+ metadata: Optional[str] = None,
375
+ page_num: Optional[int] = None,
376
+ page_size: Optional[int] = None,
377
+ to_created_at: Optional[Union[str, datetime]] = None
378
+ ) -> List[AccountDetailModel]:
379
+ """
380
+ Get list of connected accounts with filtering options asynchronously.
381
+
382
+ Args:
383
+ account_status: Filter by account status (CREATED, SUBMITTED, ACTION_REQUIRED, ACTIVE, SUSPENDED)
384
+ email: Filter by email
385
+ from_created_at: Filter by creation date (start, inclusive)
386
+ identifier: Filter by identifier
387
+ metadata: Filter by metadata (key:value format)
388
+ page_num: Page number (0-indexed)
389
+ page_size: Number of results per page (default 100, max 500)
390
+ to_created_at: Filter by creation date (end, inclusive)
391
+
392
+ Returns:
393
+ List[AccountDetailModel]: List of matching accounts.
394
+ """
395
+ url = "/api/v1/accounts"
396
+ params = {}
397
+
398
+ if account_status:
399
+ params["account_status"] = account_status
400
+
401
+ if email:
402
+ params["email"] = email
403
+
404
+ if from_created_at:
405
+ if isinstance(from_created_at, datetime):
406
+ from_created_at = from_created_at.isoformat()
407
+ params["from_created_at"] = from_created_at
408
+
409
+ if identifier:
410
+ params["identifier"] = identifier
411
+
412
+ if metadata:
413
+ params["metadata"] = metadata
414
+
415
+ if page_num is not None:
416
+ params["page_num"] = page_num
417
+
418
+ if page_size is not None:
419
+ params["page_size"] = page_size
420
+
421
+ if to_created_at:
422
+ if isinstance(to_created_at, datetime):
423
+ to_created_at = to_created_at.isoformat()
424
+ params["to_created_at"] = to_created_at
425
+
426
+ if self.client.__class__.__name__.startswith('Async'):
427
+ response = await self.client._request("GET", url, params=params)
428
+ data = response.json()
429
+ return [self.model_class.from_api_response(item) for item in data.get("items", [])]
430
+ else:
431
+ raise ValueError("Use list_accounts for sync clients")
432
+
433
+ def agree_to_terms(self, account_id: str, request: TermsAndConditionsRequest) -> AccountDetailModel:
434
+ """
435
+ Agree to terms and conditions.
436
+
437
+ Args:
438
+ account_id: The ID of the account agreeing to terms.
439
+ request: TermsAndConditionsRequest model with agreement details.
440
+
441
+ Returns:
442
+ AccountDetailModel: The updated account.
443
+ """
444
+ url = f"/api/v1/accounts/{account_id}/terms_and_conditions/agree"
445
+
446
+ if not self.client.__class__.__name__.startswith('Async'):
447
+ response = self.client._request("POST", url, json=request.to_api_dict())
448
+ return self.model_class.from_api_response(response.json())
449
+ else:
450
+ raise ValueError("Use agree_to_terms_async for async clients")
451
+
452
+ async def agree_to_terms_async(self, account_id: str, request: TermsAndConditionsRequest) -> AccountDetailModel:
453
+ """
454
+ Agree to terms and conditions asynchronously.
455
+
456
+ Args:
457
+ account_id: The ID of the account agreeing to terms.
458
+ request: TermsAndConditionsRequest model with agreement details.
459
+
460
+ Returns:
461
+ AccountDetailModel: The updated account.
462
+ """
463
+ url = f"/api/v1/accounts/{account_id}/terms_and_conditions/agree"
464
+
465
+ if self.client.__class__.__name__.startswith('Async'):
466
+ response = await self.client._request("POST", url, json=request.to_api_dict())
467
+ return self.model_class.from_api_response(response.json())
468
+ else:
469
+ raise ValueError("Use agree_to_terms for sync clients")