Files
cfw-autumn/others/python-sdk/src/autumn_sdk/models/createplanop.py
2026-02-26 10:40:45 +00:00

1325 lines
44 KiB
Python

"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
from __future__ import annotations
from autumn_sdk.types import (
BaseModel,
Nullable,
OptionalNullable,
UNSET,
UNSET_SENTINEL,
UnrecognizedStr,
)
from autumn_sdk.utils import FieldMetadata, HeaderMetadata
import pydantic
from pydantic import model_serializer
from typing import List, Literal, Optional, Union
from typing_extensions import Annotated, NotRequired, TypeAliasType, TypedDict
class CreatePlanGlobalsTypedDict(TypedDict):
x_api_version: NotRequired[str]
class CreatePlanGlobals(BaseModel):
x_api_version: Annotated[
Optional[str],
pydantic.Field(alias="x-api-version"),
FieldMetadata(header=HeaderMetadata(style="simple", explode=False)),
] = "2.1"
@model_serializer(mode="wrap")
def serialize_model(self, handler):
optional_fields = set(["x-api-version"])
serialized = handler(self)
m = {}
for n, f in type(self).model_fields.items():
k = f.alias or n
val = serialized.get(k)
if val != UNSET_SENTINEL:
if val is not None or k not in optional_fields:
m[k] = val
return m
CreatePlanPriceIntervalRequest = Literal[
"one_off",
"week",
"month",
"quarter",
"semi_annual",
"year",
]
r"""Billing interval (e.g. 'month', 'year')."""
class CreatePlanPriceRequestTypedDict(TypedDict):
r"""Base recurring price for the plan. Omit for free or usage-only plans."""
amount: float
r"""Base price amount for the plan."""
interval: CreatePlanPriceIntervalRequest
r"""Billing interval (e.g. 'month', 'year')."""
interval_count: NotRequired[float]
r"""Number of intervals per billing cycle. Defaults to 1."""
class CreatePlanPriceRequest(BaseModel):
r"""Base recurring price for the plan. Omit for free or usage-only plans."""
amount: float
r"""Base price amount for the plan."""
interval: CreatePlanPriceIntervalRequest
r"""Billing interval (e.g. 'month', 'year')."""
interval_count: Optional[float] = None
r"""Number of intervals per billing cycle. Defaults to 1."""
@model_serializer(mode="wrap")
def serialize_model(self, handler):
optional_fields = set(["interval_count"])
serialized = handler(self)
m = {}
for n, f in type(self).model_fields.items():
k = f.alias or n
val = serialized.get(k)
if val != UNSET_SENTINEL:
if val is not None or k not in optional_fields:
m[k] = val
return m
CreatePlanResetIntervalRequest = Literal[
"one_off",
"minute",
"hour",
"day",
"week",
"month",
"quarter",
"semi_annual",
"year",
]
r"""Interval at which balance resets (e.g. 'month', 'year'). For consumable features only."""
class CreatePlanResetRequestTypedDict(TypedDict):
r"""Reset configuration for consumable features. Omit for non-consumable features like seats."""
interval: CreatePlanResetIntervalRequest
r"""Interval at which balance resets (e.g. 'month', 'year'). For consumable features only."""
interval_count: NotRequired[float]
r"""Number of intervals between resets. Defaults to 1."""
class CreatePlanResetRequest(BaseModel):
r"""Reset configuration for consumable features. Omit for non-consumable features like seats."""
interval: CreatePlanResetIntervalRequest
r"""Interval at which balance resets (e.g. 'month', 'year'). For consumable features only."""
interval_count: Optional[float] = None
r"""Number of intervals between resets. Defaults to 1."""
@model_serializer(mode="wrap")
def serialize_model(self, handler):
optional_fields = set(["interval_count"])
serialized = handler(self)
m = {}
for n, f in type(self).model_fields.items():
k = f.alias or n
val = serialized.get(k)
if val != UNSET_SENTINEL:
if val is not None or k not in optional_fields:
m[k] = val
return m
CreatePlanToRequestTypedDict = TypeAliasType(
"CreatePlanToRequestTypedDict", Union[float, str]
)
CreatePlanToRequest = TypeAliasType("CreatePlanToRequest", Union[float, str])
class CreatePlanTierRequestTypedDict(TypedDict):
to: CreatePlanToRequestTypedDict
amount: float
flat_amount: NotRequired[Nullable[float]]
class CreatePlanTierRequest(BaseModel):
to: CreatePlanToRequest
amount: float
flat_amount: OptionalNullable[float] = UNSET
@model_serializer(mode="wrap")
def serialize_model(self, handler):
optional_fields = set(["flat_amount"])
nullable_fields = set(["flat_amount"])
serialized = handler(self)
m = {}
for n, f in type(self).model_fields.items():
k = f.alias or n
val = serialized.get(k)
is_nullable_and_explicitly_set = (
k in nullable_fields
and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member
)
if val != UNSET_SENTINEL:
if (
val is not None
or k not in optional_fields
or is_nullable_and_explicitly_set
):
m[k] = val
return m
CreatePlanTierBehaviorRequest = Literal[
"graduated",
"volume",
]
CreatePlanItemPriceIntervalRequest = Literal[
"one_off",
"week",
"month",
"quarter",
"semi_annual",
"year",
]
r"""Billing interval. For consumable features, should match reset.interval."""
CreatePlanBillingMethodRequest = Literal[
"prepaid",
"usage_based",
]
r"""'prepaid' for upfront payment (seats), 'usage_based' for pay-as-you-go."""
class CreatePlanItemPriceRequestTypedDict(TypedDict):
r"""Pricing for usage beyond included units. Omit for free features."""
interval: CreatePlanItemPriceIntervalRequest
r"""Billing interval. For consumable features, should match reset.interval."""
billing_method: CreatePlanBillingMethodRequest
r"""'prepaid' for upfront payment (seats), 'usage_based' for pay-as-you-go."""
amount: NotRequired[float]
r"""Price per billing_units after included usage. Either 'amount' or 'tiers' is required."""
tiers: NotRequired[List[CreatePlanTierRequestTypedDict]]
r"""Tiered pricing. Either 'amount' or 'tiers' is required."""
tier_behavior: NotRequired[CreatePlanTierBehaviorRequest]
interval_count: NotRequired[float]
r"""Number of intervals per billing cycle. Defaults to 1."""
billing_units: NotRequired[float]
r"""Units per price increment. Usage is rounded UP when billed (e.g. billing_units=100 means 101 rounds to 200)."""
max_purchase: NotRequired[float]
r"""Max units purchasable beyond included. E.g. included=100, max_purchase=300 allows 400 total."""
class CreatePlanItemPriceRequest(BaseModel):
r"""Pricing for usage beyond included units. Omit for free features."""
interval: CreatePlanItemPriceIntervalRequest
r"""Billing interval. For consumable features, should match reset.interval."""
billing_method: CreatePlanBillingMethodRequest
r"""'prepaid' for upfront payment (seats), 'usage_based' for pay-as-you-go."""
amount: Optional[float] = None
r"""Price per billing_units after included usage. Either 'amount' or 'tiers' is required."""
tiers: Optional[List[CreatePlanTierRequest]] = None
r"""Tiered pricing. Either 'amount' or 'tiers' is required."""
tier_behavior: Optional[CreatePlanTierBehaviorRequest] = None
interval_count: Optional[float] = 1
r"""Number of intervals per billing cycle. Defaults to 1."""
billing_units: Optional[float] = 1
r"""Units per price increment. Usage is rounded UP when billed (e.g. billing_units=100 means 101 rounds to 200)."""
max_purchase: Optional[float] = None
r"""Max units purchasable beyond included. E.g. included=100, max_purchase=300 allows 400 total."""
@model_serializer(mode="wrap")
def serialize_model(self, handler):
optional_fields = set(
[
"amount",
"tiers",
"tier_behavior",
"interval_count",
"billing_units",
"max_purchase",
]
)
serialized = handler(self)
m = {}
for n, f in type(self).model_fields.items():
k = f.alias or n
val = serialized.get(k)
if val != UNSET_SENTINEL:
if val is not None or k not in optional_fields:
m[k] = val
return m
CreatePlanOnIncrease = Literal[
"bill_immediately",
"prorate_immediately",
"prorate_next_cycle",
"bill_next_cycle",
]
r"""Billing behavior when quantity increases mid-cycle."""
CreatePlanOnDecrease = Literal[
"prorate",
"prorate_immediately",
"prorate_next_cycle",
"none",
"no_prorations",
]
r"""Credit behavior when quantity decreases mid-cycle."""
class CreatePlanProrationTypedDict(TypedDict):
r"""Proration settings for prepaid features. Controls mid-cycle quantity change billing."""
on_increase: CreatePlanOnIncrease
r"""Billing behavior when quantity increases mid-cycle."""
on_decrease: CreatePlanOnDecrease
r"""Credit behavior when quantity decreases mid-cycle."""
class CreatePlanProration(BaseModel):
r"""Proration settings for prepaid features. Controls mid-cycle quantity change billing."""
on_increase: CreatePlanOnIncrease
r"""Billing behavior when quantity increases mid-cycle."""
on_decrease: CreatePlanOnDecrease
r"""Credit behavior when quantity decreases mid-cycle."""
CreatePlanExpiryDurationTypeRequest = Literal[
"month",
"forever",
]
r"""When rolled over units expire."""
class CreatePlanRolloverRequestTypedDict(TypedDict):
r"""Rollover config for unused units. If set, unused included units carry over."""
expiry_duration_type: CreatePlanExpiryDurationTypeRequest
r"""When rolled over units expire."""
max: NotRequired[float]
r"""Max rollover units. Omit for unlimited rollover."""
expiry_duration_length: NotRequired[float]
r"""Number of periods before expiry."""
class CreatePlanRolloverRequest(BaseModel):
r"""Rollover config for unused units. If set, unused included units carry over."""
expiry_duration_type: CreatePlanExpiryDurationTypeRequest
r"""When rolled over units expire."""
max: Optional[float] = None
r"""Max rollover units. Omit for unlimited rollover."""
expiry_duration_length: Optional[float] = None
r"""Number of periods before expiry."""
@model_serializer(mode="wrap")
def serialize_model(self, handler):
optional_fields = set(["max", "expiry_duration_length"])
serialized = handler(self)
m = {}
for n, f in type(self).model_fields.items():
k = f.alias or n
val = serialized.get(k)
if val != UNSET_SENTINEL:
if val is not None or k not in optional_fields:
m[k] = val
return m
class CreatePlanPlanItemTypedDict(TypedDict):
r"""Configuration for a feature item in a plan, including usage limits, pricing, and rollover settings."""
feature_id: str
r"""The ID of the feature to configure."""
included: NotRequired[float]
r"""Number of free units included. Balance resets to this each interval for consumable features."""
unlimited: NotRequired[bool]
r"""If true, customer has unlimited access to this feature."""
reset: NotRequired[CreatePlanResetRequestTypedDict]
r"""Reset configuration for consumable features. Omit for non-consumable features like seats."""
price: NotRequired[CreatePlanItemPriceRequestTypedDict]
r"""Pricing for usage beyond included units. Omit for free features."""
proration: NotRequired[CreatePlanProrationTypedDict]
r"""Proration settings for prepaid features. Controls mid-cycle quantity change billing."""
rollover: NotRequired[CreatePlanRolloverRequestTypedDict]
r"""Rollover config for unused units. If set, unused included units carry over."""
class CreatePlanPlanItem(BaseModel):
r"""Configuration for a feature item in a plan, including usage limits, pricing, and rollover settings."""
feature_id: str
r"""The ID of the feature to configure."""
included: Optional[float] = None
r"""Number of free units included. Balance resets to this each interval for consumable features."""
unlimited: Optional[bool] = None
r"""If true, customer has unlimited access to this feature."""
reset: Optional[CreatePlanResetRequest] = None
r"""Reset configuration for consumable features. Omit for non-consumable features like seats."""
price: Optional[CreatePlanItemPriceRequest] = None
r"""Pricing for usage beyond included units. Omit for free features."""
proration: Optional[CreatePlanProration] = None
r"""Proration settings for prepaid features. Controls mid-cycle quantity change billing."""
rollover: Optional[CreatePlanRolloverRequest] = None
r"""Rollover config for unused units. If set, unused included units carry over."""
@model_serializer(mode="wrap")
def serialize_model(self, handler):
optional_fields = set(
["included", "unlimited", "reset", "price", "proration", "rollover"]
)
serialized = handler(self)
m = {}
for n, f in type(self).model_fields.items():
k = f.alias or n
val = serialized.get(k)
if val != UNSET_SENTINEL:
if val is not None or k not in optional_fields:
m[k] = val
return m
CreatePlanDurationTypeRequest = Literal[
"day",
"month",
"year",
]
r"""Unit of time for the trial ('day', 'month', 'year')."""
class FreeTrialRequestTypedDict(TypedDict):
r"""Free trial configuration. Customers can try this plan before being charged."""
duration_length: float
r"""Number of duration_type periods the trial lasts."""
duration_type: NotRequired[CreatePlanDurationTypeRequest]
r"""Unit of time for the trial ('day', 'month', 'year')."""
card_required: NotRequired[bool]
r"""If true, payment method required to start trial. Customer is charged after trial ends."""
class FreeTrialRequest(BaseModel):
r"""Free trial configuration. Customers can try this plan before being charged."""
duration_length: float
r"""Number of duration_type periods the trial lasts."""
duration_type: Optional[CreatePlanDurationTypeRequest] = "month"
r"""Unit of time for the trial ('day', 'month', 'year')."""
card_required: Optional[bool] = True
r"""If true, payment method required to start trial. Customer is charged after trial ends."""
@model_serializer(mode="wrap")
def serialize_model(self, handler):
optional_fields = set(["duration_type", "card_required"])
serialized = handler(self)
m = {}
for n, f in type(self).model_fields.items():
k = f.alias or n
val = serialized.get(k)
if val != UNSET_SENTINEL:
if val is not None or k not in optional_fields:
m[k] = val
return m
class CreatePlanParamsTypedDict(TypedDict):
plan_id: str
r"""The ID of the plan to create."""
name: str
r"""Display name of the plan."""
group: NotRequired[str]
r"""Group identifier for organizing related plans. Plans in the same group are mutually exclusive."""
description: NotRequired[Nullable[str]]
r"""Optional description of the plan."""
add_on: NotRequired[bool]
r"""If true, this plan can be attached alongside other plans. Otherwise, attaching replaces existing plans in the same group."""
auto_enable: NotRequired[bool]
r"""If true, plan is automatically attached when a customer is created. Use for free tiers."""
price: NotRequired[CreatePlanPriceRequestTypedDict]
r"""Base recurring price for the plan. Omit for free or usage-only plans."""
items: NotRequired[List[CreatePlanPlanItemTypedDict]]
r"""Feature configurations for this plan. Each item defines included units, pricing, and reset behavior."""
free_trial: NotRequired[FreeTrialRequestTypedDict]
r"""Free trial configuration. Customers can try this plan before being charged."""
class CreatePlanParams(BaseModel):
plan_id: str
r"""The ID of the plan to create."""
name: str
r"""Display name of the plan."""
group: Optional[str] = ""
r"""Group identifier for organizing related plans. Plans in the same group are mutually exclusive."""
description: OptionalNullable[str] = UNSET
r"""Optional description of the plan."""
add_on: Optional[bool] = False
r"""If true, this plan can be attached alongside other plans. Otherwise, attaching replaces existing plans in the same group."""
auto_enable: Optional[bool] = False
r"""If true, plan is automatically attached when a customer is created. Use for free tiers."""
price: Optional[CreatePlanPriceRequest] = None
r"""Base recurring price for the plan. Omit for free or usage-only plans."""
items: Optional[List[CreatePlanPlanItem]] = None
r"""Feature configurations for this plan. Each item defines included units, pricing, and reset behavior."""
free_trial: Optional[FreeTrialRequest] = None
r"""Free trial configuration. Customers can try this plan before being charged."""
@model_serializer(mode="wrap")
def serialize_model(self, handler):
optional_fields = set(
[
"group",
"description",
"add_on",
"auto_enable",
"price",
"items",
"free_trial",
]
)
nullable_fields = set(["description"])
serialized = handler(self)
m = {}
for n, f in type(self).model_fields.items():
k = f.alias or n
val = serialized.get(k)
is_nullable_and_explicitly_set = (
k in nullable_fields
and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member
)
if val != UNSET_SENTINEL:
if (
val is not None
or k not in optional_fields
or is_nullable_and_explicitly_set
):
m[k] = val
return m
CreatePlanPriceIntervalResponse = Union[
Literal[
"one_off",
"week",
"month",
"quarter",
"semi_annual",
"year",
],
UnrecognizedStr,
]
r"""Billing interval (e.g. 'month', 'year')."""
class CreatePlanPriceDisplayTypedDict(TypedDict):
r"""Display text for showing this price in pricing pages."""
primary_text: str
r"""Main display text (e.g. '$10' or '100 messages')."""
secondary_text: NotRequired[str]
r"""Secondary display text (e.g. 'per month' or 'then $0.5 per 100')."""
class CreatePlanPriceDisplay(BaseModel):
r"""Display text for showing this price in pricing pages."""
primary_text: str
r"""Main display text (e.g. '$10' or '100 messages')."""
secondary_text: Optional[str] = None
r"""Secondary display text (e.g. 'per month' or 'then $0.5 per 100')."""
@model_serializer(mode="wrap")
def serialize_model(self, handler):
optional_fields = set(["secondary_text"])
serialized = handler(self)
m = {}
for n, f in type(self).model_fields.items():
k = f.alias or n
val = serialized.get(k)
if val != UNSET_SENTINEL:
if val is not None or k not in optional_fields:
m[k] = val
return m
class CreatePlanPriceResponseTypedDict(TypedDict):
amount: float
r"""Base price amount for the plan."""
interval: CreatePlanPriceIntervalResponse
r"""Billing interval (e.g. 'month', 'year')."""
interval_count: NotRequired[float]
r"""Number of intervals per billing cycle. Defaults to 1."""
display: NotRequired[CreatePlanPriceDisplayTypedDict]
r"""Display text for showing this price in pricing pages."""
class CreatePlanPriceResponse(BaseModel):
amount: float
r"""Base price amount for the plan."""
interval: CreatePlanPriceIntervalResponse
r"""Billing interval (e.g. 'month', 'year')."""
interval_count: Optional[float] = None
r"""Number of intervals per billing cycle. Defaults to 1."""
display: Optional[CreatePlanPriceDisplay] = None
r"""Display text for showing this price in pricing pages."""
@model_serializer(mode="wrap")
def serialize_model(self, handler):
optional_fields = set(["interval_count", "display"])
serialized = handler(self)
m = {}
for n, f in type(self).model_fields.items():
k = f.alias or n
val = serialized.get(k)
if val != UNSET_SENTINEL:
if val is not None or k not in optional_fields:
m[k] = val
return m
CreatePlanType = Union[
Literal[
"static",
"boolean",
"single_use",
"continuous_use",
"credit_system",
],
UnrecognizedStr,
]
r"""The type of the feature"""
class CreatePlanFeatureDisplayTypedDict(TypedDict):
singular: str
r"""The singular display name for the feature."""
plural: str
r"""The plural display name for the feature."""
class CreatePlanFeatureDisplay(BaseModel):
singular: str
r"""The singular display name for the feature."""
plural: str
r"""The plural display name for the feature."""
class CreatePlanCreditSchemaTypedDict(TypedDict):
metered_feature_id: str
r"""The ID of the metered feature (should be a single_use feature)."""
credit_cost: float
r"""The credit cost of the metered feature."""
class CreatePlanCreditSchema(BaseModel):
metered_feature_id: str
r"""The ID of the metered feature (should be a single_use feature)."""
credit_cost: float
r"""The credit cost of the metered feature."""
class CreatePlanFeatureTypedDict(TypedDict):
r"""The full feature object if expanded."""
id: str
r"""The ID of the feature, used to refer to it in other API calls like /track or /check."""
type: CreatePlanType
r"""The type of the feature"""
name: NotRequired[Nullable[str]]
r"""The name of the feature."""
display: NotRequired[Nullable[CreatePlanFeatureDisplayTypedDict]]
r"""Singular and plural display names for the feature."""
credit_schema: NotRequired[Nullable[List[CreatePlanCreditSchemaTypedDict]]]
r"""Credit cost schema for credit system features."""
archived: NotRequired[Nullable[bool]]
r"""Whether or not the feature is archived."""
class CreatePlanFeature(BaseModel):
r"""The full feature object if expanded."""
id: str
r"""The ID of the feature, used to refer to it in other API calls like /track or /check."""
type: CreatePlanType
r"""The type of the feature"""
name: OptionalNullable[str] = UNSET
r"""The name of the feature."""
display: OptionalNullable[CreatePlanFeatureDisplay] = UNSET
r"""Singular and plural display names for the feature."""
credit_schema: OptionalNullable[List[CreatePlanCreditSchema]] = UNSET
r"""Credit cost schema for credit system features."""
archived: OptionalNullable[bool] = UNSET
r"""Whether or not the feature is archived."""
@model_serializer(mode="wrap")
def serialize_model(self, handler):
optional_fields = set(["name", "display", "credit_schema", "archived"])
nullable_fields = set(["name", "display", "credit_schema", "archived"])
serialized = handler(self)
m = {}
for n, f in type(self).model_fields.items():
k = f.alias or n
val = serialized.get(k)
is_nullable_and_explicitly_set = (
k in nullable_fields
and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member
)
if val != UNSET_SENTINEL:
if (
val is not None
or k not in optional_fields
or is_nullable_and_explicitly_set
):
m[k] = val
return m
CreatePlanResetIntervalResponse = Union[
Literal[
"one_off",
"minute",
"hour",
"day",
"week",
"month",
"quarter",
"semi_annual",
"year",
],
UnrecognizedStr,
]
r"""The interval at which the feature balance resets (e.g. 'month', 'year'). For consumable features, usage resets to 0 and included units are restored."""
class CreatePlanResetResponseTypedDict(TypedDict):
interval: CreatePlanResetIntervalResponse
r"""The interval at which the feature balance resets (e.g. 'month', 'year'). For consumable features, usage resets to 0 and included units are restored."""
interval_count: NotRequired[float]
r"""Number of intervals between resets. Defaults to 1."""
class CreatePlanResetResponse(BaseModel):
interval: CreatePlanResetIntervalResponse
r"""The interval at which the feature balance resets (e.g. 'month', 'year'). For consumable features, usage resets to 0 and included units are restored."""
interval_count: Optional[float] = None
r"""Number of intervals between resets. Defaults to 1."""
@model_serializer(mode="wrap")
def serialize_model(self, handler):
optional_fields = set(["interval_count"])
serialized = handler(self)
m = {}
for n, f in type(self).model_fields.items():
k = f.alias or n
val = serialized.get(k)
if val != UNSET_SENTINEL:
if val is not None or k not in optional_fields:
m[k] = val
return m
CreatePlanToResponseTypedDict = TypeAliasType(
"CreatePlanToResponseTypedDict", Union[float, str]
)
CreatePlanToResponse = TypeAliasType("CreatePlanToResponse", Union[float, str])
class CreatePlanTierResponseTypedDict(TypedDict):
to: CreatePlanToResponseTypedDict
amount: float
flat_amount: NotRequired[Nullable[float]]
class CreatePlanTierResponse(BaseModel):
to: CreatePlanToResponse
amount: float
flat_amount: OptionalNullable[float] = UNSET
@model_serializer(mode="wrap")
def serialize_model(self, handler):
optional_fields = set(["flat_amount"])
nullable_fields = set(["flat_amount"])
serialized = handler(self)
m = {}
for n, f in type(self).model_fields.items():
k = f.alias or n
val = serialized.get(k)
is_nullable_and_explicitly_set = (
k in nullable_fields
and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member
)
if val != UNSET_SENTINEL:
if (
val is not None
or k not in optional_fields
or is_nullable_and_explicitly_set
):
m[k] = val
return m
CreatePlanTierBehaviorResponse = Union[
Literal[
"graduated",
"volume",
],
UnrecognizedStr,
]
CreatePlanPriceItemIntervalResponse = Union[
Literal[
"one_off",
"week",
"month",
"quarter",
"semi_annual",
"year",
],
UnrecognizedStr,
]
r"""Billing interval for this price. For consumable features, should match reset.interval."""
CreatePlanBillingMethodResponse = Union[
Literal[
"prepaid",
"usage_based",
],
UnrecognizedStr,
]
r"""'prepaid' for features like seats where customers pay upfront, 'usage_based' for pay-as-you-go after included usage."""
class CreatePlanItemPriceResponseTypedDict(TypedDict):
interval: CreatePlanPriceItemIntervalResponse
r"""Billing interval for this price. For consumable features, should match reset.interval."""
billing_units: float
r"""Number of units per price increment. Usage is rounded UP to the nearest billing_units when billed (e.g. billing_units=100 means 101 usage rounds to 200)."""
billing_method: CreatePlanBillingMethodResponse
r"""'prepaid' for features like seats where customers pay upfront, 'usage_based' for pay-as-you-go after included usage."""
max_purchase: Nullable[float]
r"""Maximum units a customer can purchase beyond included. E.g. if included=100 and max_purchase=300, customer can use up to 400 total before usage is capped. Null for no limit."""
amount: NotRequired[float]
r"""Price per billing_units after included usage is consumed. Mutually exclusive with tiers."""
tiers: NotRequired[List[CreatePlanTierResponseTypedDict]]
r"""Tiered pricing configuration. Each tier's 'to' INCLUDES the included amount. Either 'tiers' or 'amount' is required."""
tier_behavior: NotRequired[CreatePlanTierBehaviorResponse]
interval_count: NotRequired[float]
r"""Number of intervals per billing cycle. Defaults to 1."""
class CreatePlanItemPriceResponse(BaseModel):
interval: CreatePlanPriceItemIntervalResponse
r"""Billing interval for this price. For consumable features, should match reset.interval."""
billing_units: float
r"""Number of units per price increment. Usage is rounded UP to the nearest billing_units when billed (e.g. billing_units=100 means 101 usage rounds to 200)."""
billing_method: CreatePlanBillingMethodResponse
r"""'prepaid' for features like seats where customers pay upfront, 'usage_based' for pay-as-you-go after included usage."""
max_purchase: Nullable[float]
r"""Maximum units a customer can purchase beyond included. E.g. if included=100 and max_purchase=300, customer can use up to 400 total before usage is capped. Null for no limit."""
amount: Optional[float] = None
r"""Price per billing_units after included usage is consumed. Mutually exclusive with tiers."""
tiers: Optional[List[CreatePlanTierResponse]] = None
r"""Tiered pricing configuration. Each tier's 'to' INCLUDES the included amount. Either 'tiers' or 'amount' is required."""
tier_behavior: Optional[CreatePlanTierBehaviorResponse] = None
interval_count: Optional[float] = None
r"""Number of intervals per billing cycle. Defaults to 1."""
@model_serializer(mode="wrap")
def serialize_model(self, handler):
optional_fields = set(["amount", "tiers", "tier_behavior", "interval_count"])
nullable_fields = set(["max_purchase"])
serialized = handler(self)
m = {}
for n, f in type(self).model_fields.items():
k = f.alias or n
val = serialized.get(k)
is_nullable_and_explicitly_set = (
k in nullable_fields
and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member
)
if val != UNSET_SENTINEL:
if (
val is not None
or k not in optional_fields
or is_nullable_and_explicitly_set
):
m[k] = val
return m
class CreatePlanItemDisplayTypedDict(TypedDict):
r"""Display text for showing this item in pricing pages."""
primary_text: str
r"""Main display text (e.g. '$10' or '100 messages')."""
secondary_text: NotRequired[str]
r"""Secondary display text (e.g. 'per month' or 'then $0.5 per 100')."""
class CreatePlanItemDisplay(BaseModel):
r"""Display text for showing this item in pricing pages."""
primary_text: str
r"""Main display text (e.g. '$10' or '100 messages')."""
secondary_text: Optional[str] = None
r"""Secondary display text (e.g. 'per month' or 'then $0.5 per 100')."""
@model_serializer(mode="wrap")
def serialize_model(self, handler):
optional_fields = set(["secondary_text"])
serialized = handler(self)
m = {}
for n, f in type(self).model_fields.items():
k = f.alias or n
val = serialized.get(k)
if val != UNSET_SENTINEL:
if val is not None or k not in optional_fields:
m[k] = val
return m
CreatePlanExpiryDurationTypeResponse = Union[
Literal[
"month",
"forever",
],
UnrecognizedStr,
]
r"""When rolled over units expire."""
class CreatePlanRolloverResponseTypedDict(TypedDict):
r"""Rollover configuration for unused units. If set, unused included units roll over to the next period."""
max: Nullable[float]
r"""Maximum rollover units. Null for unlimited rollover."""
expiry_duration_type: CreatePlanExpiryDurationTypeResponse
r"""When rolled over units expire."""
expiry_duration_length: NotRequired[float]
r"""Number of periods before expiry."""
class CreatePlanRolloverResponse(BaseModel):
r"""Rollover configuration for unused units. If set, unused included units roll over to the next period."""
max: Nullable[float]
r"""Maximum rollover units. Null for unlimited rollover."""
expiry_duration_type: CreatePlanExpiryDurationTypeResponse
r"""When rolled over units expire."""
expiry_duration_length: Optional[float] = None
r"""Number of periods before expiry."""
@model_serializer(mode="wrap")
def serialize_model(self, handler):
optional_fields = set(["expiry_duration_length"])
nullable_fields = set(["max"])
serialized = handler(self)
m = {}
for n, f in type(self).model_fields.items():
k = f.alias or n
val = serialized.get(k)
is_nullable_and_explicitly_set = (
k in nullable_fields
and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member
)
if val != UNSET_SENTINEL:
if (
val is not None
or k not in optional_fields
or is_nullable_and_explicitly_set
):
m[k] = val
return m
class CreatePlanItemTypedDict(TypedDict):
feature_id: str
r"""The ID of the feature this item configures."""
included: float
r"""Number of free units included. For consumable features, balance resets to this number each interval."""
unlimited: bool
r"""Whether the customer has unlimited access to this feature."""
reset: Nullable[CreatePlanResetResponseTypedDict]
r"""Reset configuration for consumable features. Null for non-consumable features like seats where usage persists across billing cycles."""
price: Nullable[CreatePlanItemPriceResponseTypedDict]
r"""Pricing configuration for usage beyond included units. Null if feature is entirely free."""
feature: NotRequired[CreatePlanFeatureTypedDict]
r"""The full feature object if expanded."""
display: NotRequired[CreatePlanItemDisplayTypedDict]
r"""Display text for showing this item in pricing pages."""
rollover: NotRequired[CreatePlanRolloverResponseTypedDict]
r"""Rollover configuration for unused units. If set, unused included units roll over to the next period."""
class CreatePlanItem(BaseModel):
feature_id: str
r"""The ID of the feature this item configures."""
included: float
r"""Number of free units included. For consumable features, balance resets to this number each interval."""
unlimited: bool
r"""Whether the customer has unlimited access to this feature."""
reset: Nullable[CreatePlanResetResponse]
r"""Reset configuration for consumable features. Null for non-consumable features like seats where usage persists across billing cycles."""
price: Nullable[CreatePlanItemPriceResponse]
r"""Pricing configuration for usage beyond included units. Null if feature is entirely free."""
feature: Optional[CreatePlanFeature] = None
r"""The full feature object if expanded."""
display: Optional[CreatePlanItemDisplay] = None
r"""Display text for showing this item in pricing pages."""
rollover: Optional[CreatePlanRolloverResponse] = None
r"""Rollover configuration for unused units. If set, unused included units roll over to the next period."""
@model_serializer(mode="wrap")
def serialize_model(self, handler):
optional_fields = set(["feature", "display", "rollover"])
nullable_fields = set(["reset", "price"])
serialized = handler(self)
m = {}
for n, f in type(self).model_fields.items():
k = f.alias or n
val = serialized.get(k)
is_nullable_and_explicitly_set = (
k in nullable_fields
and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member
)
if val != UNSET_SENTINEL:
if (
val is not None
or k not in optional_fields
or is_nullable_and_explicitly_set
):
m[k] = val
return m
CreatePlanDurationTypeResponse = Union[
Literal[
"day",
"month",
"year",
],
UnrecognizedStr,
]
r"""Unit of time for the trial duration ('day', 'month', 'year')."""
class CreatePlanFreeTrialResponseTypedDict(TypedDict):
r"""Free trial configuration. If set, new customers can try this plan before being charged."""
duration_length: float
r"""Number of duration_type periods the trial lasts."""
duration_type: CreatePlanDurationTypeResponse
r"""Unit of time for the trial duration ('day', 'month', 'year')."""
card_required: bool
r"""Whether a payment method is required to start the trial. If true, customer will be charged after trial ends."""
class CreatePlanFreeTrialResponse(BaseModel):
r"""Free trial configuration. If set, new customers can try this plan before being charged."""
duration_length: float
r"""Number of duration_type periods the trial lasts."""
duration_type: CreatePlanDurationTypeResponse
r"""Unit of time for the trial duration ('day', 'month', 'year')."""
card_required: bool
r"""Whether a payment method is required to start the trial. If true, customer will be charged after trial ends."""
CreatePlanEnv = Union[
Literal[
"sandbox",
"live",
],
UnrecognizedStr,
]
r"""Environment this plan belongs to ('sandbox' or 'live')."""
CreatePlanScenario = Union[
Literal[
"scheduled",
"active",
"new",
"renew",
"upgrade",
"downgrade",
"cancel",
"expired",
"past_due",
],
UnrecognizedStr,
]
r"""The attach scenario for this customer (e.g. new_subscription, upgrade, downgrade)."""
class CreatePlanCustomerEligibilityTypedDict(TypedDict):
scenario: CreatePlanScenario
r"""The attach scenario for this customer (e.g. new_subscription, upgrade, downgrade)."""
trial_available: NotRequired[bool]
r"""Whether a free trial is available for this customer."""
class CreatePlanCustomerEligibility(BaseModel):
scenario: CreatePlanScenario
r"""The attach scenario for this customer (e.g. new_subscription, upgrade, downgrade)."""
trial_available: Optional[bool] = None
r"""Whether a free trial is available for this customer."""
@model_serializer(mode="wrap")
def serialize_model(self, handler):
optional_fields = set(["trial_available"])
serialized = handler(self)
m = {}
for n, f in type(self).model_fields.items():
k = f.alias or n
val = serialized.get(k)
if val != UNSET_SENTINEL:
if val is not None or k not in optional_fields:
m[k] = val
return m
class CreatePlanResponseTypedDict(TypedDict):
r"""A plan defines a set of features, pricing, and entitlements that can be attached to customers."""
id: str
r"""Unique identifier for the plan."""
name: str
r"""Display name of the plan."""
description: Nullable[str]
r"""Optional description of the plan."""
group: Nullable[str]
r"""Group identifier for organizing related plans. Plans in the same group are mutually exclusive."""
version: float
r"""Version number of the plan. Incremented when plan configuration changes."""
add_on: bool
r"""Whether this is an add-on plan that can be attached alongside a main plan."""
auto_enable: bool
r"""If true, this plan is automatically attached when a customer is created. Used for free plans."""
price: Nullable[CreatePlanPriceResponseTypedDict]
r"""Base recurring price for the plan. Null for free plans or usage-only plans."""
items: List[CreatePlanItemTypedDict]
r"""Feature configurations included in this plan. Each item defines included units, pricing, and reset behavior for a feature."""
created_at: float
r"""Unix timestamp (ms) when the plan was created."""
env: CreatePlanEnv
r"""Environment this plan belongs to ('sandbox' or 'live')."""
archived: bool
r"""Whether the plan is archived. Archived plans cannot be attached to new customers."""
base_variant_id: Nullable[str]
r"""If this is a variant, the ID of the base plan it was created from."""
free_trial: NotRequired[CreatePlanFreeTrialResponseTypedDict]
r"""Free trial configuration. If set, new customers can try this plan before being charged."""
customer_eligibility: NotRequired[CreatePlanCustomerEligibilityTypedDict]
class CreatePlanResponse(BaseModel):
r"""A plan defines a set of features, pricing, and entitlements that can be attached to customers."""
id: str
r"""Unique identifier for the plan."""
name: str
r"""Display name of the plan."""
description: Nullable[str]
r"""Optional description of the plan."""
group: Nullable[str]
r"""Group identifier for organizing related plans. Plans in the same group are mutually exclusive."""
version: float
r"""Version number of the plan. Incremented when plan configuration changes."""
add_on: bool
r"""Whether this is an add-on plan that can be attached alongside a main plan."""
auto_enable: bool
r"""If true, this plan is automatically attached when a customer is created. Used for free plans."""
price: Nullable[CreatePlanPriceResponse]
r"""Base recurring price for the plan. Null for free plans or usage-only plans."""
items: List[CreatePlanItem]
r"""Feature configurations included in this plan. Each item defines included units, pricing, and reset behavior for a feature."""
created_at: float
r"""Unix timestamp (ms) when the plan was created."""
env: CreatePlanEnv
r"""Environment this plan belongs to ('sandbox' or 'live')."""
archived: bool
r"""Whether the plan is archived. Archived plans cannot be attached to new customers."""
base_variant_id: Nullable[str]
r"""If this is a variant, the ID of the base plan it was created from."""
free_trial: Optional[CreatePlanFreeTrialResponse] = None
r"""Free trial configuration. If set, new customers can try this plan before being charged."""
customer_eligibility: Optional[CreatePlanCustomerEligibility] = None
@model_serializer(mode="wrap")
def serialize_model(self, handler):
optional_fields = set(["free_trial", "customer_eligibility"])
nullable_fields = set(["description", "group", "price", "base_variant_id"])
serialized = handler(self)
m = {}
for n, f in type(self).model_fields.items():
k = f.alias or n
val = serialized.get(k)
is_nullable_and_explicitly_set = (
k in nullable_fields
and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member
)
if val != UNSET_SENTINEL:
if (
val is not None
or k not in optional_fields
or is_nullable_and_explicitly_set
):
m[k] = val
return m