dodopayments 1.51.0__py3-none-any.whl → 1.52.4__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.

Potentially problematic release.


This version of dodopayments might be problematic. Click here for more details.

Files changed (43) hide show
  1. dodopayments/_client.py +18 -0
  2. dodopayments/_models.py +1 -1
  3. dodopayments/_types.py +35 -1
  4. dodopayments/_utils/__init__.py +1 -0
  5. dodopayments/_utils/_transform.py +6 -0
  6. dodopayments/_utils/_typing.py +5 -0
  7. dodopayments/_version.py +1 -1
  8. dodopayments/resources/__init__.py +28 -0
  9. dodopayments/resources/discounts.py +6 -6
  10. dodopayments/resources/invoices/payments.py +80 -0
  11. dodopayments/resources/meters.py +554 -0
  12. dodopayments/resources/products/products.py +16 -16
  13. dodopayments/resources/subscriptions.py +223 -0
  14. dodopayments/resources/usage_events.py +597 -0
  15. dodopayments/types/__init__.py +20 -0
  16. dodopayments/types/add_meter_to_price.py +29 -0
  17. dodopayments/types/add_meter_to_price_param.py +30 -0
  18. dodopayments/types/discount_create_params.py +3 -2
  19. dodopayments/types/discount_update_params.py +3 -2
  20. dodopayments/types/event.py +26 -0
  21. dodopayments/types/event_input_param.py +38 -0
  22. dodopayments/types/meter.py +40 -0
  23. dodopayments/types/meter_aggregation.py +16 -0
  24. dodopayments/types/meter_aggregation_param.py +16 -0
  25. dodopayments/types/meter_create_params.py +31 -0
  26. dodopayments/types/meter_filter.py +131 -0
  27. dodopayments/types/meter_filter_param.py +143 -0
  28. dodopayments/types/meter_list_params.py +18 -0
  29. dodopayments/types/payment.py +6 -0
  30. dodopayments/types/price.py +52 -5
  31. dodopayments/types/price_param.py +52 -5
  32. dodopayments/types/product_create_params.py +3 -2
  33. dodopayments/types/product_update_params.py +4 -3
  34. dodopayments/types/subscription.py +20 -1
  35. dodopayments/types/subscription_retrieve_usage_history_params.py +28 -0
  36. dodopayments/types/subscription_retrieve_usage_history_response.py +46 -0
  37. dodopayments/types/usage_event_ingest_params.py +15 -0
  38. dodopayments/types/usage_event_ingest_response.py +9 -0
  39. dodopayments/types/usage_event_list_params.py +42 -0
  40. {dodopayments-1.51.0.dist-info → dodopayments-1.52.4.dist-info}/METADATA +1 -1
  41. {dodopayments-1.51.0.dist-info → dodopayments-1.52.4.dist-info}/RECORD +43 -25
  42. {dodopayments-1.51.0.dist-info → dodopayments-1.52.4.dist-info}/WHEEL +0 -0
  43. {dodopayments-1.51.0.dist-info → dodopayments-1.52.4.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,30 @@
1
+ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Optional
6
+ from typing_extensions import Required, TypedDict
7
+
8
+ __all__ = ["AddMeterToPriceParam"]
9
+
10
+
11
+ class AddMeterToPriceParam(TypedDict, total=False):
12
+ meter_id: Required[str]
13
+
14
+ price_per_unit: Required[str]
15
+ """The price per unit in lowest denomination.
16
+
17
+ Must be greater than zero. Supports up to 5 digits before decimal point and 12
18
+ decimal places.
19
+ """
20
+
21
+ description: Optional[str]
22
+ """Meter description. Will ignored on Request, but will be shown in response"""
23
+
24
+ free_threshold: Optional[int]
25
+
26
+ measurement_unit: Optional[str]
27
+ """Meter measurement unit. Will ignored on Request, but will be shown in response"""
28
+
29
+ name: Optional[str]
30
+ """Meter name. Will ignored on Request, but will be shown in response"""
@@ -2,10 +2,11 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import List, Union, Optional
5
+ from typing import Union, Optional
6
6
  from datetime import datetime
7
7
  from typing_extensions import Required, Annotated, TypedDict
8
8
 
9
+ from .._types import SequenceNotStr
9
10
  from .._utils import PropertyInfo
10
11
  from .discount_type import DiscountType
11
12
 
@@ -39,7 +40,7 @@ class DiscountCreateParams(TypedDict, total=False):
39
40
 
40
41
  name: Optional[str]
41
42
 
42
- restricted_to: Optional[List[str]]
43
+ restricted_to: Optional[SequenceNotStr[str]]
43
44
  """List of product IDs to restrict usage (if any)."""
44
45
 
45
46
  subscription_cycles: Optional[int]
@@ -2,10 +2,11 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import List, Union, Optional
5
+ from typing import Union, Optional
6
6
  from datetime import datetime
7
7
  from typing_extensions import Annotated, TypedDict
8
8
 
9
+ from .._types import SequenceNotStr
9
10
  from .._utils import PropertyInfo
10
11
  from .discount_type import DiscountType
11
12
 
@@ -30,7 +31,7 @@ class DiscountUpdateParams(TypedDict, total=False):
30
31
 
31
32
  name: Optional[str]
32
33
 
33
- restricted_to: Optional[List[str]]
34
+ restricted_to: Optional[SequenceNotStr[str]]
34
35
  """
35
36
  If present, replaces all restricted product IDs with this new set. To remove all
36
37
  restrictions, send empty array
@@ -0,0 +1,26 @@
1
+ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
+
3
+ from typing import Dict, Union, Optional
4
+ from datetime import datetime
5
+
6
+ from .._models import BaseModel
7
+
8
+ __all__ = ["Event"]
9
+
10
+
11
+ class Event(BaseModel):
12
+ business_id: str
13
+
14
+ customer_id: str
15
+
16
+ event_id: str
17
+
18
+ event_name: str
19
+
20
+ timestamp: datetime
21
+
22
+ metadata: Optional[Dict[str, Union[str, float, bool]]] = None
23
+ """Arbitrary key-value metadata.
24
+
25
+ Values can be string, integer, number, or boolean.
26
+ """
@@ -0,0 +1,38 @@
1
+ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Dict, Union, Optional
6
+ from datetime import datetime
7
+ from typing_extensions import Required, Annotated, TypedDict
8
+
9
+ from .._utils import PropertyInfo
10
+
11
+ __all__ = ["EventInputParam"]
12
+
13
+
14
+ class EventInputParam(TypedDict, total=False):
15
+ customer_id: Required[str]
16
+ """customer_id of the customer whose usage needs to be tracked"""
17
+
18
+ event_id: Required[str]
19
+ """Event Id acts as an idempotency key.
20
+
21
+ Any subsequent requests with the same event_id will be ignored
22
+ """
23
+
24
+ event_name: Required[str]
25
+ """Name of the event"""
26
+
27
+ metadata: Optional[Dict[str, Union[str, float, bool]]]
28
+ """Custom metadata.
29
+
30
+ Only key value pairs are accepted, objects or arrays submitted will be rejected.
31
+ """
32
+
33
+ timestamp: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")]
34
+ """Custom Timestamp.
35
+
36
+ Defaults to current timestamp in UTC. Timestamps that are older that 1 hour or
37
+ after 5 mins, from current timestamp, will be rejected.
38
+ """
@@ -0,0 +1,40 @@
1
+ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
+
3
+ from typing import Optional
4
+ from datetime import datetime
5
+
6
+ from .._models import BaseModel
7
+ from .meter_filter import MeterFilter
8
+ from .meter_aggregation import MeterAggregation
9
+
10
+ __all__ = ["Meter"]
11
+
12
+
13
+ class Meter(BaseModel):
14
+ id: str
15
+
16
+ aggregation: MeterAggregation
17
+
18
+ business_id: str
19
+
20
+ created_at: datetime
21
+
22
+ event_name: str
23
+
24
+ measurement_unit: str
25
+
26
+ name: str
27
+
28
+ updated_at: datetime
29
+
30
+ description: Optional[str] = None
31
+
32
+ filter: Optional[MeterFilter] = None
33
+ """
34
+ A filter structure that combines multiple conditions with logical conjunctions
35
+ (AND/OR).
36
+
37
+ Supports up to 3 levels of nesting to create complex filter expressions. Each
38
+ filter has a conjunction (and/or) and clauses that can be either direct
39
+ conditions or nested filters.
40
+ """
@@ -0,0 +1,16 @@
1
+ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
+
3
+ from typing import Optional
4
+ from typing_extensions import Literal
5
+
6
+ from .._models import BaseModel
7
+
8
+ __all__ = ["MeterAggregation"]
9
+
10
+
11
+ class MeterAggregation(BaseModel):
12
+ type: Literal["count", "sum", "max", "last"]
13
+ """Aggregation type for the meter"""
14
+
15
+ key: Optional[str] = None
16
+ """Required when type is not COUNT"""
@@ -0,0 +1,16 @@
1
+ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Optional
6
+ from typing_extensions import Literal, Required, TypedDict
7
+
8
+ __all__ = ["MeterAggregationParam"]
9
+
10
+
11
+ class MeterAggregationParam(TypedDict, total=False):
12
+ type: Required[Literal["count", "sum", "max", "last"]]
13
+ """Aggregation type for the meter"""
14
+
15
+ key: Optional[str]
16
+ """Required when type is not COUNT"""
@@ -0,0 +1,31 @@
1
+ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Optional
6
+ from typing_extensions import Required, TypedDict
7
+
8
+ from .meter_filter_param import MeterFilterParam
9
+ from .meter_aggregation_param import MeterAggregationParam
10
+
11
+ __all__ = ["MeterCreateParams"]
12
+
13
+
14
+ class MeterCreateParams(TypedDict, total=False):
15
+ aggregation: Required[MeterAggregationParam]
16
+ """Aggregation configuration for the meter"""
17
+
18
+ event_name: Required[str]
19
+ """Event name to track"""
20
+
21
+ measurement_unit: Required[str]
22
+ """measurement unit"""
23
+
24
+ name: Required[str]
25
+ """Name of the meter"""
26
+
27
+ description: Optional[str]
28
+ """Optional description of the meter"""
29
+
30
+ filter: Optional[MeterFilterParam]
31
+ """Optional filter to apply to the meter"""
@@ -0,0 +1,131 @@
1
+ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
+
3
+ from typing import List, Union
4
+ from typing_extensions import Literal
5
+
6
+ from .._models import BaseModel
7
+
8
+ __all__ = [
9
+ "MeterFilter",
10
+ "ClausesDirectFilterCondition",
11
+ "ClausesNestedMeterFilter",
12
+ "ClausesNestedMeterFilterClausesLevel1FilterCondition",
13
+ "ClausesNestedMeterFilterClausesLevel1NestedFilter",
14
+ "ClausesNestedMeterFilterClausesLevel1NestedFilterClausesLevel2FilterCondition",
15
+ "ClausesNestedMeterFilterClausesLevel1NestedFilterClausesLevel2NestedFilter",
16
+ "ClausesNestedMeterFilterClausesLevel1NestedFilterClausesLevel2NestedFilterClause",
17
+ ]
18
+
19
+
20
+ class ClausesDirectFilterCondition(BaseModel):
21
+ key: str
22
+ """Filter key to apply"""
23
+
24
+ operator: Literal[
25
+ "equals",
26
+ "not_equals",
27
+ "greater_than",
28
+ "greater_than_or_equals",
29
+ "less_than",
30
+ "less_than_or_equals",
31
+ "contains",
32
+ "does_not_contain",
33
+ ]
34
+
35
+ value: Union[str, float, bool]
36
+ """Filter value - can be string, number, or boolean"""
37
+
38
+
39
+ class ClausesNestedMeterFilterClausesLevel1FilterCondition(BaseModel):
40
+ key: str
41
+ """Filter key to apply"""
42
+
43
+ operator: Literal[
44
+ "equals",
45
+ "not_equals",
46
+ "greater_than",
47
+ "greater_than_or_equals",
48
+ "less_than",
49
+ "less_than_or_equals",
50
+ "contains",
51
+ "does_not_contain",
52
+ ]
53
+
54
+ value: Union[str, float, bool]
55
+ """Filter value - can be string, number, or boolean"""
56
+
57
+
58
+ class ClausesNestedMeterFilterClausesLevel1NestedFilterClausesLevel2FilterCondition(BaseModel):
59
+ key: str
60
+ """Filter key to apply"""
61
+
62
+ operator: Literal[
63
+ "equals",
64
+ "not_equals",
65
+ "greater_than",
66
+ "greater_than_or_equals",
67
+ "less_than",
68
+ "less_than_or_equals",
69
+ "contains",
70
+ "does_not_contain",
71
+ ]
72
+
73
+ value: Union[str, float, bool]
74
+ """Filter value - can be string, number, or boolean"""
75
+
76
+
77
+ class ClausesNestedMeterFilterClausesLevel1NestedFilterClausesLevel2NestedFilterClause(BaseModel):
78
+ key: str
79
+ """Filter key to apply"""
80
+
81
+ operator: Literal[
82
+ "equals",
83
+ "not_equals",
84
+ "greater_than",
85
+ "greater_than_or_equals",
86
+ "less_than",
87
+ "less_than_or_equals",
88
+ "contains",
89
+ "does_not_contain",
90
+ ]
91
+
92
+ value: Union[str, float, bool]
93
+ """Filter value - can be string, number, or boolean"""
94
+
95
+
96
+ class ClausesNestedMeterFilterClausesLevel1NestedFilterClausesLevel2NestedFilter(BaseModel):
97
+ clauses: List[ClausesNestedMeterFilterClausesLevel1NestedFilterClausesLevel2NestedFilterClause]
98
+ """Level 3: Filter conditions only (max depth reached)"""
99
+
100
+ conjunction: Literal["and", "or"]
101
+
102
+
103
+ class ClausesNestedMeterFilterClausesLevel1NestedFilter(BaseModel):
104
+ clauses: Union[
105
+ List[ClausesNestedMeterFilterClausesLevel1NestedFilterClausesLevel2FilterCondition],
106
+ List[ClausesNestedMeterFilterClausesLevel1NestedFilterClausesLevel2NestedFilter],
107
+ ]
108
+ """Level 2: Can be conditions or nested filters (1 more level allowed)"""
109
+
110
+ conjunction: Literal["and", "or"]
111
+
112
+
113
+ class ClausesNestedMeterFilter(BaseModel):
114
+ clauses: Union[
115
+ List[ClausesNestedMeterFilterClausesLevel1FilterCondition],
116
+ List[ClausesNestedMeterFilterClausesLevel1NestedFilter],
117
+ ]
118
+ """Level 1: Can be conditions or nested filters (2 more levels allowed)"""
119
+
120
+ conjunction: Literal["and", "or"]
121
+
122
+
123
+ class MeterFilter(BaseModel):
124
+ clauses: Union[List[ClausesDirectFilterCondition], List[ClausesNestedMeterFilter]]
125
+ """
126
+ Filter clauses - can be direct conditions or nested filters (up to 3 levels
127
+ deep)
128
+ """
129
+
130
+ conjunction: Literal["and", "or"]
131
+ """Logical conjunction to apply between clauses (and/or)"""
@@ -0,0 +1,143 @@
1
+ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Union, Iterable
6
+ from typing_extensions import Literal, Required, TypedDict
7
+
8
+ __all__ = [
9
+ "MeterFilterParam",
10
+ "ClausesDirectFilterCondition",
11
+ "ClausesNestedMeterFilter",
12
+ "ClausesNestedMeterFilterClausesLevel1FilterCondition",
13
+ "ClausesNestedMeterFilterClausesLevel1NestedFilter",
14
+ "ClausesNestedMeterFilterClausesLevel1NestedFilterClausesLevel2FilterCondition",
15
+ "ClausesNestedMeterFilterClausesLevel1NestedFilterClausesLevel2NestedFilter",
16
+ "ClausesNestedMeterFilterClausesLevel1NestedFilterClausesLevel2NestedFilterClause",
17
+ ]
18
+
19
+
20
+ class ClausesDirectFilterCondition(TypedDict, total=False):
21
+ key: Required[str]
22
+ """Filter key to apply"""
23
+
24
+ operator: Required[
25
+ Literal[
26
+ "equals",
27
+ "not_equals",
28
+ "greater_than",
29
+ "greater_than_or_equals",
30
+ "less_than",
31
+ "less_than_or_equals",
32
+ "contains",
33
+ "does_not_contain",
34
+ ]
35
+ ]
36
+
37
+ value: Required[Union[str, float, bool]]
38
+ """Filter value - can be string, number, or boolean"""
39
+
40
+
41
+ class ClausesNestedMeterFilterClausesLevel1FilterCondition(TypedDict, total=False):
42
+ key: Required[str]
43
+ """Filter key to apply"""
44
+
45
+ operator: Required[
46
+ Literal[
47
+ "equals",
48
+ "not_equals",
49
+ "greater_than",
50
+ "greater_than_or_equals",
51
+ "less_than",
52
+ "less_than_or_equals",
53
+ "contains",
54
+ "does_not_contain",
55
+ ]
56
+ ]
57
+
58
+ value: Required[Union[str, float, bool]]
59
+ """Filter value - can be string, number, or boolean"""
60
+
61
+
62
+ class ClausesNestedMeterFilterClausesLevel1NestedFilterClausesLevel2FilterCondition(TypedDict, total=False):
63
+ key: Required[str]
64
+ """Filter key to apply"""
65
+
66
+ operator: Required[
67
+ Literal[
68
+ "equals",
69
+ "not_equals",
70
+ "greater_than",
71
+ "greater_than_or_equals",
72
+ "less_than",
73
+ "less_than_or_equals",
74
+ "contains",
75
+ "does_not_contain",
76
+ ]
77
+ ]
78
+
79
+ value: Required[Union[str, float, bool]]
80
+ """Filter value - can be string, number, or boolean"""
81
+
82
+
83
+ class ClausesNestedMeterFilterClausesLevel1NestedFilterClausesLevel2NestedFilterClause(TypedDict, total=False):
84
+ key: Required[str]
85
+ """Filter key to apply"""
86
+
87
+ operator: Required[
88
+ Literal[
89
+ "equals",
90
+ "not_equals",
91
+ "greater_than",
92
+ "greater_than_or_equals",
93
+ "less_than",
94
+ "less_than_or_equals",
95
+ "contains",
96
+ "does_not_contain",
97
+ ]
98
+ ]
99
+
100
+ value: Required[Union[str, float, bool]]
101
+ """Filter value - can be string, number, or boolean"""
102
+
103
+
104
+ class ClausesNestedMeterFilterClausesLevel1NestedFilterClausesLevel2NestedFilter(TypedDict, total=False):
105
+ clauses: Required[Iterable[ClausesNestedMeterFilterClausesLevel1NestedFilterClausesLevel2NestedFilterClause]]
106
+ """Level 3: Filter conditions only (max depth reached)"""
107
+
108
+ conjunction: Required[Literal["and", "or"]]
109
+
110
+
111
+ class ClausesNestedMeterFilterClausesLevel1NestedFilter(TypedDict, total=False):
112
+ clauses: Required[
113
+ Union[
114
+ Iterable[ClausesNestedMeterFilterClausesLevel1NestedFilterClausesLevel2FilterCondition],
115
+ Iterable[ClausesNestedMeterFilterClausesLevel1NestedFilterClausesLevel2NestedFilter],
116
+ ]
117
+ ]
118
+ """Level 2: Can be conditions or nested filters (1 more level allowed)"""
119
+
120
+ conjunction: Required[Literal["and", "or"]]
121
+
122
+
123
+ class ClausesNestedMeterFilter(TypedDict, total=False):
124
+ clauses: Required[
125
+ Union[
126
+ Iterable[ClausesNestedMeterFilterClausesLevel1FilterCondition],
127
+ Iterable[ClausesNestedMeterFilterClausesLevel1NestedFilter],
128
+ ]
129
+ ]
130
+ """Level 1: Can be conditions or nested filters (2 more levels allowed)"""
131
+
132
+ conjunction: Required[Literal["and", "or"]]
133
+
134
+
135
+ class MeterFilterParam(TypedDict, total=False):
136
+ clauses: Required[Union[Iterable[ClausesDirectFilterCondition], Iterable[ClausesNestedMeterFilter]]]
137
+ """
138
+ Filter clauses - can be direct conditions or nested filters (up to 3 levels
139
+ deep)
140
+ """
141
+
142
+ conjunction: Required[Literal["and", "or"]]
143
+ """Logical conjunction to apply between clauses (and/or)"""
@@ -0,0 +1,18 @@
1
+ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing_extensions import TypedDict
6
+
7
+ __all__ = ["MeterListParams"]
8
+
9
+
10
+ class MeterListParams(TypedDict, total=False):
11
+ archived: bool
12
+ """List archived meters"""
13
+
14
+ page_number: int
15
+ """Page number default is 0"""
16
+
17
+ page_size: int
18
+ """Page size default is 10 max is 100"""
@@ -87,6 +87,12 @@ class Payment(BaseModel):
87
87
  card_type: Optional[str] = None
88
88
  """The type of card DEBIT or CREDIT"""
89
89
 
90
+ checkout_session_id: Optional[str] = None
91
+ """
92
+ If payment is made using a checkout session, this field is set to the id of the
93
+ session.
94
+ """
95
+
90
96
  discount_id: Optional[str] = None
91
97
  """The discount id if discount is applied"""
92
98
 
@@ -1,20 +1,21 @@
1
1
  # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
2
 
3
- from typing import Union, Optional
3
+ from typing import List, Union, Optional
4
4
  from typing_extensions import Literal, TypeAlias
5
5
 
6
6
  from .._models import BaseModel
7
7
  from .currency import Currency
8
8
  from .time_interval import TimeInterval
9
+ from .add_meter_to_price import AddMeterToPrice
9
10
 
10
- __all__ = ["Price", "OneTimePrice", "RecurringPrice"]
11
+ __all__ = ["Price", "OneTimePrice", "RecurringPrice", "UsageBasedPrice"]
11
12
 
12
13
 
13
14
  class OneTimePrice(BaseModel):
14
15
  currency: Currency
15
16
  """The currency in which the payment is made."""
16
17
 
17
- discount: float
18
+ discount: int
18
19
  """Discount applied to the price, represented as a percentage (0 to 100)."""
19
20
 
20
21
  price: int
@@ -55,7 +56,7 @@ class RecurringPrice(BaseModel):
55
56
  currency: Currency
56
57
  """The currency in which the payment is made."""
57
58
 
58
- discount: float
59
+ discount: int
59
60
  """Discount applied to the price, represented as a percentage (0 to 100)."""
60
61
 
61
62
  payment_frequency_count: int
@@ -98,4 +99,50 @@ class RecurringPrice(BaseModel):
98
99
  """Number of days for the trial period. A value of `0` indicates no trial period."""
99
100
 
100
101
 
101
- Price: TypeAlias = Union[OneTimePrice, RecurringPrice]
102
+ class UsageBasedPrice(BaseModel):
103
+ currency: Currency
104
+ """The currency in which the payment is made."""
105
+
106
+ discount: int
107
+ """Discount applied to the price, represented as a percentage (0 to 100)."""
108
+
109
+ fixed_price: int
110
+ """The fixed payment amount.
111
+
112
+ Represented in the lowest denomination of the currency (e.g., cents for USD).
113
+ For example, to charge $1.00, pass `100`.
114
+ """
115
+
116
+ payment_frequency_count: int
117
+ """
118
+ Number of units for the payment frequency. For example, a value of `1` with a
119
+ `payment_frequency_interval` of `month` represents monthly payments.
120
+ """
121
+
122
+ payment_frequency_interval: TimeInterval
123
+ """The time interval for the payment frequency (e.g., day, month, year)."""
124
+
125
+ purchasing_power_parity: bool
126
+ """
127
+ Indicates if purchasing power parity adjustments are applied to the price.
128
+ Purchasing power parity feature is not available as of now
129
+ """
130
+
131
+ subscription_period_count: int
132
+ """
133
+ Number of units for the subscription period. For example, a value of `12` with a
134
+ `subscription_period_interval` of `month` represents a one-year subscription.
135
+ """
136
+
137
+ subscription_period_interval: TimeInterval
138
+ """The time interval for the subscription period (e.g., day, month, year)."""
139
+
140
+ type: Literal["usage_based_price"]
141
+
142
+ meters: Optional[List[AddMeterToPrice]] = None
143
+
144
+ tax_inclusive: Optional[bool] = None
145
+ """Indicates if the price is tax inclusive"""
146
+
147
+
148
+ Price: TypeAlias = Union[OneTimePrice, RecurringPrice, UsageBasedPrice]