lago-python-client 1.32.0__tar.gz → 1.33.0__tar.gz

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 (153) hide show
  1. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/PKG-INFO +2 -2
  2. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/client.py +5 -0
  3. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/customers/clients.py +22 -0
  4. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/models/__init__.py +4 -0
  5. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/models/billing_entity.py +5 -1
  6. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/models/customer.py +1 -15
  7. lago_python_client-1.33.0/lago_python_client/models/customer_projected_usage.py +73 -0
  8. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/models/customer_usage.py +2 -2
  9. lago_python_client-1.33.0/lago_python_client/models/invoice_custom_section.py +17 -0
  10. lago_python_client-1.33.0/lago_python_client/models/usage.py +18 -0
  11. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/models/wallet.py +1 -0
  12. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/payment_requests/clients.py +2 -1
  13. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/services/response.py +13 -9
  14. lago_python_client-1.33.0/lago_python_client/usages/clients.py +39 -0
  15. lago_python_client-1.33.0/lago_python_client/version.py +1 -0
  16. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/webhooks/clients.py +4 -6
  17. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client.egg-info/PKG-INFO +2 -2
  18. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client.egg-info/SOURCES.txt +12 -0
  19. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client.egg-info/requires.txt +1 -1
  20. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/setup.cfg +1 -1
  21. lago_python_client-1.33.0/tests/__init__.py +0 -0
  22. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/tests/test_billing_entity_client.py +1 -0
  23. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/tests/test_customer_client.py +27 -3
  24. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/tests/test_payment_request_client.py +31 -0
  25. lago_python_client-1.33.0/tests/test_usage_client.py +27 -0
  26. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/tests/test_wallet_client.py +5 -1
  27. lago_python_client-1.32.0/lago_python_client/version.py +0 -1
  28. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/LICENSE +0 -0
  29. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/README.md +0 -0
  30. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/__init__.py +0 -0
  31. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/activity_logs/__init__.py +0 -0
  32. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/activity_logs/clients.py +0 -0
  33. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/add_ons/__init__.py +0 -0
  34. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/add_ons/clients.py +0 -0
  35. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/api_logs/__init__.py +0 -0
  36. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/api_logs/clients.py +0 -0
  37. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/base_client.py +0 -0
  38. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/base_model.py +0 -0
  39. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/billable_metrics/__init__.py +0 -0
  40. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/billable_metrics/clients.py +0 -0
  41. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/billing_entities/__init__.py +0 -0
  42. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/billing_entities/clients.py +0 -0
  43. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/coupons/__init__.py +0 -0
  44. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/coupons/clients.py +0 -0
  45. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/credit_notes/__init__.py +0 -0
  46. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/credit_notes/clients.py +0 -0
  47. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/customers/__init__.py +0 -0
  48. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/events/__init__.py +0 -0
  49. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/events/clients.py +0 -0
  50. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/exceptions.py +0 -0
  51. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/fees/__init__.py +0 -0
  52. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/fees/clients.py +0 -0
  53. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/functools_ext.py +0 -0
  54. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/gross_revenues/__init__.py +0 -0
  55. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/gross_revenues/clients.py +0 -0
  56. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/invoice_collections/__init__.py +0 -0
  57. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/invoice_collections/clients.py +0 -0
  58. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/invoiced_usages/__init__.py +0 -0
  59. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/invoiced_usages/clients.py +0 -0
  60. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/invoices/__init__.py +0 -0
  61. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/invoices/clients.py +0 -0
  62. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/mixins.py +0 -0
  63. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/models/activity_log.py +0 -0
  64. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/models/add_on.py +0 -0
  65. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/models/api_log.py +0 -0
  66. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/models/applied_coupon.py +0 -0
  67. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/models/billable_metric.py +0 -0
  68. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/models/billing_period.py +0 -0
  69. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/models/charge.py +0 -0
  70. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/models/coupon.py +0 -0
  71. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/models/credit.py +0 -0
  72. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/models/credit_note.py +0 -0
  73. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/models/error_detail.py +0 -0
  74. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/models/event.py +0 -0
  75. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/models/fee.py +0 -0
  76. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/models/gross_revenue.py +0 -0
  77. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/models/invoice.py +0 -0
  78. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/models/invoice_collection.py +0 -0
  79. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/models/invoice_item.py +0 -0
  80. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/models/invoiced_usage.py +0 -0
  81. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/models/lifetime_usage.py +0 -0
  82. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/models/minimum_commitment.py +0 -0
  83. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/models/mrr.py +0 -0
  84. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/models/organization.py +0 -0
  85. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/models/overdue_balance.py +0 -0
  86. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/models/payment.py +0 -0
  87. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/models/payment_receipt.py +0 -0
  88. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/models/payment_request.py +0 -0
  89. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/models/plan.py +0 -0
  90. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/models/subscription.py +0 -0
  91. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/models/tax.py +0 -0
  92. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/models/usage_threshold.py +0 -0
  93. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/models/wallet_transaction.py +0 -0
  94. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/models/webhook_endpoint.py +0 -0
  95. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/mrrs/__init__.py +0 -0
  96. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/mrrs/clients.py +0 -0
  97. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/organizations/__init__.py +0 -0
  98. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/organizations/clients.py +0 -0
  99. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/overdue_balances/__init__.py +0 -0
  100. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/overdue_balances/clients.py +0 -0
  101. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/payment_receipts/__init__.py +0 -0
  102. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/payment_receipts/clients.py +0 -0
  103. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/payment_requests/__init__.py +0 -0
  104. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/payments/__init__.py +0 -0
  105. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/payments/clients.py +0 -0
  106. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/plans/__init__.py +0 -0
  107. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/plans/clients.py +0 -0
  108. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/py.typed +0 -0
  109. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/services/__init__.py +0 -0
  110. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/services/json.py +0 -0
  111. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/services/request.py +0 -0
  112. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/subscriptions/__init__.py +0 -0
  113. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/subscriptions/clients.py +0 -0
  114. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/taxes/__init__.py +0 -0
  115. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/taxes/clients.py +0 -0
  116. {lago_python_client-1.32.0/lago_python_client/wallets → lago_python_client-1.33.0/lago_python_client/usages}/__init__.py +0 -0
  117. {lago_python_client-1.32.0/lago_python_client/webhook_endpoints → lago_python_client-1.33.0/lago_python_client/wallets}/__init__.py +0 -0
  118. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/wallets/clients.py +0 -0
  119. {lago_python_client-1.32.0/lago_python_client/webhooks → lago_python_client-1.33.0/lago_python_client/webhook_endpoints}/__init__.py +0 -0
  120. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client/webhook_endpoints/clients.py +0 -0
  121. {lago_python_client-1.32.0/tests → lago_python_client-1.33.0/lago_python_client/webhooks}/__init__.py +0 -0
  122. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client.egg-info/dependency_links.txt +0 -0
  123. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/lago_python_client.egg-info/top_level.txt +0 -0
  124. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/pyproject.toml +0 -0
  125. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/tests/test_activity_logs_client.py +0 -0
  126. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/tests/test_add_on_client.py +0 -0
  127. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/tests/test_api_logs_client.py +0 -0
  128. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/tests/test_applied_coupon_client.py +0 -0
  129. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/tests/test_billable_metric_client.py +0 -0
  130. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/tests/test_client.py +0 -0
  131. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/tests/test_coupon_client.py +0 -0
  132. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/tests/test_credit_note_client.py +0 -0
  133. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/tests/test_event_client.py +0 -0
  134. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/tests/test_fee_client.py +0 -0
  135. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/tests/test_functools_ext.py +0 -0
  136. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/tests/test_gross_revenue_client.py +0 -0
  137. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/tests/test_invoice_client.py +0 -0
  138. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/tests/test_invoice_collection_client.py +0 -0
  139. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/tests/test_invoiced_usage_client.py +0 -0
  140. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/tests/test_json_services.py +0 -0
  141. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/tests/test_mrr_client.py +0 -0
  142. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/tests/test_organization_client.py +0 -0
  143. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/tests/test_overdue_balance_client.py +0 -0
  144. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/tests/test_payment_client.py +0 -0
  145. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/tests/test_payment_receipt_client.py +0 -0
  146. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/tests/test_plan_client.py +0 -0
  147. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/tests/test_request_services.py +0 -0
  148. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/tests/test_response_services.py +0 -0
  149. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/tests/test_subscription_client.py +0 -0
  150. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/tests/test_tax_client.py +0 -0
  151. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/tests/test_wallet_transaction_client.py +0 -0
  152. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/tests/test_webhook_client.py +0 -0
  153. {lago_python_client-1.32.0 → lago_python_client-1.33.0}/tests/test_webhook_endpoint_client.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lago-python-client
3
- Version: 1.32.0
3
+ Version: 1.33.0
4
4
  Summary: Lago Python API Client
5
5
  Home-page: https://github.com/getlago/lago-python-client
6
6
  Author: Lovro Colic
@@ -24,7 +24,7 @@ Requires-Dist: classes~=0.4.1
24
24
  Requires-Dist: httpx<1.0.0,>=0.24.0
25
25
  Requires-Dist: orjson~=3.8
26
26
  Requires-Dist: pydantic<3,>=1.10
27
- Requires-Dist: typeguard~=3.0.2
27
+ Requires-Dist: typeguard~=4.0
28
28
  Provides-Extra: test
29
29
  Requires-Dist: mypy==0.971; extra == "test"
30
30
  Requires-Dist: pytest; extra == "test"
@@ -22,6 +22,7 @@ from .invoice_collections.clients import InvoiceCollectionClient
22
22
  from .plans.clients import PlanClient
23
23
  from .subscriptions.clients import SubscriptionClient
24
24
  from .taxes.clients import TaxClient
25
+ from .usages.clients import UsageClient
25
26
  from .wallets.clients import WalletClient, WalletTransactionClient
26
27
  from .webhooks.clients import WebhookClient
27
28
  from .webhook_endpoints.clients import WebhookEndpointClient
@@ -151,6 +152,10 @@ class Client:
151
152
  def taxes(self) -> TaxClient:
152
153
  return TaxClient(self.base_api_url, self.api_key)
153
154
 
155
+ @callable_cached_property
156
+ def usages(self) -> UsageClient:
157
+ return UsageClient(self.base_api_url, self.api_key)
158
+
154
159
  @callable_cached_property
155
160
  def wallets(self) -> WalletClient:
156
161
  return WalletClient(self.base_api_url, self.api_key)
@@ -10,6 +10,7 @@ from ..mixins import (
10
10
  )
11
11
  from ..models.customer import CustomerResponse
12
12
  from ..models.customer_usage import CustomerUsageResponse
13
+ from ..models.customer_projected_usage import CustomerProjectedUsageResponse
13
14
  from ..services.request import make_headers, make_url, send_get_request, send_post_request, QueryPairs
14
15
  from ..services.response import (
15
16
  get_response_data,
@@ -56,6 +57,27 @@ class CustomerClient(
56
57
  data=get_response_data(response=api_response, key="customer_usage"),
57
58
  )
58
59
 
60
+ def projected_usage(
61
+ self, resource_id: str, external_subscription_id: str, apply_taxes: Optional[str] = None
62
+ ) -> CustomerProjectedUsageResponse:
63
+ query_params = {"external_subscription_id": external_subscription_id}
64
+ if apply_taxes is not None:
65
+ query_params["apply_taxes"] = apply_taxes
66
+
67
+ api_response: Response = send_get_request(
68
+ url=make_url(
69
+ origin=self.base_url,
70
+ path_parts=(self.API_RESOURCE, resource_id, "projected_usage"),
71
+ query_pairs=query_params,
72
+ ),
73
+ headers=make_headers(api_key=self.api_key),
74
+ )
75
+
76
+ return prepare_object_response(
77
+ response_model=CustomerProjectedUsageResponse,
78
+ data=get_response_data(response=api_response, key="customer_projected_usage"),
79
+ )
80
+
59
81
  def past_usage(
60
82
  self,
61
83
  resource_id: str,
@@ -67,6 +67,10 @@ from .invoice import (
67
67
  InvoiceFee as InvoiceFee,
68
68
  )
69
69
  from .invoice_item import InvoiceItemResponse as InvoiceItemResponse
70
+ from .invoice_custom_section import (
71
+ InvoiceCustomSectionResponse as InvoiceCustomSectionResponse,
72
+ InvoiceCustomSectionsResponseList as InvoiceCustomSectionsResponseList,
73
+ )
70
74
  from .minimum_commitment import (
71
75
  MinimumCommitment as MinimumCommitment,
72
76
  MinimumCommitmentResponse as MinimumCommitmentResponse,
@@ -1,7 +1,9 @@
1
1
  from typing import Optional, List
2
+ from datetime import datetime
3
+
2
4
  from ..base_model import BaseModel, BaseResponseModel
3
5
  from .tax import TaxesResponse
4
- from datetime import datetime
6
+ from .invoice_custom_section import InvoiceCustomSectionsResponseList
5
7
 
6
8
 
7
9
  class BillingEntityBillingConfiguration(BaseModel):
@@ -60,6 +62,7 @@ class BillingEntityUpdate(BaseModel):
60
62
  tax_codes: Optional[List[str]]
61
63
  email_settings: Optional[List[str]]
62
64
  billing_configuration: Optional[BillingEntityBillingConfiguration]
65
+ invoice_custom_section_codes: Optional[List[str]]
63
66
 
64
67
 
65
68
  class BillingEntityResponse(BaseResponseModel):
@@ -92,5 +95,6 @@ class BillingEntityResponse(BaseResponseModel):
92
95
  invoice_grace_period: Optional[int]
93
96
  email_settings: Optional[List[str]]
94
97
  taxes: Optional[TaxesResponse]
98
+ selected_invoice_custom_sections: Optional[InvoiceCustomSectionsResponseList]
95
99
  created_at: datetime
96
100
  updated_at: datetime
@@ -5,6 +5,7 @@ from lago_python_client.base_model import BaseModel
5
5
  from ..base_model import BaseResponseModel
6
6
 
7
7
  from .tax import TaxesResponse
8
+ from .invoice_custom_section import InvoiceCustomSectionsResponseList
8
9
 
9
10
 
10
11
  class CustomerBillingConfiguration(BaseModel):
@@ -75,21 +76,6 @@ class MetadataResponseList(BaseModel):
75
76
  __root__: List[MetadataResponse]
76
77
 
77
78
 
78
- class InvoiceCustomSection(BaseModel):
79
- lago_id: Optional[str]
80
- code: Optional[str]
81
- name: Optional[str]
82
- description: Optional[str]
83
- details: Optional[str]
84
- display_name: Optional[str]
85
- applied_to_organization: Optional[bool]
86
- created_at: Optional[str]
87
-
88
-
89
- class InvoiceCustomSectionsResponseList(BaseModel):
90
- __root__: List[InvoiceCustomSection]
91
-
92
-
93
79
  class Customer(BaseModel):
94
80
  external_id: str
95
81
  address_line1: Optional[str]
@@ -0,0 +1,73 @@
1
+ from typing import Dict, List, Optional
2
+
3
+ from lago_python_client.base_model import BaseModel
4
+
5
+ from ..base_model import BaseResponseModel
6
+
7
+
8
+ class Metric(BaseModel):
9
+ lago_id: str
10
+ name: str
11
+ code: str
12
+ aggregation_type: str
13
+
14
+
15
+ class PricingUnitDetails(BaseModel):
16
+ amount_cents: int
17
+ short_name: str
18
+ conversion_rate: float
19
+
20
+
21
+ class ProjectedChargeFilterUsage(BaseModel):
22
+ invoice_display_name: Optional[str]
23
+ values: Dict[str, List[str]]
24
+ units: str
25
+ projected_units: str
26
+ amount_cents: int
27
+ projected_amount_cents: int
28
+ events_count: int
29
+ pricing_unit_details: Optional[PricingUnitDetails]
30
+
31
+
32
+ class ChargeObject(BaseModel):
33
+ lago_id: str
34
+ charge_model: str
35
+ invoice_display_name: Optional[str]
36
+
37
+
38
+ class ProjectedGroupedUsage(BaseModel):
39
+ amount_cents: int
40
+ projected_amount_cents: int
41
+ events_count: int
42
+ units: str
43
+ projected_units: str
44
+ grouped_by: Dict[str, str]
45
+ filters: List[ProjectedChargeFilterUsage]
46
+ pricing_unit_details: Optional[PricingUnitDetails]
47
+
48
+
49
+ class ProjectedChargeUsage(BaseModel):
50
+ units: str
51
+ projected_units: str
52
+ events_count: int
53
+ amount_cents: int
54
+ projected_amount_cents: int
55
+ amount_currency: str
56
+ charge: ChargeObject
57
+ billable_metric: Metric
58
+ filters: List[ProjectedChargeFilterUsage]
59
+ grouped_usage: Optional[List[ProjectedGroupedUsage]]
60
+ pricing_unit_details: Optional[PricingUnitDetails]
61
+
62
+
63
+ class CustomerProjectedUsageResponse(BaseResponseModel):
64
+ from_datetime: str
65
+ to_datetime: str
66
+ issuing_date: str
67
+ invoice_id: Optional[str]
68
+ currency: str
69
+ amount_cents: int
70
+ projected_amount_cents: int
71
+ total_amount_cents: int
72
+ taxes_amount_cents: int
73
+ charges_usage: List[ProjectedChargeUsage]
@@ -36,14 +36,14 @@ class ChargeObject(BaseModel):
36
36
  class GroupedUsage(BaseModel):
37
37
  amount_cents: int
38
38
  events_count: int
39
- units: float
39
+ units: str
40
40
  grouped_by: Dict[str, str]
41
41
  filters: List[ChargeFilterUsage]
42
42
  pricing_unit_details: Optional[PricingUnitDetails]
43
43
 
44
44
 
45
45
  class ChargeUsage(BaseModel):
46
- units: float
46
+ units: str
47
47
  events_count: int
48
48
  amount_cents: int
49
49
  amount_currency: str
@@ -0,0 +1,17 @@
1
+ from typing import List, Optional
2
+
3
+ from ..base_model import BaseResponseModel
4
+
5
+
6
+ class InvoiceCustomSectionResponse(BaseResponseModel):
7
+ lago_id: Optional[str]
8
+ code: Optional[str]
9
+ name: Optional[str]
10
+ description: Optional[str]
11
+ details: Optional[str]
12
+ display_name: Optional[str]
13
+ applied_to_organization: Optional[bool] # Deprecated
14
+
15
+
16
+ class InvoiceCustomSectionsResponseList(BaseResponseModel):
17
+ __root__: List[InvoiceCustomSectionResponse]
@@ -0,0 +1,18 @@
1
+ from typing import List
2
+
3
+ from ..base_model import BaseResponseModel
4
+
5
+
6
+ class UsageResponse(BaseResponseModel):
7
+ organization_id: str
8
+ start_of_period_dt: str
9
+ end_of_period_dt: str
10
+ amount_currency: str
11
+ amount_cents: int
12
+ billable_metric_code: str
13
+ units: float
14
+ is_billable_metric_deleted: bool
15
+
16
+
17
+ class UsagesResponse(BaseResponseModel):
18
+ __root__: List[UsageResponse]
@@ -45,6 +45,7 @@ class RecurringTransactionRuleResponseList(BaseModel):
45
45
 
46
46
  class AppliesTo(BaseModel):
47
47
  fee_types: Optional[List[str]]
48
+ billable_metric_codes: Optional[List[str]]
48
49
 
49
50
 
50
51
  class Wallet(BaseModel):
@@ -1,13 +1,14 @@
1
1
  from typing import ClassVar, Type
2
2
 
3
3
  from ..base_client import BaseClient
4
- from ..mixins import CreateCommandMixin, FindAllCommandMixin
4
+ from ..mixins import CreateCommandMixin, FindAllCommandMixin, FindCommandMixin
5
5
  from ..models.payment_request import PaymentRequestResponse
6
6
 
7
7
 
8
8
  class PaymentRequestClient(
9
9
  CreateCommandMixin[PaymentRequestResponse],
10
10
  FindAllCommandMixin[PaymentRequestResponse],
11
+ FindCommandMixin[PaymentRequestResponse],
11
12
  BaseClient,
12
13
  ):
13
14
  API_RESOURCE: ClassVar[str] = "payment_requests"
@@ -13,7 +13,7 @@ except ImportError: # Python 3.7
13
13
 
14
14
  from httpx import Response as Response # not a typo! implicit reexport
15
15
  from lago_python_client.base_model import BaseModel
16
- import typeguard
16
+ from typeguard import check_type, CollectionCheckStrategy, TypeCheckError
17
17
 
18
18
  from ..exceptions import LagoApiError
19
19
  from ..services.json import DeserializedData, from_json
@@ -25,8 +25,6 @@ else:
25
25
 
26
26
  _M = TypeVar("_M", bound=BaseModel)
27
27
 
28
- typeguard.config.collection_check_strategy = typeguard.CollectionCheckStrategy.ALL_ITEMS
29
-
30
28
  RESPONSE_SUCCESS_CODES: Final[Set[int]] = {
31
29
  HTTPStatus.OK, # 200
32
30
  HTTPStatus.CREATED, # 201
@@ -74,8 +72,10 @@ def get_response_data(*, response: Response, key: str = "") -> Optional[_Mapping
74
72
 
75
73
  # Ensure deserialized_data has correct type: sequence or mapping or raise LagoApiError
76
74
  try:
77
- mapping_or_sequence_data = typeguard.check_type(deserialized_data, _MappingOrSequence)
78
- except typeguard.TypeCheckError as exc:
75
+ mapping_or_sequence_data = check_type(
76
+ deserialized_data, _MappingOrSequence, collection_check_strategy=CollectionCheckStrategy.ALL_ITEMS
77
+ )
78
+ except TypeCheckError as exc:
79
79
  raise LagoApiError(
80
80
  status_code=HTTPStatus.INTERNAL_SERVER_ERROR, # 500
81
81
  url=None,
@@ -113,8 +113,10 @@ def prepare_index_response(
113
113
  # Ensure deserialized_data has correct type: mapping with mapping or sequence inside or raise LagoApiError
114
114
 
115
115
  try:
116
- response_data: Mapping[str, _MappingOrSequence] = typeguard.check_type(data, Mapping[str, _MappingOrSequence])
117
- except typeguard.TypeCheckError as exc:
116
+ response_data: Mapping[str, _MappingOrSequence] = check_type(
117
+ data, Mapping[str, _MappingOrSequence], collection_check_strategy=CollectionCheckStrategy.ALL_ITEMS
118
+ )
119
+ except TypeCheckError as exc:
118
120
  raise LagoApiError(
119
121
  status_code=HTTPStatus.INTERNAL_SERVER_ERROR, # 500
120
122
  url=None,
@@ -140,8 +142,10 @@ def prepare_object_list_response(
140
142
  # The only usage - ``WalletTransactionClient.create``
141
143
  # Ensure deserialized_data has correct type: sequence with mapping or sequence inside or raise LagoApiError
142
144
  try:
143
- response_data: Sequence[_MappingOrSequence] = typeguard.check_type(data, Sequence[_MappingOrSequence])
144
- except typeguard.TypeCheckError as exc:
145
+ response_data: Sequence[_MappingOrSequence] = check_type(
146
+ data, Sequence[_MappingOrSequence], collection_check_strategy=CollectionCheckStrategy.ALL_ITEMS
147
+ )
148
+ except TypeCheckError as exc:
145
149
  raise LagoApiError(
146
150
  status_code=HTTPStatus.INTERNAL_SERVER_ERROR, # 500
147
151
  url=None,
@@ -0,0 +1,39 @@
1
+ import sys
2
+ from typing import Any, ClassVar, Type
3
+
4
+ from ..base_client import BaseClient
5
+ from ..mixins import FindAllCommandMixin
6
+ from ..models.usage import UsageResponse
7
+ from ..services.request import make_headers, make_url, send_get_request, QueryPairs
8
+ from ..services.response import get_response_data, prepare_index_response, Response
9
+
10
+ if sys.version_info >= (3, 9):
11
+ from collections.abc import Mapping
12
+ else:
13
+ from typing import Mapping
14
+
15
+
16
+ class UsageClient(
17
+ FindAllCommandMixin[UsageResponse],
18
+ BaseClient,
19
+ ):
20
+ API_RESOURCE: ClassVar[str] = "usages"
21
+ RESPONSE_MODEL: ClassVar[Type[UsageResponse]] = UsageResponse
22
+ ROOT_NAME: ClassVar[str] = "usage"
23
+
24
+ def find_all(self, options: QueryPairs = {}) -> Mapping[str, Any]:
25
+ api_response: Response = send_get_request(
26
+ url=make_url(
27
+ origin=self.base_url,
28
+ path_parts=("analytics", "usage"),
29
+ query_pairs=options,
30
+ ),
31
+ headers=make_headers(api_key=self.api_key),
32
+ )
33
+
34
+ # Process response data
35
+ return prepare_index_response(
36
+ api_resource=self.API_RESOURCE,
37
+ response_model=self.RESPONSE_MODEL,
38
+ data=get_response_data(response=api_response),
39
+ )
@@ -0,0 +1 @@
1
+ LAGO_VERSION = "1.33.0"
@@ -9,7 +9,7 @@ except ImportError:
9
9
  from typing_extensions import TypedDict
10
10
 
11
11
  from lago_python_client.base_model import BaseModel
12
- import typeguard
12
+ from typeguard import check_type, CollectionCheckStrategy, TypeCheckError
13
13
 
14
14
  from ..base_client import BaseClient
15
15
  from ..exceptions import LagoApiError
@@ -21,8 +21,6 @@ if sys.version_info >= (3, 9):
21
21
  else:
22
22
  from typing import Mapping, Sequence
23
23
 
24
- typeguard.config.collection_check_strategy = typeguard.CollectionCheckStrategy.ALL_ITEMS
25
-
26
24
 
27
25
  class _ResponseWithPublicKeyInside(TypedDict):
28
26
  public_key: str
@@ -46,10 +44,10 @@ class WebhookClient(BaseClient):
46
44
  )
47
45
 
48
46
  try:
49
- checked_response_data: _ResponseWithPublicKeyInside = typeguard.check_type(
50
- response_data, _ResponseWithPublicKeyInside
47
+ checked_response_data: _ResponseWithPublicKeyInside = check_type(
48
+ response_data, _ResponseWithPublicKeyInside, collection_check_strategy=CollectionCheckStrategy.ALL_ITEMS
51
49
  ) # type: ignore
52
- except typeguard.TypeCheckError:
50
+ except TypeCheckError:
53
51
  raise LagoApiError(
54
52
  status_code=HTTPStatus.INTERNAL_SERVER_ERROR, # 500
55
53
  url=None,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lago-python-client
3
- Version: 1.32.0
3
+ Version: 1.33.0
4
4
  Summary: Lago Python API Client
5
5
  Home-page: https://github.com/getlago/lago-python-client
6
6
  Author: Lovro Colic
@@ -24,7 +24,7 @@ Requires-Dist: classes~=0.4.1
24
24
  Requires-Dist: httpx<1.0.0,>=0.24.0
25
25
  Requires-Dist: orjson~=3.8
26
26
  Requires-Dist: pydantic<3,>=1.10
27
- Requires-Dist: typeguard~=3.0.2
27
+ Requires-Dist: typeguard~=4.0
28
28
  Provides-Extra: test
29
29
  Requires-Dist: mypy==0.971; extra == "test"
30
30
  Requires-Dist: pytest; extra == "test"
@@ -52,6 +52,7 @@ setup.cfg
52
52
  ./lago_python_client/models/credit.py
53
53
  ./lago_python_client/models/credit_note.py
54
54
  ./lago_python_client/models/customer.py
55
+ ./lago_python_client/models/customer_projected_usage.py
55
56
  ./lago_python_client/models/customer_usage.py
56
57
  ./lago_python_client/models/error_detail.py
57
58
  ./lago_python_client/models/event.py
@@ -59,6 +60,7 @@ setup.cfg
59
60
  ./lago_python_client/models/gross_revenue.py
60
61
  ./lago_python_client/models/invoice.py
61
62
  ./lago_python_client/models/invoice_collection.py
63
+ ./lago_python_client/models/invoice_custom_section.py
62
64
  ./lago_python_client/models/invoice_item.py
63
65
  ./lago_python_client/models/invoiced_usage.py
64
66
  ./lago_python_client/models/lifetime_usage.py
@@ -72,6 +74,7 @@ setup.cfg
72
74
  ./lago_python_client/models/plan.py
73
75
  ./lago_python_client/models/subscription.py
74
76
  ./lago_python_client/models/tax.py
77
+ ./lago_python_client/models/usage.py
75
78
  ./lago_python_client/models/usage_threshold.py
76
79
  ./lago_python_client/models/wallet.py
77
80
  ./lago_python_client/models/wallet_transaction.py
@@ -98,6 +101,8 @@ setup.cfg
98
101
  ./lago_python_client/subscriptions/clients.py
99
102
  ./lago_python_client/taxes/__init__.py
100
103
  ./lago_python_client/taxes/clients.py
104
+ ./lago_python_client/usages/__init__.py
105
+ ./lago_python_client/usages/clients.py
101
106
  ./lago_python_client/wallets/__init__.py
102
107
  ./lago_python_client/wallets/clients.py
103
108
  ./lago_python_client/webhook_endpoints/__init__.py
@@ -134,6 +139,7 @@ setup.cfg
134
139
  ./tests/test_response_services.py
135
140
  ./tests/test_subscription_client.py
136
141
  ./tests/test_tax_client.py
142
+ ./tests/test_usage_client.py
137
143
  ./tests/test_wallet_client.py
138
144
  ./tests/test_wallet_transaction_client.py
139
145
  ./tests/test_webhook_client.py
@@ -193,6 +199,7 @@ lago_python_client/models/coupon.py
193
199
  lago_python_client/models/credit.py
194
200
  lago_python_client/models/credit_note.py
195
201
  lago_python_client/models/customer.py
202
+ lago_python_client/models/customer_projected_usage.py
196
203
  lago_python_client/models/customer_usage.py
197
204
  lago_python_client/models/error_detail.py
198
205
  lago_python_client/models/event.py
@@ -200,6 +207,7 @@ lago_python_client/models/fee.py
200
207
  lago_python_client/models/gross_revenue.py
201
208
  lago_python_client/models/invoice.py
202
209
  lago_python_client/models/invoice_collection.py
210
+ lago_python_client/models/invoice_custom_section.py
203
211
  lago_python_client/models/invoice_item.py
204
212
  lago_python_client/models/invoiced_usage.py
205
213
  lago_python_client/models/lifetime_usage.py
@@ -213,6 +221,7 @@ lago_python_client/models/payment_request.py
213
221
  lago_python_client/models/plan.py
214
222
  lago_python_client/models/subscription.py
215
223
  lago_python_client/models/tax.py
224
+ lago_python_client/models/usage.py
216
225
  lago_python_client/models/usage_threshold.py
217
226
  lago_python_client/models/wallet.py
218
227
  lago_python_client/models/wallet_transaction.py
@@ -239,6 +248,8 @@ lago_python_client/subscriptions/__init__.py
239
248
  lago_python_client/subscriptions/clients.py
240
249
  lago_python_client/taxes/__init__.py
241
250
  lago_python_client/taxes/clients.py
251
+ lago_python_client/usages/__init__.py
252
+ lago_python_client/usages/clients.py
242
253
  lago_python_client/wallets/__init__.py
243
254
  lago_python_client/wallets/clients.py
244
255
  lago_python_client/webhook_endpoints/__init__.py
@@ -275,6 +286,7 @@ tests/test_request_services.py
275
286
  tests/test_response_services.py
276
287
  tests/test_subscription_client.py
277
288
  tests/test_tax_client.py
289
+ tests/test_usage_client.py
278
290
  tests/test_wallet_client.py
279
291
  tests/test_wallet_transaction_client.py
280
292
  tests/test_webhook_client.py
@@ -2,7 +2,7 @@ classes~=0.4.1
2
2
  httpx<1.0.0,>=0.24.0
3
3
  orjson~=3.8
4
4
  pydantic<3,>=1.10
5
- typeguard~=3.0.2
5
+ typeguard~=4.0
6
6
 
7
7
  [lint]
8
8
  ruff
@@ -31,7 +31,7 @@ install_requires =
31
31
  httpx>=0.24.0,<1.0.0 # minor auto updates allowed
32
32
  orjson~=3.8 # minor auto updates allowed
33
33
  pydantic>=1.10,<3 # minor auto updates allowed
34
- typeguard~=3.0.2 # bugfix auto updates allowed
34
+ typeguard~=4.0 # bugfix auto updates allowed
35
35
 
36
36
  [options.extras_require]
37
37
  test =
File without changes
@@ -77,6 +77,7 @@ def update_billing_entity_input():
77
77
  invoice_grace_period=5,
78
78
  document_locale="fr",
79
79
  ),
80
+ invoice_custom_section_codes=["custom_section_1", "custom_section_2"],
80
81
  )
81
82
 
82
83
 
@@ -95,6 +95,7 @@ def test_valid_create_customers_request(httpx_mock: HTTPXMock):
95
95
  assert response.shipping_address.state == "XZ"
96
96
  assert response.integration_customers.__root__[0].external_customer_id == "test-12345"
97
97
  assert response.integration_customers.__root__[0].type == "netsuite"
98
+ assert response.applicable_invoice_custom_sections.__root__[0].code == "custom_section_code"
98
99
  assert response.metadata.__root__[0].lago_id == "12345"
99
100
  assert response.metadata.__root__[0].key == "key"
100
101
  assert response.metadata.__root__[0].value == "value"
@@ -126,11 +127,34 @@ def test_valid_current_usage(httpx_mock: HTTPXMock):
126
127
 
127
128
  assert response.from_datetime == "2022-07-01T00:00:00Z"
128
129
  assert len(response.charges_usage) == 1
129
- assert response.charges_usage[0].units == 1.0
130
+ assert response.charges_usage[0].units == "1.0"
130
131
  assert len(response.charges_usage[0].filters) == 1
131
132
  assert response.charges_usage[0].filters[0].values["country"] == ["france"]
132
133
 
133
134
 
135
+ def test_valid_projected_usage(httpx_mock: HTTPXMock):
136
+ client = Client(api_key="886fe239-927d-4072-ab72-6dd345e8dd0d")
137
+
138
+ httpx_mock.add_response(
139
+ method="GET",
140
+ url="https://api.getlago.com/api/v1/customers/external_customer_id/projected_usage?external_subscription_id=123",
141
+ content=mock_response("customer_projected_usage"),
142
+ )
143
+ response = client.customers.projected_usage("external_customer_id", "123")
144
+
145
+ assert response.from_datetime == "2022-07-01T00:00:00Z"
146
+ assert len(response.charges_usage) == 1
147
+ assert response.charges_usage[0].units == "1.0"
148
+ assert response.charges_usage[0].projected_units == "2.0"
149
+ assert response.charges_usage[0].amount_cents == 123
150
+ assert response.charges_usage[0].projected_amount_cents == 256
151
+ assert response.charges_usage[0].amount_currency == "EUR"
152
+ assert response.charges_usage[0].charge.lago_id == "5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba"
153
+ assert response.charges_usage[0].charge.charge_model == "graduated"
154
+ assert response.charges_usage[0].charge.invoice_display_name == "add_on_invoice_display_name"
155
+ assert response.charges_usage[0].billable_metric.lago_id == "99a6094e-199b-4101-896a-54e927ce7bd7"
156
+
157
+
134
158
  def test_valid_current_usage_without_taxes(httpx_mock: HTTPXMock):
135
159
  client = Client(api_key="886fe239-927d-4072-ab72-6dd345e8dd0d")
136
160
 
@@ -143,7 +167,7 @@ def test_valid_current_usage_without_taxes(httpx_mock: HTTPXMock):
143
167
 
144
168
  assert response.from_datetime == "2022-07-01T00:00:00Z"
145
169
  assert len(response.charges_usage) == 1
146
- assert response.charges_usage[0].units == 1.0
170
+ assert response.charges_usage[0].units == "1.0"
147
171
  assert len(response.charges_usage[0].filters) == 1
148
172
  assert response.charges_usage[0].filters[0].values["country"] == ["france"]
149
173
 
@@ -175,7 +199,7 @@ def test_valid_past_usage(httpx_mock: HTTPXMock):
175
199
  assert len(response["usage_periods"]) == 1
176
200
  assert response["usage_periods"][0].from_datetime == "2022-07-01T00:00:00Z"
177
201
  assert len(response["usage_periods"][0].charges_usage) == 1
178
- assert response["usage_periods"][0].charges_usage[0].units == 1.0
202
+ assert response["usage_periods"][0].charges_usage[0].units == "1.0"
179
203
  assert len(response["usage_periods"][0].charges_usage[0].filters) == 1
180
204
 
181
205
 
@@ -32,6 +32,37 @@ def mock_collection_response():
32
32
  return payment_requests_response.read()
33
33
 
34
34
 
35
+ def test_valid_find_payment_request_request(httpx_mock: HTTPXMock):
36
+ client = Client(api_key="886fe239-927d-4072-ab72-6dd345e8dd0d")
37
+ payment_request_id = "89b6b61e-4dbc-4307-ac96-4abcfa9e3e2d"
38
+
39
+ httpx_mock.add_response(
40
+ method="GET",
41
+ url="https://api.getlago.com/api/v1/payment_requests/" + payment_request_id,
42
+ content=mock_response(),
43
+ )
44
+ response = client.payment_requests.find(payment_request_id)
45
+
46
+ assert response.lago_id == "89b6b61e-4dbc-4307-ac96-4abcfa9e3e2d"
47
+ assert response.amount_cents == 19955
48
+ assert response.amount_currency == "EUR"
49
+
50
+
51
+ def test_invalid_find_payment_request_request(httpx_mock: HTTPXMock):
52
+ client = Client(api_key="886fe239-927d-4072-ab72-6dd345e8dd0d")
53
+ payment_request_id = "invalid"
54
+
55
+ httpx_mock.add_response(
56
+ method="GET",
57
+ url="https://api.getlago.com/api/v1/payment_requests/" + payment_request_id,
58
+ status_code=404,
59
+ content=b"",
60
+ )
61
+
62
+ with pytest.raises(LagoApiError):
63
+ client.payment_requests.find(payment_request_id)
64
+
65
+
35
66
  def test_valid_find_all_payment_requests_request(httpx_mock: HTTPXMock):
36
67
  client = Client(api_key="886fe239-927d-4072-ab72-6dd345e8dd0d")
37
68