billkit-sdk 0.0.6__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 (149) hide show
  1. billkit/__init__.py +329 -0
  2. billkit/_default_clients.py +30 -0
  3. billkit/addons/__init__.py +4 -0
  4. billkit/addons/client.py +245 -0
  5. billkit/addons/raw_client.py +446 -0
  6. billkit/api_keys/__init__.py +4 -0
  7. billkit/api_keys/client.py +342 -0
  8. billkit/api_keys/raw_client.py +643 -0
  9. billkit/assignments/__init__.py +4 -0
  10. billkit/assignments/client.py +231 -0
  11. billkit/assignments/raw_client.py +414 -0
  12. billkit/billing/__init__.py +4 -0
  13. billkit/billing/client.py +409 -0
  14. billkit/billing/raw_client.py +729 -0
  15. billkit/client.py +409 -0
  16. billkit/contracts/__init__.py +4 -0
  17. billkit/contracts/client.py +235 -0
  18. billkit/contracts/raw_client.py +440 -0
  19. billkit/core/__init__.py +127 -0
  20. billkit/core/api_error.py +23 -0
  21. billkit/core/client_wrapper.py +141 -0
  22. billkit/core/datetime_utils.py +70 -0
  23. billkit/core/file.py +67 -0
  24. billkit/core/force_multipart.py +18 -0
  25. billkit/core/http_client.py +940 -0
  26. billkit/core/http_response.py +59 -0
  27. billkit/core/http_sse/__init__.py +42 -0
  28. billkit/core/http_sse/_api.py +455 -0
  29. billkit/core/http_sse/_decoders.py +74 -0
  30. billkit/core/http_sse/_exceptions.py +7 -0
  31. billkit/core/http_sse/_models.py +17 -0
  32. billkit/core/jsonable_encoder.py +133 -0
  33. billkit/core/logging.py +107 -0
  34. billkit/core/parse_error.py +36 -0
  35. billkit/core/pydantic_utilities.py +508 -0
  36. billkit/core/query_encoder.py +58 -0
  37. billkit/core/remove_none_from_dict.py +11 -0
  38. billkit/core/request_options.py +40 -0
  39. billkit/core/serialization.py +347 -0
  40. billkit/entitlements/__init__.py +4 -0
  41. billkit/entitlements/client.py +143 -0
  42. billkit/entitlements/raw_client.py +307 -0
  43. billkit/errors/__init__.py +68 -0
  44. billkit/errors/bad_gateway_error.py +10 -0
  45. billkit/errors/bad_request_error.py +10 -0
  46. billkit/errors/conflict_error.py +10 -0
  47. billkit/errors/forbidden_error.py +10 -0
  48. billkit/errors/internal_server_error.py +10 -0
  49. billkit/errors/not_found_error.py +10 -0
  50. billkit/errors/payment_required_error.py +10 -0
  51. billkit/errors/service_unavailable_error.py +10 -0
  52. billkit/errors/too_many_requests_error.py +10 -0
  53. billkit/errors/unauthorized_error.py +10 -0
  54. billkit/errors/unprocessable_entity_error.py +10 -0
  55. billkit/invoices/__init__.py +4 -0
  56. billkit/invoices/client.py +552 -0
  57. billkit/invoices/raw_client.py +925 -0
  58. billkit/pricing/__init__.py +4 -0
  59. billkit/pricing/client.py +120 -0
  60. billkit/pricing/raw_client.py +188 -0
  61. billkit/py.typed +0 -0
  62. billkit/schema/__init__.py +34 -0
  63. billkit/schema/client.py +352 -0
  64. billkit/schema/raw_client.py +607 -0
  65. billkit/schema/types/__init__.py +38 -0
  66. billkit/schema/types/get_schema_request_format.py +5 -0
  67. billkit/schema/types/validate_schema_request_format.py +5 -0
  68. billkit/subjects/__init__.py +4 -0
  69. billkit/subjects/client.py +469 -0
  70. billkit/subjects/raw_client.py +796 -0
  71. billkit/tenants/__init__.py +4 -0
  72. billkit/tenants/client.py +130 -0
  73. billkit/tenants/raw_client.py +200 -0
  74. billkit/types/__init__.py +236 -0
  75. billkit/types/addon_definition.py +26 -0
  76. billkit/types/addon_type.py +5 -0
  77. billkit/types/apply_contract_response.py +24 -0
  78. billkit/types/attach_addon_response.py +25 -0
  79. billkit/types/attribute_data_type.py +5 -0
  80. billkit/types/batch_register_response.py +24 -0
  81. billkit/types/batch_subject_result.py +26 -0
  82. billkit/types/billing_config.py +47 -0
  83. billkit/types/billing_cycle.py +5 -0
  84. billkit/types/cadence.py +5 -0
  85. billkit/types/change_plan_response.py +51 -0
  86. billkit/types/contract_definition.py +25 -0
  87. billkit/types/create_assignment_response.py +25 -0
  88. billkit/types/create_key_response.py +28 -0
  89. billkit/types/create_portal_token_response.py +36 -0
  90. billkit/types/decision.py +5 -0
  91. billkit/types/feature_definition.py +26 -0
  92. billkit/types/feature_type.py +5 -0
  93. billkit/types/feature_usage.py +63 -0
  94. billkit/types/feature_value.py +27 -0
  95. billkit/types/gate_response.py +27 -0
  96. billkit/types/invoice_failure_item.py +30 -0
  97. billkit/types/invoice_line_item_response.py +24 -0
  98. billkit/types/invoice_list_item.py +34 -0
  99. billkit/types/invoice_preview_response.py +31 -0
  100. billkit/types/key_list_item.py +31 -0
  101. billkit/types/limit.py +7 -0
  102. billkit/types/limit_definition.py +29 -0
  103. billkit/types/limit_one.py +5 -0
  104. billkit/types/list_invoice_failures_params.py +42 -0
  105. billkit/types/list_invoice_failures_response.py +33 -0
  106. billkit/types/list_invoices_params.py +54 -0
  107. billkit/types/list_invoices_response.py +33 -0
  108. billkit/types/list_keys_response.py +24 -0
  109. billkit/types/list_platform_invoices_response.py +27 -0
  110. billkit/types/monthly_revenue.py +41 -0
  111. billkit/types/overage_info.py +24 -0
  112. billkit/types/overage_policy.py +5 -0
  113. billkit/types/pagination_query.py +31 -0
  114. billkit/types/plan_definition.py +29 -0
  115. billkit/types/platform_invoice_item.py +46 -0
  116. billkit/types/portal_list_invoices_response.py +33 -0
  117. billkit/types/preview_overage_item.py +28 -0
  118. billkit/types/pricing_billing.py +24 -0
  119. billkit/types/pricing_feature.py +25 -0
  120. billkit/types/pricing_metadata.py +24 -0
  121. billkit/types/pricing_plan.py +28 -0
  122. billkit/types/pricing_response.py +32 -0
  123. billkit/types/rate_card_dimension.py +29 -0
  124. billkit/types/rate_card_response.py +24 -0
  125. billkit/types/register_subject_request.py +38 -0
  126. billkit/types/register_subject_response.py +28 -0
  127. billkit/types/revenue_response.py +43 -0
  128. billkit/types/revoke_key_response.py +23 -0
  129. billkit/types/rotate_key_response.py +24 -0
  130. billkit/types/schema_document.py +34 -0
  131. billkit/types/schema_format.py +5 -0
  132. billkit/types/set_usage_rejection.py +46 -0
  133. billkit/types/set_usage_response.py +41 -0
  134. billkit/types/subject_detail_response.py +32 -0
  135. billkit/types/subject_info.py +27 -0
  136. billkit/types/subjects_response.py +34 -0
  137. billkit/types/tenant_me_response.py +32 -0
  138. billkit/types/usage_response.py +39 -0
  139. billkit/types/validation_error.py +24 -0
  140. billkit/types/validation_error_response.py +27 -0
  141. billkit/types/validation_warning.py +24 -0
  142. billkit/usage/__init__.py +4 -0
  143. billkit/usage/client.py +252 -0
  144. billkit/usage/raw_client.py +412 -0
  145. billkit/version.py +3 -0
  146. billkit_sdk-0.0.6.dist-info/LICENSE +21 -0
  147. billkit_sdk-0.0.6.dist-info/METADATA +212 -0
  148. billkit_sdk-0.0.6.dist-info/RECORD +149 -0
  149. billkit_sdk-0.0.6.dist-info/WHEEL +4 -0
billkit/__init__.py ADDED
@@ -0,0 +1,329 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ # isort: skip_file
4
+
5
+ import typing
6
+ from importlib import import_module
7
+
8
+ if typing.TYPE_CHECKING:
9
+ from .types import (
10
+ AddonDefinition,
11
+ AddonType,
12
+ ApplyContractResponse,
13
+ AttachAddonResponse,
14
+ AttributeDataType,
15
+ BatchRegisterResponse,
16
+ BatchSubjectResult,
17
+ BillingConfig,
18
+ BillingCycle,
19
+ Cadence,
20
+ ChangePlanResponse,
21
+ ContractDefinition,
22
+ CreateAssignmentResponse,
23
+ CreateKeyResponse,
24
+ CreatePortalTokenResponse,
25
+ Decision,
26
+ FeatureDefinition,
27
+ FeatureType,
28
+ FeatureUsage,
29
+ FeatureValue,
30
+ GateResponse,
31
+ InvoiceFailureItem,
32
+ InvoiceLineItemResponse,
33
+ InvoiceListItem,
34
+ InvoicePreviewResponse,
35
+ KeyListItem,
36
+ Limit,
37
+ LimitDefinition,
38
+ LimitOne,
39
+ ListInvoiceFailuresParams,
40
+ ListInvoiceFailuresResponse,
41
+ ListInvoicesParams,
42
+ ListInvoicesResponse,
43
+ ListKeysResponse,
44
+ ListPlatformInvoicesResponse,
45
+ MonthlyRevenue,
46
+ OverageInfo,
47
+ OveragePolicy,
48
+ PaginationQuery,
49
+ PlanDefinition,
50
+ PlatformInvoiceItem,
51
+ PortalListInvoicesResponse,
52
+ PreviewOverageItem,
53
+ PricingBilling,
54
+ PricingFeature,
55
+ PricingMetadata,
56
+ PricingPlan,
57
+ PricingResponse,
58
+ RateCardDimension,
59
+ RateCardResponse,
60
+ RegisterSubjectRequest,
61
+ RegisterSubjectResponse,
62
+ RevenueResponse,
63
+ RevokeKeyResponse,
64
+ RotateKeyResponse,
65
+ SchemaDocument,
66
+ SchemaFormat,
67
+ SetUsageRejection,
68
+ SetUsageResponse,
69
+ SubjectDetailResponse,
70
+ SubjectInfo,
71
+ SubjectsResponse,
72
+ TenantMeResponse,
73
+ UsageResponse,
74
+ ValidationError,
75
+ ValidationErrorResponse,
76
+ ValidationWarning,
77
+ )
78
+ from .errors import (
79
+ BadGatewayError,
80
+ BadRequestError,
81
+ ConflictError,
82
+ ForbiddenError,
83
+ InternalServerError,
84
+ NotFoundError,
85
+ PaymentRequiredError,
86
+ ServiceUnavailableError,
87
+ TooManyRequestsError,
88
+ UnauthorizedError,
89
+ UnprocessableEntityError,
90
+ )
91
+ from . import (
92
+ addons,
93
+ api_keys,
94
+ assignments,
95
+ billing,
96
+ contracts,
97
+ entitlements,
98
+ invoices,
99
+ pricing,
100
+ schema,
101
+ subjects,
102
+ tenants,
103
+ usage,
104
+ )
105
+ from ._default_clients import DefaultAioHttpClient, DefaultAsyncHttpxClient
106
+ from .client import AsyncBillkitApi, BillkitApi
107
+ from .schema import GetSchemaRequestFormat, ValidateSchemaRequestFormat
108
+ from .version import __version__
109
+ _dynamic_imports: typing.Dict[str, str] = {
110
+ "AddonDefinition": ".types",
111
+ "AddonType": ".types",
112
+ "ApplyContractResponse": ".types",
113
+ "AsyncBillkitApi": ".client",
114
+ "AttachAddonResponse": ".types",
115
+ "AttributeDataType": ".types",
116
+ "BadGatewayError": ".errors",
117
+ "BadRequestError": ".errors",
118
+ "BatchRegisterResponse": ".types",
119
+ "BatchSubjectResult": ".types",
120
+ "BillingConfig": ".types",
121
+ "BillingCycle": ".types",
122
+ "BillkitApi": ".client",
123
+ "Cadence": ".types",
124
+ "ChangePlanResponse": ".types",
125
+ "ConflictError": ".errors",
126
+ "ContractDefinition": ".types",
127
+ "CreateAssignmentResponse": ".types",
128
+ "CreateKeyResponse": ".types",
129
+ "CreatePortalTokenResponse": ".types",
130
+ "Decision": ".types",
131
+ "DefaultAioHttpClient": "._default_clients",
132
+ "DefaultAsyncHttpxClient": "._default_clients",
133
+ "FeatureDefinition": ".types",
134
+ "FeatureType": ".types",
135
+ "FeatureUsage": ".types",
136
+ "FeatureValue": ".types",
137
+ "ForbiddenError": ".errors",
138
+ "GateResponse": ".types",
139
+ "GetSchemaRequestFormat": ".schema",
140
+ "InternalServerError": ".errors",
141
+ "InvoiceFailureItem": ".types",
142
+ "InvoiceLineItemResponse": ".types",
143
+ "InvoiceListItem": ".types",
144
+ "InvoicePreviewResponse": ".types",
145
+ "KeyListItem": ".types",
146
+ "Limit": ".types",
147
+ "LimitDefinition": ".types",
148
+ "LimitOne": ".types",
149
+ "ListInvoiceFailuresParams": ".types",
150
+ "ListInvoiceFailuresResponse": ".types",
151
+ "ListInvoicesParams": ".types",
152
+ "ListInvoicesResponse": ".types",
153
+ "ListKeysResponse": ".types",
154
+ "ListPlatformInvoicesResponse": ".types",
155
+ "MonthlyRevenue": ".types",
156
+ "NotFoundError": ".errors",
157
+ "OverageInfo": ".types",
158
+ "OveragePolicy": ".types",
159
+ "PaginationQuery": ".types",
160
+ "PaymentRequiredError": ".errors",
161
+ "PlanDefinition": ".types",
162
+ "PlatformInvoiceItem": ".types",
163
+ "PortalListInvoicesResponse": ".types",
164
+ "PreviewOverageItem": ".types",
165
+ "PricingBilling": ".types",
166
+ "PricingFeature": ".types",
167
+ "PricingMetadata": ".types",
168
+ "PricingPlan": ".types",
169
+ "PricingResponse": ".types",
170
+ "RateCardDimension": ".types",
171
+ "RateCardResponse": ".types",
172
+ "RegisterSubjectRequest": ".types",
173
+ "RegisterSubjectResponse": ".types",
174
+ "RevenueResponse": ".types",
175
+ "RevokeKeyResponse": ".types",
176
+ "RotateKeyResponse": ".types",
177
+ "SchemaDocument": ".types",
178
+ "SchemaFormat": ".types",
179
+ "ServiceUnavailableError": ".errors",
180
+ "SetUsageRejection": ".types",
181
+ "SetUsageResponse": ".types",
182
+ "SubjectDetailResponse": ".types",
183
+ "SubjectInfo": ".types",
184
+ "SubjectsResponse": ".types",
185
+ "TenantMeResponse": ".types",
186
+ "TooManyRequestsError": ".errors",
187
+ "UnauthorizedError": ".errors",
188
+ "UnprocessableEntityError": ".errors",
189
+ "UsageResponse": ".types",
190
+ "ValidateSchemaRequestFormat": ".schema",
191
+ "ValidationError": ".types",
192
+ "ValidationErrorResponse": ".types",
193
+ "ValidationWarning": ".types",
194
+ "__version__": ".version",
195
+ "addons": ".addons",
196
+ "api_keys": ".api_keys",
197
+ "assignments": ".assignments",
198
+ "billing": ".billing",
199
+ "contracts": ".contracts",
200
+ "entitlements": ".entitlements",
201
+ "invoices": ".invoices",
202
+ "pricing": ".pricing",
203
+ "schema": ".schema",
204
+ "subjects": ".subjects",
205
+ "tenants": ".tenants",
206
+ "usage": ".usage",
207
+ }
208
+
209
+
210
+ def __getattr__(attr_name: str) -> typing.Any:
211
+ module_name = _dynamic_imports.get(attr_name)
212
+ if module_name is None:
213
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
214
+ try:
215
+ module = import_module(module_name, __package__)
216
+ if module_name == f".{attr_name}":
217
+ return module
218
+ else:
219
+ return getattr(module, attr_name)
220
+ except ImportError as e:
221
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
222
+ except AttributeError as e:
223
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
224
+
225
+
226
+ def __dir__():
227
+ lazy_attrs = list(_dynamic_imports.keys())
228
+ return sorted(lazy_attrs)
229
+
230
+
231
+ __all__ = [
232
+ "AddonDefinition",
233
+ "AddonType",
234
+ "ApplyContractResponse",
235
+ "AsyncBillkitApi",
236
+ "AttachAddonResponse",
237
+ "AttributeDataType",
238
+ "BadGatewayError",
239
+ "BadRequestError",
240
+ "BatchRegisterResponse",
241
+ "BatchSubjectResult",
242
+ "BillingConfig",
243
+ "BillingCycle",
244
+ "BillkitApi",
245
+ "Cadence",
246
+ "ChangePlanResponse",
247
+ "ConflictError",
248
+ "ContractDefinition",
249
+ "CreateAssignmentResponse",
250
+ "CreateKeyResponse",
251
+ "CreatePortalTokenResponse",
252
+ "Decision",
253
+ "DefaultAioHttpClient",
254
+ "DefaultAsyncHttpxClient",
255
+ "FeatureDefinition",
256
+ "FeatureType",
257
+ "FeatureUsage",
258
+ "FeatureValue",
259
+ "ForbiddenError",
260
+ "GateResponse",
261
+ "GetSchemaRequestFormat",
262
+ "InternalServerError",
263
+ "InvoiceFailureItem",
264
+ "InvoiceLineItemResponse",
265
+ "InvoiceListItem",
266
+ "InvoicePreviewResponse",
267
+ "KeyListItem",
268
+ "Limit",
269
+ "LimitDefinition",
270
+ "LimitOne",
271
+ "ListInvoiceFailuresParams",
272
+ "ListInvoiceFailuresResponse",
273
+ "ListInvoicesParams",
274
+ "ListInvoicesResponse",
275
+ "ListKeysResponse",
276
+ "ListPlatformInvoicesResponse",
277
+ "MonthlyRevenue",
278
+ "NotFoundError",
279
+ "OverageInfo",
280
+ "OveragePolicy",
281
+ "PaginationQuery",
282
+ "PaymentRequiredError",
283
+ "PlanDefinition",
284
+ "PlatformInvoiceItem",
285
+ "PortalListInvoicesResponse",
286
+ "PreviewOverageItem",
287
+ "PricingBilling",
288
+ "PricingFeature",
289
+ "PricingMetadata",
290
+ "PricingPlan",
291
+ "PricingResponse",
292
+ "RateCardDimension",
293
+ "RateCardResponse",
294
+ "RegisterSubjectRequest",
295
+ "RegisterSubjectResponse",
296
+ "RevenueResponse",
297
+ "RevokeKeyResponse",
298
+ "RotateKeyResponse",
299
+ "SchemaDocument",
300
+ "SchemaFormat",
301
+ "ServiceUnavailableError",
302
+ "SetUsageRejection",
303
+ "SetUsageResponse",
304
+ "SubjectDetailResponse",
305
+ "SubjectInfo",
306
+ "SubjectsResponse",
307
+ "TenantMeResponse",
308
+ "TooManyRequestsError",
309
+ "UnauthorizedError",
310
+ "UnprocessableEntityError",
311
+ "UsageResponse",
312
+ "ValidateSchemaRequestFormat",
313
+ "ValidationError",
314
+ "ValidationErrorResponse",
315
+ "ValidationWarning",
316
+ "__version__",
317
+ "addons",
318
+ "api_keys",
319
+ "assignments",
320
+ "billing",
321
+ "contracts",
322
+ "entitlements",
323
+ "invoices",
324
+ "pricing",
325
+ "schema",
326
+ "subjects",
327
+ "tenants",
328
+ "usage",
329
+ ]
@@ -0,0 +1,30 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ import typing
4
+
5
+ import httpx
6
+
7
+ SDK_DEFAULT_TIMEOUT = 60
8
+
9
+ try:
10
+ import httpx_aiohttp # type: ignore[import-not-found]
11
+ except ImportError:
12
+
13
+ class DefaultAioHttpClient(httpx.AsyncClient): # type: ignore
14
+ def __init__(self, **kwargs: typing.Any) -> None:
15
+ raise RuntimeError("To use the aiohttp client, install the aiohttp extra: pip install billkit-sdk[aiohttp]")
16
+
17
+ else:
18
+
19
+ class DefaultAioHttpClient(httpx_aiohttp.HttpxAiohttpClient): # type: ignore
20
+ def __init__(self, **kwargs: typing.Any) -> None:
21
+ kwargs.setdefault("timeout", SDK_DEFAULT_TIMEOUT)
22
+ kwargs.setdefault("follow_redirects", True)
23
+ super().__init__(**kwargs)
24
+
25
+
26
+ class DefaultAsyncHttpxClient(httpx.AsyncClient):
27
+ def __init__(self, **kwargs: typing.Any) -> None:
28
+ kwargs.setdefault("timeout", SDK_DEFAULT_TIMEOUT)
29
+ kwargs.setdefault("follow_redirects", True)
30
+ super().__init__(**kwargs)
@@ -0,0 +1,4 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ # isort: skip_file
4
+
@@ -0,0 +1,245 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ import typing
4
+
5
+ from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
6
+ from ..core.request_options import RequestOptions
7
+ from ..types.attach_addon_response import AttachAddonResponse
8
+ from .raw_client import AsyncRawAddonsClient, RawAddonsClient
9
+
10
+ # this is used as the default value for optional parameters
11
+ OMIT = typing.cast(typing.Any, ...)
12
+
13
+
14
+ class AddonsClient:
15
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
16
+ self._raw_client = RawAddonsClient(client_wrapper=client_wrapper)
17
+
18
+ @property
19
+ def with_raw_response(self) -> RawAddonsClient:
20
+ """
21
+ Retrieves a raw implementation of this client that returns raw responses.
22
+
23
+ Returns
24
+ -------
25
+ RawAddonsClient
26
+ """
27
+ return self._raw_client
28
+
29
+ def attach_addon(
30
+ self, *, addon_key: str, subject_id: str, request_options: typing.Optional[RequestOptions] = None
31
+ ) -> AttachAddonResponse:
32
+ """
33
+ Validates that the add-on key exists in the tenant's schema, attaches it to
34
+ the subject's existing assignment in the store, and invalidates the subject's
35
+ cache entries.
36
+
37
+ - If the request body is missing or malformed: returns 400 (via Axum rejection).
38
+ - If subject_id or addon_key is empty: returns 400.
39
+ - If the tenant has no schema uploaded: returns 422.
40
+ - If the add-on key does not exist in the schema: returns 422.
41
+ - If the subject has no existing assignment: returns 404.
42
+ - If a store or cache error occurs: returns 500.
43
+ - On success: returns 200 with the updated add-on list.
44
+
45
+ Parameters
46
+ ----------
47
+ addon_key : str
48
+
49
+ subject_id : str
50
+
51
+ request_options : typing.Optional[RequestOptions]
52
+ Request-specific configuration.
53
+
54
+ Returns
55
+ -------
56
+ AttachAddonResponse
57
+ Add-on attached
58
+
59
+ Examples
60
+ --------
61
+ from billkit import BillkitApi
62
+
63
+ client = BillkitApi(
64
+ api_key="YOUR_API_KEY",
65
+ base_url="https://yourhost.com/path/to/api",
66
+ )
67
+ client.addons.attach_addon(
68
+ addon_key="addon_key",
69
+ subject_id="subject_id",
70
+ )
71
+ """
72
+ _response = self._raw_client.attach_addon(
73
+ addon_key=addon_key, subject_id=subject_id, request_options=request_options
74
+ )
75
+ return _response.data
76
+
77
+ def detach_addon(
78
+ self, subject_id: str, addon_key: str, *, request_options: typing.Optional[RequestOptions] = None
79
+ ) -> None:
80
+ """
81
+ Removes the given add-on from the subject's existing assignment in the store
82
+ and invalidates the subject's cache entries. Tenant is resolved from
83
+ `X-Api-Key` via the auth middleware.
84
+
85
+ - If subject_id or addon_key is empty: returns 400.
86
+ - If the subject has no existing assignment: returns 404.
87
+ - If a store error occurs: returns 500.
88
+ - On success: returns 204 No Content, whether or not the add-on was
89
+ actually attached (idempotent, matching `DELETE /assignments/{subject_id}`).
90
+
91
+ Parameters
92
+ ----------
93
+ subject_id : str
94
+ The subject identifier
95
+
96
+ addon_key : str
97
+ The add-on key to detach
98
+
99
+ request_options : typing.Optional[RequestOptions]
100
+ Request-specific configuration.
101
+
102
+ Returns
103
+ -------
104
+ None
105
+
106
+ Examples
107
+ --------
108
+ from billkit import BillkitApi
109
+
110
+ client = BillkitApi(
111
+ api_key="YOUR_API_KEY",
112
+ base_url="https://yourhost.com/path/to/api",
113
+ )
114
+ client.addons.detach_addon(
115
+ subject_id="subject_id",
116
+ addon_key="addon_key",
117
+ )
118
+ """
119
+ _response = self._raw_client.detach_addon(subject_id, addon_key, request_options=request_options)
120
+ return _response.data
121
+
122
+
123
+ class AsyncAddonsClient:
124
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
125
+ self._raw_client = AsyncRawAddonsClient(client_wrapper=client_wrapper)
126
+
127
+ @property
128
+ def with_raw_response(self) -> AsyncRawAddonsClient:
129
+ """
130
+ Retrieves a raw implementation of this client that returns raw responses.
131
+
132
+ Returns
133
+ -------
134
+ AsyncRawAddonsClient
135
+ """
136
+ return self._raw_client
137
+
138
+ async def attach_addon(
139
+ self, *, addon_key: str, subject_id: str, request_options: typing.Optional[RequestOptions] = None
140
+ ) -> AttachAddonResponse:
141
+ """
142
+ Validates that the add-on key exists in the tenant's schema, attaches it to
143
+ the subject's existing assignment in the store, and invalidates the subject's
144
+ cache entries.
145
+
146
+ - If the request body is missing or malformed: returns 400 (via Axum rejection).
147
+ - If subject_id or addon_key is empty: returns 400.
148
+ - If the tenant has no schema uploaded: returns 422.
149
+ - If the add-on key does not exist in the schema: returns 422.
150
+ - If the subject has no existing assignment: returns 404.
151
+ - If a store or cache error occurs: returns 500.
152
+ - On success: returns 200 with the updated add-on list.
153
+
154
+ Parameters
155
+ ----------
156
+ addon_key : str
157
+
158
+ subject_id : str
159
+
160
+ request_options : typing.Optional[RequestOptions]
161
+ Request-specific configuration.
162
+
163
+ Returns
164
+ -------
165
+ AttachAddonResponse
166
+ Add-on attached
167
+
168
+ Examples
169
+ --------
170
+ import asyncio
171
+
172
+ from billkit import AsyncBillkitApi
173
+
174
+ client = AsyncBillkitApi(
175
+ api_key="YOUR_API_KEY",
176
+ base_url="https://yourhost.com/path/to/api",
177
+ )
178
+
179
+
180
+ async def main() -> None:
181
+ await client.addons.attach_addon(
182
+ addon_key="addon_key",
183
+ subject_id="subject_id",
184
+ )
185
+
186
+
187
+ asyncio.run(main())
188
+ """
189
+ _response = await self._raw_client.attach_addon(
190
+ addon_key=addon_key, subject_id=subject_id, request_options=request_options
191
+ )
192
+ return _response.data
193
+
194
+ async def detach_addon(
195
+ self, subject_id: str, addon_key: str, *, request_options: typing.Optional[RequestOptions] = None
196
+ ) -> None:
197
+ """
198
+ Removes the given add-on from the subject's existing assignment in the store
199
+ and invalidates the subject's cache entries. Tenant is resolved from
200
+ `X-Api-Key` via the auth middleware.
201
+
202
+ - If subject_id or addon_key is empty: returns 400.
203
+ - If the subject has no existing assignment: returns 404.
204
+ - If a store error occurs: returns 500.
205
+ - On success: returns 204 No Content, whether or not the add-on was
206
+ actually attached (idempotent, matching `DELETE /assignments/{subject_id}`).
207
+
208
+ Parameters
209
+ ----------
210
+ subject_id : str
211
+ The subject identifier
212
+
213
+ addon_key : str
214
+ The add-on key to detach
215
+
216
+ request_options : typing.Optional[RequestOptions]
217
+ Request-specific configuration.
218
+
219
+ Returns
220
+ -------
221
+ None
222
+
223
+ Examples
224
+ --------
225
+ import asyncio
226
+
227
+ from billkit import AsyncBillkitApi
228
+
229
+ client = AsyncBillkitApi(
230
+ api_key="YOUR_API_KEY",
231
+ base_url="https://yourhost.com/path/to/api",
232
+ )
233
+
234
+
235
+ async def main() -> None:
236
+ await client.addons.detach_addon(
237
+ subject_id="subject_id",
238
+ addon_key="addon_key",
239
+ )
240
+
241
+
242
+ asyncio.run(main())
243
+ """
244
+ _response = await self._raw_client.detach_addon(subject_id, addon_key, request_options=request_options)
245
+ return _response.data