API Reference¶
This section contains the complete API reference.
Main Interface¶
SubscriptionKore - Provider-agnostic async subscriptionkore management library.
- class subscriptionkore.AppliedDiscount(*, discount_id: str, coupon_code: str | None = None, amount_off: Money | None = None, percent_off: Decimal | None = None, valid_until: datetime | None = None)[source]
Bases:
BaseModelDiscount applied to a subscriptionn.
- amount_off: Money | None
- coupon_code: str | None
- discount_id: str
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'amount_off': FieldInfo(annotation=Union[Money, NoneType], required=False, default=None), 'coupon_code': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'discount_id': FieldInfo(annotation=str, required=True), 'percent_off': FieldInfo(annotation=Union[Decimal, NoneType], required=False, default=None), 'valid_until': FieldInfo(annotation=Union[datetime, NoneType], required=False, default=None)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- percent_off: Decimal | None
- valid_until: datetime | None
- class subscriptionkore.BillingPeriod(*, interval: Interval, interval_count: Annotated[int, Ge(ge=1)] = 1, anchor_date: datetime | None = None)[source]
Bases:
BaseModelBilling period configuration.
- anchor_date: datetime | None
- property display_name: str
- interval: Interval
- interval_count: int
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'anchor_date': FieldInfo(annotation=Union[datetime, NoneType], required=False, default=None), 'interval': FieldInfo(annotation=Interval, required=True), 'interval_count': FieldInfo(annotation=int, required=False, default=1, metadata=[Ge(ge=1)])}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- classmethod monthly() BillingPeriod[source]
- classmethod weekly() BillingPeriod[source]
- classmethod yearly() BillingPeriod[source]
- exception subscriptionkore.ConfigurationError(message: str, details: dict[str, Any] | None = None)[source]
Bases:
SubscriptionKoreErrorBase class for configuration errors.
- class subscriptionkore.Customer(*, id: str = None, external_id: str, email: EmailStr, name: str | None = None, provider_refs: list[ProviderReference] = None, tax_info: TaxInfo | None = None, billing_address: Address | None = None, metadata: dict[str, Any] = None, created_at: datetime = None, updated_at: datetime = None)[source]
Bases:
BaseModelCustomer domain entity.
- add_provider_ref(ref: ProviderReference) None[source]
Add or update a provider reference.
- billing_address: Address | None
- created_at: datetime
- email: EmailStr
- external_id: str
- get_provider_ref(provider_type: str) ProviderReference | None[source]
Get provider reference for a specific provider.
- id: str
- metadata: dict[str, Any]
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'billing_address': FieldInfo(annotation=Union[Address, NoneType], required=False, default=None), 'created_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method), 'email': FieldInfo(annotation=EmailStr, required=True), 'external_id': FieldInfo(annotation=str, required=True), 'id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'name': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'provider_refs': FieldInfo(annotation=list[ProviderReference], required=False, default_factory=list), 'tax_info': FieldInfo(annotation=Union[TaxInfo, NoneType], required=False, default=None), 'updated_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- name: str | None
- provider_refs: list[ProviderReference]
- tax_info: TaxInfo | None
- update(email: str | None = None, name: str | None = None, tax_info: TaxInfo | None = None, billing_address: Address | None = None, metadata: dict[str, Any] | None = None) None[source]
Update customer fields.
- updated_at: datetime
- class subscriptionkore.CustomerCreated(*, event_id: str = None, event_type: str = 'CustomerCreated', occurred_at: datetime = None, metadata: dict[str, Any] = None, customer: Customer)[source]
Bases:
DomainEventEmitted when a customer is created.
- customer: Customer
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'customer': FieldInfo(annotation=Customer, required=True), 'event_id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'event_type': FieldInfo(annotation=str, required=False, default='CustomerCreated'), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'occurred_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- class subscriptionkore.CustomerEntitlement(*, customer_id: str, entitlement_key: str, current_value: bool | int | str, value_type: EntitlementValueType, source: EntitlementSource, expires_at: datetime | None = None, subscription_id: str | None = None, plan_id: str | None = None)[source]
Bases:
BaseModelResolved entitlement for a customer.
- as_bool() bool[source]
Get value as boolean.
- as_int() int | None[source]
Get value as integer (None for unlimited).
- current_value: bool | int | str
- customer_id: str
- entitlement_key: str
- expires_at: datetime | None
- is_boolean() bool[source]
- is_expired() bool[source]
Check if entitlement has expired.
- is_numeric() bool[source]
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'current_value': FieldInfo(annotation=Union[bool, int, str], required=True), 'customer_id': FieldInfo(annotation=str, required=True), 'entitlement_key': FieldInfo(annotation=str, required=True), 'expires_at': FieldInfo(annotation=Union[datetime, NoneType], required=False, default=None), 'plan_id': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'source': FieldInfo(annotation=EntitlementSource, required=True), 'subscription_id': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'value_type': FieldInfo(annotation=EntitlementValueType, required=True)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- plan_id: str | None
- source: EntitlementSource
- subscription_id: str | None
- value_type: EntitlementValueType
- class subscriptionkore.CustomerUpdated(*, event_id: str = None, event_type: str = 'CustomerUpdated', occurred_at: datetime = None, metadata: dict[str, Any] = None, customer: Customer, changed_fields: list[str])[source]
Bases:
DomainEventEmitted when a customer is updated.
- changed_fields: list[str]
- customer: Customer
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'changed_fields': FieldInfo(annotation=list[str], required=True), 'customer': FieldInfo(annotation=Customer, required=True), 'event_id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'event_type': FieldInfo(annotation=str, required=False, default='CustomerUpdated'), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'occurred_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- exception subscriptionkore.DomainError(message: str, details: dict[str, Any] | None = None)[source]
Bases:
SubscriptionKoreErrorBase class for domain errors.
- class subscriptionkore.DomainEvent(*, event_id: str = None, event_type: str = '', occurred_at: datetime = None, metadata: dict[str, Any] = None)[source]
Bases:
BaseModelBase class for all domain events.
- event_id: str
- event_type: str
- metadata: dict[str, Any]
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'event_id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'event_type': FieldInfo(annotation=str, required=False, default='SubscriptionPlanChanged'), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'occurred_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- occurred_at: datetime
- exception subscriptionkore.DuplicateEntityError(entity_type: str, identifier: str)[source]
Bases:
DomainErrorRaised when attempting to create a duplicate entity.
- class subscriptionkore.Entitlement(*, id: str = None, key: str, name: str, description: str | None = None, value_type: EntitlementValueType, default_value: bool | int | str | None = None, metadata: dict[str, Any] = None, created_at: datetime = None, updated_at: datetime = None)[source]
Bases:
BaseModelEntitlement definition entity.
- created_at: datetime
- default_value: bool | int | str | None
- description: str | None
- id: str
- key: str
- metadata: dict[str, Any]
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'created_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method), 'default_value': FieldInfo(annotation=Union[bool, int, str, NoneType], required=False, default=None), 'description': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'key': FieldInfo(annotation=str, required=True), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'name': FieldInfo(annotation=str, required=True), 'updated_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method), 'value_type': FieldInfo(annotation=EntitlementValueType, required=True)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- name: str
- updated_at: datetime
- value_type: EntitlementValueType
- exception subscriptionkore.EntitlementError(message: str, details: dict[str, Any] | None = None)[source]
Bases:
SubscriptionKoreErrorBase class for entitlement errors.
- exception subscriptionkore.EntitlementNotFoundError(key: str)[source]
Bases:
EntitlementErrorRaised when an entitlement is not found.
- class subscriptionkore.EntitlementOverride(*, id: str = None, customer_id: str, entitlement_key: str, value: bool | int | str, value_type: EntitlementValueType, reason: str | None = None, expires_at: datetime | None = None, created_by: str | None = None, created_at: datetime = None)[source]
Bases:
BaseModelManual entitlement override for a customer.
- created_at: datetime
- created_by: str | None
- customer_id: str
- entitlement_key: str
- expires_at: datetime | None
- id: str
- is_expired() bool[source]
Check if override has expired.
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'created_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method), 'created_by': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'customer_id': FieldInfo(annotation=str, required=True), 'entitlement_key': FieldInfo(annotation=str, required=True), 'expires_at': FieldInfo(annotation=Union[datetime, NoneType], required=False, default=None), 'id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'reason': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'value': FieldInfo(annotation=Union[bool, int, str], required=True), 'value_type': FieldInfo(annotation=EntitlementValueType, required=True)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- reason: str | None
- value: bool | int | str
- value_type: EntitlementValueType
- class subscriptionkore.EntitlementValueType(*values)[source]
Bases:
StrEnumTypes of entitlement values.
- BOOLEAN = 'boolean'
- NUMERIC = 'numeric'
- STRING = 'string'
- UNLIMITED = 'unlimited'
- exception subscriptionkore.EntityNotFoundError(entity_type: str, entity_id: str)[source]
Bases:
DomainErrorRaised when an entity is not found.
- class subscriptionkore.Interval(*values)[source]
Bases:
StrEnumBilling interval types.
- DAY = 'day'
- MONTH = 'month'
- WEEK = 'week'
- YEAR = 'year'
- exception subscriptionkore.InvalidConfigurationError(message: str, details: dict[str, Any] | None = None)[source]
Bases:
ConfigurationErrorRaised when configuration is invalid.
- exception subscriptionkore.InvalidStateTransitionError(from_state: SubscriptionStatus, to_state: SubscriptionStatus, reason: str | None = None)[source]
Bases:
DomainErrorRaised when an invalid state transition is attempted.
- class subscriptionkore.Invoice(*, id: str = None, customer_id: str, subscriptionkore_id: str | None = None, provider_ref: ProviderReference, status: InvoiceStatus = InvoiceStatus.DRAFT, subtotal: Money, tax: Money = None, discount_amount: Money = None, total: Money, amount_paid: Money = None, amount_due: Money, currency: Currency = Currency.USD, line_items: list[InvoiceLineItem] = None, period: DateRange | None = None, due_date: datetime | None = None, paid_at: datetime | None = None, invoice_pdf_url: str | None = None, hosted_invoice_url: str | None = None, metadata: dict[str, Any] = None, created_at: datetime = None)[source]
Bases:
BaseModelInvoice domain entity.
- amount_due: Money
- amount_paid: Money
- created_at: datetime
- currency: Currency
- customer_id: str
- discount_amount: Money
- due_date: datetime | None
- hosted_invoice_url: str | None
- id: str
- invoice_pdf_url: str | None
- is_open() bool[source]
Check if invoice is open for payment.
- is_overdue() bool[source]
Check if invoice is past due date.
- is_paid() bool[source]
Check if invoice is fully paid.
- line_items: list[InvoiceLineItem]
- metadata: dict[str, Any]
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'amount_due': FieldInfo(annotation=Money, required=True), 'amount_paid': FieldInfo(annotation=Money, required=False, default_factory=<lambda>), 'created_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method), 'currency': FieldInfo(annotation=Currency, required=False, default=<Currency.USD: 'USD'>), 'customer_id': FieldInfo(annotation=str, required=True), 'discount_amount': FieldInfo(annotation=Money, required=False, default_factory=<lambda>), 'due_date': FieldInfo(annotation=Union[datetime, NoneType], required=False, default=None), 'hosted_invoice_url': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'invoice_pdf_url': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'line_items': FieldInfo(annotation=list[InvoiceLineItem], required=False, default_factory=list), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'paid_at': FieldInfo(annotation=Union[datetime, NoneType], required=False, default=None), 'period': FieldInfo(annotation=Union[DateRange, NoneType], required=False, default=None), 'provider_ref': FieldInfo(annotation=ProviderReference, required=True), 'status': FieldInfo(annotation=InvoiceStatus, required=False, default=<InvoiceStatus.DRAFT: 'draft'>), 'subscriptionkore_id': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'subtotal': FieldInfo(annotation=Money, required=True), 'tax': FieldInfo(annotation=Money, required=False, default_factory=<lambda>), 'total': FieldInfo(annotation=Money, required=True)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- paid_at: datetime | None
- period: DateRange | None
- provider_ref: ProviderReference
- status: InvoiceStatus
- subscriptionkore_id: str | None
- subtotal: Money
- tax: Money
- total: Money
- class subscriptionkore.InvoiceCreated(*, event_id: str = None, event_type: str = 'InvoiceCreated', occurred_at: datetime = None, metadata: dict[str, Any] = None, invoice: Invoice, customer_id: str, subscription_id: str | None = None)[source]
Bases:
DomainEventEmitted when an invoice is created.
- customer_id: str
- invoice: Invoice
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'customer_id': FieldInfo(annotation=str, required=True), 'event_id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'event_type': FieldInfo(annotation=str, required=False, default='InvoiceCreated'), 'invoice': FieldInfo(annotation=Invoice, required=True), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'occurred_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method), 'subscription_id': FieldInfo(annotation=Union[str, NoneType], required=False, default=None)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- subscription_id: str | None
- class subscriptionkore.InvoiceLineItem(*, id: str = None, description: str, quantity: int = 1, unit_amount: Money, amount: Money, period: DateRange | None = None, proration: bool = False, metadata: dict[str, Any] = None)[source]
Bases:
BaseModelLine item on an invoice.
- amount: Money
- description: str
- id: str
- metadata: dict[str, Any]
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'amount': FieldInfo(annotation=Money, required=True), 'description': FieldInfo(annotation=str, required=True), 'id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'period': FieldInfo(annotation=Union[DateRange, NoneType], required=False, default=None), 'proration': FieldInfo(annotation=bool, required=False, default=False), 'quantity': FieldInfo(annotation=int, required=False, default=1), 'unit_amount': FieldInfo(annotation=Money, required=True)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- period: DateRange | None
- proration: bool
- quantity: int
- unit_amount: Money
- class subscriptionkore.InvoicePaid(*, event_id: str = None, event_type: str = 'InvoicePaid', occurred_at: datetime = None, metadata: dict[str, Any] = None, invoice: Invoice, customer_id: str, subscription_id: str | None = None, amount_paid: Money)[source]
Bases:
DomainEventEmitted when an invoice is paid.
- amount_paid: Money
- customer_id: str
- invoice: Invoice
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'amount_paid': FieldInfo(annotation=Money, required=True), 'customer_id': FieldInfo(annotation=str, required=True), 'event_id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'event_type': FieldInfo(annotation=str, required=False, default='InvoicePaid'), 'invoice': FieldInfo(annotation=Invoice, required=True), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'occurred_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method), 'subscription_id': FieldInfo(annotation=Union[str, NoneType], required=False, default=None)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- subscription_id: str | None
- class subscriptionkore.InvoiceStatus(*values)[source]
Bases:
StrEnumInvoice status values.
- DRAFT = 'draft'
- OPEN = 'open'
- PAID = 'paid'
- UNCOLLECTIBLE = 'uncollectible'
- VOID = 'void'
- exception subscriptionkore.MissingProviderCredentialsError(provider: str, missing_fields: list[str])[source]
Bases:
ConfigurationErrorRaised when provider credentials are missing.
- class subscriptionkore.Money(*, amount: Decimal, currency: Currency = Currency.USD)[source]
Bases:
BaseModelImmutable monetary value with currency.
- amount: Decimal
- currency: Currency
- classmethod from_cents(cents: int, currency: Currency = Currency.USD) Money[source]
Create Money from minor units (cents).
- is_negative() bool[source]
- is_positive() bool[source]
- is_zero() bool[source]
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'amount': FieldInfo(annotation=Decimal, required=True, description='Amount in major currency units'), 'currency': FieldInfo(annotation=Currency, required=False, default=<Currency.USD: 'USD'>)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- classmethod normalize_amount(v: Any) Decimal[source]
- to_cents() int[source]
Convert to minor units (cents).
- class subscriptionkore.PauseConfig(*, resumes_at: datetime | None = None, behavior: PauseBehavior = PauseBehavior.VOID)[source]
Bases:
BaseModelSubscription pause configuration.
- behavior: PauseBehavior
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'behavior': FieldInfo(annotation=PauseBehavior, required=False, default=<PauseBehavior.VOID: 'void'>), 'resumes_at': FieldInfo(annotation=Union[datetime, NoneType], required=False, default=None)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- resumes_at: datetime | None
- class subscriptionkore.PaymentEvent(*, id: str = None, provider_ref: ProviderReference, customer_id: str, subscriptionkore_id: str | None = None, invoice_id: str | None = None, event_type: PaymentEventType, amount: Money, status: PaymentStatus, failure_reason: str | None = None, failure_code: str | None = None, payment_method_type: str | None = None, payment_method_last4: str | None = None, occurred_at: datetime = None, metadata: dict[str, Any] = None)[source]
Bases:
BaseModelPayment event domain entity.
- amount: Money
- customer_id: str
- event_type: PaymentEventType
- failure_code: str | None
- failure_reason: str | None
- id: str
- invoice_id: str | None
- is_failed() bool[source]
Check if payment failed.
- is_successful() bool[source]
Check if payment succeeded.
- metadata: dict[str, Any]
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'amount': FieldInfo(annotation=Money, required=True), 'customer_id': FieldInfo(annotation=str, required=True), 'event_type': FieldInfo(annotation=PaymentEventType, required=True), 'failure_code': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'failure_reason': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'invoice_id': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'occurred_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method), 'payment_method_last4': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'payment_method_type': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'provider_ref': FieldInfo(annotation=ProviderReference, required=True), 'status': FieldInfo(annotation=PaymentStatus, required=True), 'subscriptionkore_id': FieldInfo(annotation=Union[str, NoneType], required=False, default=None)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- occurred_at: datetime
- payment_method_last4: str | None
- payment_method_type: str | None
- provider_ref: ProviderReference
- status: PaymentStatus
- subscriptionkore_id: str | None
- class subscriptionkore.PaymentEventType(*values)[source]
Bases:
StrEnumPayment event types.
- PAYMENT_DISPUTED = 'payment_disputed'
- PAYMENT_FAILED = 'payment_failed'
- PAYMENT_REFUNDED = 'payment_refunded'
- PAYMENT_SUCCEEDED = 'payment_succeeded'
- class subscriptionkore.PaymentFailed(*, event_id: str = None, event_type: str = 'PaymentFailed', occurred_at: datetime = None, metadata: dict[str, Any] = None, payment_event: PaymentEvent, customer_id: str, subscription_id: str | None = None, invoice_id: str | None = None, amount: Money, failure_reason: str | None = None, failure_code: str | None = None, attempt_count: int = 1)[source]
Bases:
DomainEventEmitted when a payment fails.
- amount: Money
- attempt_count: int
- customer_id: str
- failure_code: str | None
- failure_reason: str | None
- invoice_id: str | None
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'amount': FieldInfo(annotation=Money, required=True), 'attempt_count': FieldInfo(annotation=int, required=False, default=1), 'customer_id': FieldInfo(annotation=str, required=True), 'event_id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'event_type': FieldInfo(annotation=str, required=False, default='PaymentFailed'), 'failure_code': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'failure_reason': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'invoice_id': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'occurred_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method), 'payment_event': FieldInfo(annotation=PaymentEvent, required=True), 'subscription_id': FieldInfo(annotation=Union[str, NoneType], required=False, default=None)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- payment_event: PaymentEvent
- subscription_id: str | None
- class subscriptionkore.PaymentStatus(*values)[source]
Bases:
StrEnumPayment status values.
- DISPUTED = 'disputed'
- FAILED = 'failed'
- PARTIALLY_REFUNDED = 'partially_refunded'
- PENDING = 'pending'
- REFUNDED = 'refunded'
- SUCCEEDED = 'succeeded'
- class subscriptionkore.PaymentSucceeded(*, event_id: str = None, event_type: str = 'PaymentSucceeded', occurred_at: datetime = None, metadata: dict[str, Any] = None, payment_event: PaymentEvent, customer_id: str, subscription_id: str | None = None, invoice_id: str | None = None, amount: Money)[source]
Bases:
DomainEventEmitted when a payment succeeds.
- amount: Money
- customer_id: str
- invoice_id: str | None
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'amount': FieldInfo(annotation=Money, required=True), 'customer_id': FieldInfo(annotation=str, required=True), 'event_id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'event_type': FieldInfo(annotation=str, required=False, default='PaymentSucceeded'), 'invoice_id': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'occurred_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method), 'payment_event': FieldInfo(annotation=PaymentEvent, required=True), 'subscription_id': FieldInfo(annotation=Union[str, NoneType], required=False, default=None)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- payment_event: PaymentEvent
- subscription_id: str | None
- class subscriptionkore.Plan(*, id: str = None, product_id: str, name: str, description: str | None = None, provider_refs: list[ProviderReference] = None, price: Money, billing_period: BillingPeriod, trial_period_days: int | None = None, entitlements: list[PlanEntitlement] = None, active: bool = True, tier: int = 0, metadata: dict[str, Any] = None, created_at: datetime = None, updated_at: datetime = None)[source]
Bases:
BaseModelPlan domain entity (a pricing tier for a product).
- active: bool
- add_provider_ref(ref: ProviderReference) None[source]
Add or update a provider reference.
- billing_period: BillingPeriod
- created_at: datetime
- deactivate() None[source]
Deactivate the plan.
- description: str | None
- entitlements: list[PlanEntitlement]
- get_entitlement_value(key: str) bool | int | str | None[source]
Get entitlement value by key.
- get_provider_ref(provider_type: str) ProviderReference | None[source]
Get provider reference for a specific provider.
- id: str
- metadata: dict[str, Any]
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'active': FieldInfo(annotation=bool, required=False, default=True), 'billing_period': FieldInfo(annotation=BillingPeriod, required=True), 'created_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method), 'description': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'entitlements': FieldInfo(annotation=list[PlanEntitlement], required=False, default_factory=list), 'id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'name': FieldInfo(annotation=str, required=True), 'price': FieldInfo(annotation=Money, required=True), 'product_id': FieldInfo(annotation=str, required=True), 'provider_refs': FieldInfo(annotation=list[ProviderReference], required=False, default_factory=list), 'tier': FieldInfo(annotation=int, required=False, default=0, description='For upgrade/downgrade ordering'), 'trial_period_days': FieldInfo(annotation=Union[int, NoneType], required=False, default=None), 'updated_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- name: str
- price: Money
- product_id: str
- provider_refs: list[ProviderReference]
- tier: int
- trial_period_days: int | None
- updated_at: datetime
- class subscriptionkore.PlanEntitlement(*, entitlement_id: str, entitlement_key: str, value: bool | int | str | None, value_type: EntitlementValueType)[source]
Bases:
BaseModelEntitlement configuration for a plan.
- entitlement_id: str
- entitlement_key: str
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'entitlement_id': FieldInfo(annotation=str, required=True), 'entitlement_key': FieldInfo(annotation=str, required=True), 'value': FieldInfo(annotation=Union[bool, int, str, NoneType], required=True), 'value_type': FieldInfo(annotation=EntitlementValueType, required=True)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- value: bool | int | str | None
- value_type: EntitlementValueType
- class subscriptionkore.Product(*, id: str = None, name: str, description: str | None = None, provider_refs: list[ProviderReference] = None, active: bool = True, metadata: dict[str, Any] = None, created_at: datetime = None, updated_at: datetime = None)[source]
Bases:
BaseModelProduct domain entity.
- activate() None[source]
Activate the product.
- active: bool
- add_provider_ref(ref: ProviderReference) None[source]
Add or update a provider reference.
- created_at: datetime
- deactivate() None[source]
Deactivate the product.
- description: str | None
- get_provider_ref(provider_type: str) ProviderReference | None[source]
Get provider reference for a specific provider.
- id: str
- metadata: dict[str, Any]
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'active': FieldInfo(annotation=bool, required=False, default=True), 'created_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method), 'description': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'name': FieldInfo(annotation=str, required=True), 'provider_refs': FieldInfo(annotation=list[ProviderReference], required=False, default_factory=list), 'updated_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- name: str
- provider_refs: list[ProviderReference]
- updated_at: datetime
- exception subscriptionkore.ProviderAPIError(message: str, provider: str, status_code: int, provider_message: str | None = None, provider_code: str | None = None)[source]
Bases:
ProviderErrorRaised for non-recoverable API errors from providers.
- exception subscriptionkore.ProviderAuthenticationError(provider: str, message: str | None = None)[source]
Bases:
ProviderErrorRaised when authentication fails. Non-recoverable.
- exception subscriptionkore.ProviderError(message: str, provider: str, details: dict[str, Any] | None = None)[source]
Bases:
SubscriptionKoreErrorBase class for provider errors.
- exception subscriptionkore.ProviderNetworkError(provider: str, original_error: Exception)[source]
Bases:
ProviderErrorRaised for network errors. Recoverable with retry.
- exception subscriptionkore.ProviderRateLimitError(provider: str, retry_after: int | None = None)[source]
Bases:
ProviderErrorRaised when provider rate limit is exceeded. Recoverable with retry.
- class subscriptionkore.ProviderReference(*, provider: ProviderType, external_id: str, metadata: dict[str, Any] = None)[source]
Bases:
BaseModelReference to an entity in a payment provider.
- external_id: str
- metadata: dict[str, Any]
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'external_id': FieldInfo(annotation=str, required=True), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'provider': FieldInfo(annotation=ProviderType, required=True)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- provider: ProviderType
- class subscriptionkore.ProviderType(*values)[source]
Bases:
StrEnumSupported payment providers.
- CHARGEBEE = 'chargebee'
- LEMONSQUEEZY = 'lemonsqueezy'
- PADDLE = 'paddle'
- STRIPE = 'stripe'
- exception subscriptionkore.RepositoryError(operation: str, entity_type: str, original_error: Exception)[source]
Bases:
SubscriptionKoreErrorRaised when a repository operation fails.
- class subscriptionkore.Subscription(*, id: str = None, customer_id: str, plan_id: str, provider_ref: ProviderReference, status: SubscriptionStatus = SubscriptionStatus.INCOMPLETE, current_period: DateRange, trial_end: datetime | None = None, cancel_at_period_end: bool = False, canceled_at: datetime | None = None, ended_at: datetime | None = None, pause_collection: PauseConfig | None = None, discount: AppliedDiscount | None = None, quantity: int = 1, metadata: dict[str, Any] = None, created_at: datetime = None, updated_at: datetime = None)[source]
Bases:
BaseModelSubscription domain entity.
- apply_discount(discount: AppliedDiscount) None[source]
Apply a discount to the subscriptionn.
- cancel_at_period_end: bool
- canceled_at: datetime | None
- created_at: datetime
- current_period: DateRange
- customer_id: str
- days_until_trial_ends() int | None[source]
Get days until trial ends, or None if not trialing.
- discount: AppliedDiscount | None
- ended_at: datetime | None
- has_ended() bool[source]
Check if subscriptionn has permanently ended.
- id: str
- is_active() bool[source]
Check if subscriptionn is in an active state.
- is_canceled() bool[source]
Check if subscriptionn is canceled.
- is_past_due() bool[source]
Check if subscriptionn has payment issues.
- is_paused() bool[source]
Check if subscriptionn is paused.
- is_trialing() bool[source]
Check if subscriptionn is in trial.
- metadata: dict[str, Any]
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'cancel_at_period_end': FieldInfo(annotation=bool, required=False, default=False), 'canceled_at': FieldInfo(annotation=Union[datetime, NoneType], required=False, default=None), 'created_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method), 'current_period': FieldInfo(annotation=DateRange, required=True), 'customer_id': FieldInfo(annotation=str, required=True), 'discount': FieldInfo(annotation=Union[AppliedDiscount, NoneType], required=False, default=None), 'ended_at': FieldInfo(annotation=Union[datetime, NoneType], required=False, default=None), 'id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'pause_collection': FieldInfo(annotation=Union[PauseConfig, NoneType], required=False, default=None), 'plan_id': FieldInfo(annotation=str, required=True), 'provider_ref': FieldInfo(annotation=ProviderReference, required=True), 'quantity': FieldInfo(annotation=int, required=False, default=1), 'status': FieldInfo(annotation=SubscriptionStatus, required=False, default=<SubscriptionStatus.INCOMPLETE: 'incomplete'>), 'trial_end': FieldInfo(annotation=Union[datetime, NoneType], required=False, default=None), 'updated_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- pause_collection: PauseConfig | None
- plan_id: str
- provider_ref: ProviderReference
- quantity: int
- remove_discount() None[source]
Remove discount from subscriptionn.
- schedule_cancellation() None[source]
Schedule cancellation at period end.
- status: SubscriptionStatus
- trial_end: datetime | None
- unschedule_cancellation() None[source]
Remove scheduled cancellation.
- updated_at: datetime
- will_cancel_at_period_end() bool[source]
Check if subscriptionn is scheduled to cancel.
- class subscriptionkore.SubscriptionActivated(*, event_id: str = None, event_type: str = 'SubscriptionActivated', occurred_at: datetime = None, metadata: dict[str, Any] = None, subscriptionkore: Subscription, customer_id: str, plan_id: str)[source]
Bases:
DomainEventEmitted when a subscriptionkore becomes active.
- customer_id: str
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'customer_id': FieldInfo(annotation=str, required=True), 'event_id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'event_type': FieldInfo(annotation=str, required=False, default='SubscriptionActivated'), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'occurred_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method), 'plan_id': FieldInfo(annotation=str, required=True), 'subscriptionkore': FieldInfo(annotation=Subscription, required=True)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- plan_id: str
- subscriptionkore: Subscription
- class subscriptionkore.SubscriptionCanceled(*, event_id: str = None, event_type: str = 'SubscriptionCanceled', occurred_at: datetime = None, metadata: dict[str, Any] = None, subscriptionkore: Subscription, customer_id: str, plan_id: str, immediate: bool, reason: str | None = None)[source]
Bases:
DomainEventEmitted when a subscriptionkore is canceled.
- customer_id: str
- immediate: bool
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'customer_id': FieldInfo(annotation=str, required=True), 'event_id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'event_type': FieldInfo(annotation=str, required=False, default='SubscriptionCanceled'), 'immediate': FieldInfo(annotation=bool, required=True), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'occurred_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method), 'plan_id': FieldInfo(annotation=str, required=True), 'reason': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'subscriptionkore': FieldInfo(annotation=Subscription, required=True)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- plan_id: str
- reason: str | None
- subscriptionkore: Subscription
- class subscriptionkore.SubscriptionCreated(*, event_id: str = None, event_type: str = 'SubscriptionCreated', occurred_at: datetime = None, metadata: dict[str, Any] = None, subscriptionkore: Subscription, customer_id: str, plan_id: str)[source]
Bases:
DomainEventEmitted when a subscriptionkore is created.
- customer_id: str
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'customer_id': FieldInfo(annotation=str, required=True), 'event_id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'event_type': FieldInfo(annotation=str, required=False, default='SubscriptionCreated'), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'occurred_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method), 'plan_id': FieldInfo(annotation=str, required=True), 'subscriptionkore': FieldInfo(annotation=Subscription, required=True)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- plan_id: str
- subscriptionkore: Subscription
- class subscriptionkore.SubscriptionKore(config: SubscriptionKoreConfig)[source]
Bases:
objectMain entry point for the SubscriptionKore library.
Provides access to all subscription management functionality.
Example:
from subscriptionkore import SubscriptionKore, SubscriptionKoreConfig from subscriptionkore.config import StripeConfig config = SubscriptionKoreConfig( database_url="postgresql+asyncpg://user:pass@localhost/db", stripe=StripeConfig( api_key="sk_test_...", webhook_secret="whsec_...", ), ) async with SubscriptionKore(config) as subscriptionkore: # Create a customer customer = await subscriptionkore.customers.create( external_id="user_123", email="user@example.com", ) # Create a subscription subscription = await subscriptionkore.subscriptions.create( customer_id=customer.id, plan_id="plan_abc", ) # Check entitlements has_access = await subscriptionkore.entitlements.has_access( customer_id=customer.id, entitlement_key="premium_features", )
- async check_entitlement(customer_id: str, entitlement_key: str) CustomerEntitlement[source]
Convenience method to check an entitlement.
- async close() None[source]
Close all connections and clean up resources.
- property configured_providers: list[ProviderType]
Get list of configured providers.
- async create_customer(external_id: str, email: str, name: str | None = None, provider_type: ProviderType | None = None) Customer[source]
Convenience method to create a customer.
- async create_subscription(customer_id: str, plan_id: str, quantity: int = 1, trial_period_days: int | None = None, provider_type: ProviderType | None = None) Subscription[source]
Convenience method to create a subscription.
- property event_bus: EventBusPort
Access the event bus for subscribing to domain events.
- async get_customer_manager(provider_type: ProviderType | None = None) CustomerManager[source]
Get a customer manager instance.
- async get_entitlement_service() EntitlementService[source]
Get an entitlement service instance.
- get_provider(provider_type: ProviderType) PaymentProviderPort[source]
Get a specific provider adapter.
- async get_subscription_manager(provider_type: ProviderType | None = None) SubscriptionManager[source]
Get a subscription manager instance.
- async get_webhook_processor() WebhookProcessor[source]
Get a webhook processor instance.
- async has_access(customer_id: str, entitlement_key: str) bool[source]
Convenience method to check feature access.
- async initialize() None[source]
Initialize all components.
- on_event(event_type: type['DomainEvent']) Callable[[Callable[['DomainEvent'], Awaitable[None]]], Callable[['DomainEvent'], Awaitable[None]]][source]
Decorator to subscribe to domain events.
Example:
@subscriptionkore.on_event(SubscriptionActivated) async def handle_activation(event: SubscriptionActivated): await send_welcome_email(event.customer_id)
- class subscriptionkore.SubscriptionKoreConfig(_case_sensitive: bool | None = None, _nested_model_default_partial_update: bool | None = None, _env_prefix: str | None = None, _env_file: DotenvType | None = PosixPath('.'), _env_file_encoding: str | None = None, _env_ignore_empty: bool | None = None, _env_nested_delimiter: str | None = None, _env_parse_none_str: str | None = None, _env_parse_enums: bool | None = None, _cli_prog_name: str | None = None, _cli_parse_args: bool | list[str] | tuple[str, ...] | None = None, _cli_settings_source: CliSettingsSource[Any] | None = None, _cli_parse_none_str: str | None = None, _cli_hide_none_type: bool | None = None, _cli_avoid_json: bool | None = None, _cli_enforce_required: bool | None = None, _cli_use_class_docs_for_groups: bool | None = None, _cli_exit_on_error: bool | None = None, _cli_prefix: str | None = None, _cli_flag_prefix_char: str | None = None, _cli_implicit_flags: bool | None = None, _cli_ignore_unknown_args: bool | None = None, _secrets_dir: PathType | None = None, *, database_url: str, redis_url: str | None = None, stripe: StripeConfig | None = None, paddle: PaddleConfig | None = None, lemonsqueezy: LemonSqueezyConfig | None = None, chargebee: ChargebeeConfig | None = None, default_provider: ProviderType = ProviderType.STRIPE, webhook_processing: Literal['sync', 'async'] = 'sync', entitlement_cache_ttl: int = 300, processed_event_ttl_days: int = 7)[source]
Bases:
BaseSettingsMain configuration for SubscriptionKore.
- chargebee: ChargebeeConfig | None
- database_url: str
- default_provider: ProviderType
- entitlement_cache_ttl: int
- get_configured_providers() list[ProviderType][source]
Get list of configured providers.
- get_provider_config(provider: ProviderType) StripeConfig | PaddleConfig | LemonSqueezyConfig | ChargebeeConfig | None[source]
Get configuration for a specific provider.
- lemonsqueezy: LemonSqueezyConfig | None
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[SettingsConfigDict] = {'arbitrary_types_allowed': True, 'case_sensitive': False, 'cli_avoid_json': False, 'cli_enforce_required': False, 'cli_exit_on_error': True, 'cli_flag_prefix_char': '-', 'cli_hide_none_type': False, 'cli_ignore_unknown_args': False, 'cli_implicit_flags': False, 'cli_parse_args': None, 'cli_parse_none_str': None, 'cli_prefix': '', 'cli_prog_name': None, 'cli_use_class_docs_for_groups': False, 'env_file': None, 'env_file_encoding': None, 'env_ignore_empty': False, 'env_nested_delimiter': '__', 'env_parse_enums': None, 'env_parse_none_str': None, 'env_prefix': 'SUBSCRIPTIONKORE_', 'extra': 'forbid', 'json_file': None, 'json_file_encoding': None, 'nested_model_default_partial_update': False, 'protected_namespaces': ('model_', 'settings_'), 'secrets_dir': None, 'toml_file': None, 'validate_default': True, 'yaml_file': None, 'yaml_file_encoding': None}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'chargebee': FieldInfo(annotation=Union[ChargebeeConfig, NoneType], required=False, default=None), 'database_url': FieldInfo(annotation=str, required=True, description='PostgreSQL async connection URL'), 'default_provider': FieldInfo(annotation=ProviderType, required=False, default=<ProviderType.STRIPE: 'stripe'>, description='Default payment provider to use'), 'entitlement_cache_ttl': FieldInfo(annotation=int, required=False, default=300, description='Entitlement cache TTL in seconds'), 'lemonsqueezy': FieldInfo(annotation=Union[LemonSqueezyConfig, NoneType], required=False, default=None), 'paddle': FieldInfo(annotation=Union[PaddleConfig, NoneType], required=False, default=None), 'processed_event_ttl_days': FieldInfo(annotation=int, required=False, default=7, description='Days to keep processed event records'), 'redis_url': FieldInfo(annotation=Union[str, NoneType], required=False, default=None, description='Redis connection URL'), 'stripe': FieldInfo(annotation=Union[StripeConfig, NoneType], required=False, default=None), 'webhook_processing': FieldInfo(annotation=Literal['sync', 'async'], required=False, default='sync', description='Webhook processing mode')}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- paddle: PaddleConfig | None
- processed_event_ttl_days: int
- redis_url: str | None
- stripe: StripeConfig | None
- classmethod validate_database_url(v: str) str[source]
Validate database URL is async-compatible.
- validate_default_provider_configured() SubscriptionKoreConfig[source]
Ensure default provider has configuration.
- webhook_processing: Literal['sync', 'async']
- exception subscriptionkore.SubscriptionKoreError(message: str, details: dict[str, Any] | None = None)[source]
Bases:
ExceptionBase exception for all subscriptionkore errors.
- class subscriptionkore.SubscriptionPastDue(*, event_id: str = None, event_type: str = 'SubscriptionPastDue', occurred_at: datetime = None, metadata: dict[str, Any] = None, subscriptionkore: Subscription, customer_id: str, invoice_id: str | None = None)[source]
Bases:
DomainEventEmitted when a subscriptionkore becomes past due.
- customer_id: str
- invoice_id: str | None
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'customer_id': FieldInfo(annotation=str, required=True), 'event_id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'event_type': FieldInfo(annotation=str, required=False, default='SubscriptionPastDue'), 'invoice_id': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'occurred_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method), 'subscriptionkore': FieldInfo(annotation=Subscription, required=True)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- subscriptionkore: Subscription
- class subscriptionkore.SubscriptionPaused(*, event_id: str = None, event_type: str = 'SubscriptionPaused', occurred_at: datetime = None, metadata: dict[str, Any] = None, subscriptionkore: Subscription, customer_id: str, resumes_at: datetime | None = None)[source]
Bases:
DomainEventEmitted when a subscriptionkore is paused.
- customer_id: str
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'customer_id': FieldInfo(annotation=str, required=True), 'event_id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'event_type': FieldInfo(annotation=str, required=False, default='SubscriptionPaused'), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'occurred_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method), 'resumes_at': FieldInfo(annotation=Union[datetime, NoneType], required=False, default=None), 'subscriptionkore': FieldInfo(annotation=Subscription, required=True)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- resumes_at: datetime | None
- subscriptionkore: Subscription
- class subscriptionkore.SubscriptionPlanChanged(*, event_id: str = None, event_type: str = 'SubscriptionPlanChanged', occurred_at: datetime = None, metadata: dict[str, Any] = None, subscriptionkore: Subscription, customer_id: str, previous_plan_id: str, new_plan_id: str, is_upgrade: bool)[source]
Bases:
DomainEventEmitted when subscriptionkore plan is changed.
- customer_id: str
- is_upgrade: bool
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'customer_id': FieldInfo(annotation=str, required=True), 'event_id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'event_type': FieldInfo(annotation=str, required=False, default='SubscriptionPlanChanged'), 'is_upgrade': FieldInfo(annotation=bool, required=True), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'new_plan_id': FieldInfo(annotation=str, required=True), 'occurred_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method), 'previous_plan_id': FieldInfo(annotation=str, required=True), 'subscriptionkore': FieldInfo(annotation=Subscription, required=True)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- new_plan_id: str
- previous_plan_id: str
- subscriptionkore: Subscription
- class subscriptionkore.SubscriptionResumed(*, event_id: str = None, event_type: str = 'SubscriptionResumed', occurred_at: datetime = None, metadata: dict[str, Any] = None, subscriptionkore: Subscription, customer_id: str)[source]
Bases:
DomainEventEmitted when a subscriptionkore is resumed.
- customer_id: str
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'customer_id': FieldInfo(annotation=str, required=True), 'event_id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'event_type': FieldInfo(annotation=str, required=False, default='SubscriptionResumed'), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'occurred_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method), 'subscriptionkore': FieldInfo(annotation=Subscription, required=True)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- subscriptionkore: Subscription
- class subscriptionkore.SubscriptionStatus(*values)[source]
Bases:
StrEnumSubscription status values.
- ACTIVE = 'active'
- CANCELED = 'canceled'
- EXPIRED = 'expired'
- INCOMPLETE = 'incomplete'
- INCOMPLETE_EXPIRED = 'incomplete_expired'
- PAST_DUE = 'past_due'
- PAUSED = 'paused'
- TRIALING = 'trialing'
- UNPAID = 'unpaid'
- class subscriptionkore.SubscriptionTrialEnded(*, event_id: str = None, event_type: str = 'SubscriptionTrialEnded', occurred_at: datetime = None, metadata: dict[str, Any] = None, subscriptionkore: Subscription, customer_id: str, converted: bool)[source]
Bases:
DomainEventEmitted when a trial ends.
- converted: bool
- customer_id: str
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'converted': FieldInfo(annotation=bool, required=True), 'customer_id': FieldInfo(annotation=str, required=True), 'event_id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'event_type': FieldInfo(annotation=str, required=False, default='SubscriptionTrialEnded'), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'occurred_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method), 'subscriptionkore': FieldInfo(annotation=Subscription, required=True)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- subscriptionkore: Subscription
- class subscriptionkore.SubscriptionTrialStarted(*, event_id: str = None, event_type: str = 'SubscriptionTrialStarted', occurred_at: datetime = None, metadata: dict[str, Any] = None, subscriptionkore: Subscription, customer_id: str, trial_end: datetime)[source]
Bases:
DomainEventEmitted when a trial starts.
- customer_id: str
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'customer_id': FieldInfo(annotation=str, required=True), 'event_id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'event_type': FieldInfo(annotation=str, required=False, default='SubscriptionTrialStarted'), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'occurred_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method), 'subscriptionkore': FieldInfo(annotation=Subscription, required=True), 'trial_end': FieldInfo(annotation=datetime, required=True)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- subscriptionkore: Subscription
- trial_end: datetime
- class subscriptionkore.SubscriptionUpdated(*, event_id: str = None, event_type: str = 'SubscriptionUpdated', occurred_at: datetime = None, metadata: dict[str, Any] = None, subscriptionkore: Subscription, customer_id: str, changed_fields: list[str])[source]
Bases:
DomainEventEmitted when a subscriptionkore is updated.
- changed_fields: list[str]
- customer_id: str
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'changed_fields': FieldInfo(annotation=list[str], required=True), 'customer_id': FieldInfo(annotation=str, required=True), 'event_id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'event_type': FieldInfo(annotation=str, required=False, default='SubscriptionUpdated'), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'occurred_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method), 'subscriptionkore': FieldInfo(annotation=Subscription, required=True)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- subscriptionkore: Subscription
- exception subscriptionkore.UsageLimitExceededError(entitlement_key: str, limit: int, current_usage: int, requested: int)[source]
Bases:
EntitlementErrorRaised when a usage limit is exceeded.
- exception subscriptionkore.ValidationError(field: str, message: str)[source]
Bases:
DomainErrorRaised when validation fails.
- exception subscriptionkore.WebhookError(message: str, details: dict[str, Any] | None = None)[source]
Bases:
SubscriptionKoreErrorBase class for webhook errors.
- exception subscriptionkore.WebhookPayloadInvalidError(provider: str, reason: str)[source]
Bases:
WebhookErrorRaised when webhook payload cannot be parsed.
- exception subscriptionkore.WebhookProcessingError(event_id: str, reason: str)[source]
Bases:
WebhookErrorRaised when webhook processing fails.
- exception subscriptionkore.WebhookSignatureInvalidError(provider: str)[source]
Bases:
WebhookErrorRaised when webhook signature verification fails.
Configuration¶
Configuration management.
- class subscriptionkore.config.ChargebeeConfig(_case_sensitive: bool | None = None, _nested_model_default_partial_update: bool | None = None, _env_prefix: str | None = None, _env_file: DotenvType | None = PosixPath('.'), _env_file_encoding: str | None = None, _env_ignore_empty: bool | None = None, _env_nested_delimiter: str | None = None, _env_parse_none_str: str | None = None, _env_parse_enums: bool | None = None, _cli_prog_name: str | None = None, _cli_parse_args: bool | list[str] | tuple[str, ...] | None = None, _cli_settings_source: CliSettingsSource[Any] | None = None, _cli_parse_none_str: str | None = None, _cli_hide_none_type: bool | None = None, _cli_avoid_json: bool | None = None, _cli_enforce_required: bool | None = None, _cli_use_class_docs_for_groups: bool | None = None, _cli_exit_on_error: bool | None = None, _cli_prefix: str | None = None, _cli_flag_prefix_char: str | None = None, _cli_implicit_flags: bool | None = None, _cli_ignore_unknown_args: bool | None = None, _secrets_dir: PathType | None = None, *, site: str, api_key: str, webhook_username: str | None = None, webhook_password: str | None = None)[source]¶
Bases:
BaseSettingsChargebee provider configuration.
- api_key: str¶
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}¶
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[SettingsConfigDict] = {'arbitrary_types_allowed': True, 'case_sensitive': False, 'cli_avoid_json': False, 'cli_enforce_required': False, 'cli_exit_on_error': True, 'cli_flag_prefix_char': '-', 'cli_hide_none_type': False, 'cli_ignore_unknown_args': False, 'cli_implicit_flags': False, 'cli_parse_args': None, 'cli_parse_none_str': None, 'cli_prefix': '', 'cli_prog_name': None, 'cli_use_class_docs_for_groups': False, 'env_file': None, 'env_file_encoding': None, 'env_ignore_empty': False, 'env_nested_delimiter': None, 'env_parse_enums': None, 'env_parse_none_str': None, 'env_prefix': 'CHARGEBEE_', 'extra': 'forbid', 'json_file': None, 'json_file_encoding': None, 'nested_model_default_partial_update': False, 'protected_namespaces': ('model_', 'settings_'), 'secrets_dir': None, 'toml_file': None, 'validate_default': True, 'yaml_file': None, 'yaml_file_encoding': None}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'api_key': FieldInfo(annotation=str, required=True, description='Chargebee API key'), 'site': FieldInfo(annotation=str, required=True, description='Chargebee site name'), 'webhook_password': FieldInfo(annotation=Union[str, NoneType], required=False, default=None, description='Webhook basic auth password'), 'webhook_username': FieldInfo(annotation=Union[str, NoneType], required=False, default=None, description='Webhook basic auth username')}¶
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- site: str¶
- webhook_password: str | None¶
- webhook_username: str | None¶
- class subscriptionkore.config.LemonSqueezyConfig(_case_sensitive: bool | None = None, _nested_model_default_partial_update: bool | None = None, _env_prefix: str | None = None, _env_file: DotenvType | None = PosixPath('.'), _env_file_encoding: str | None = None, _env_ignore_empty: bool | None = None, _env_nested_delimiter: str | None = None, _env_parse_none_str: str | None = None, _env_parse_enums: bool | None = None, _cli_prog_name: str | None = None, _cli_parse_args: bool | list[str] | tuple[str, ...] | None = None, _cli_settings_source: CliSettingsSource[Any] | None = None, _cli_parse_none_str: str | None = None, _cli_hide_none_type: bool | None = None, _cli_avoid_json: bool | None = None, _cli_enforce_required: bool | None = None, _cli_use_class_docs_for_groups: bool | None = None, _cli_exit_on_error: bool | None = None, _cli_prefix: str | None = None, _cli_flag_prefix_char: str | None = None, _cli_implicit_flags: bool | None = None, _cli_ignore_unknown_args: bool | None = None, _secrets_dir: PathType | None = None, *, api_key: str, webhook_secret: str, store_id: str)[source]¶
Bases:
BaseSettingsLemonSqueezy provider configuration.
- api_key: str¶
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}¶
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[SettingsConfigDict] = {'arbitrary_types_allowed': True, 'case_sensitive': False, 'cli_avoid_json': False, 'cli_enforce_required': False, 'cli_exit_on_error': True, 'cli_flag_prefix_char': '-', 'cli_hide_none_type': False, 'cli_ignore_unknown_args': False, 'cli_implicit_flags': False, 'cli_parse_args': None, 'cli_parse_none_str': None, 'cli_prefix': '', 'cli_prog_name': None, 'cli_use_class_docs_for_groups': False, 'env_file': None, 'env_file_encoding': None, 'env_ignore_empty': False, 'env_nested_delimiter': None, 'env_parse_enums': None, 'env_parse_none_str': None, 'env_prefix': 'LEMONSQUEEZY_', 'extra': 'forbid', 'json_file': None, 'json_file_encoding': None, 'nested_model_default_partial_update': False, 'protected_namespaces': ('model_', 'settings_'), 'secrets_dir': None, 'toml_file': None, 'validate_default': True, 'yaml_file': None, 'yaml_file_encoding': None}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'api_key': FieldInfo(annotation=str, required=True, description='LemonSqueezy API key'), 'store_id': FieldInfo(annotation=str, required=True, description='LemonSqueezy store ID'), 'webhook_secret': FieldInfo(annotation=str, required=True, description='LemonSqueezy webhook signing secret')}¶
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- store_id: str¶
- webhook_secret: str¶
- class subscriptionkore.config.PaddleConfig(_case_sensitive: bool | None = None, _nested_model_default_partial_update: bool | None = None, _env_prefix: str | None = None, _env_file: DotenvType | None = PosixPath('.'), _env_file_encoding: str | None = None, _env_ignore_empty: bool | None = None, _env_nested_delimiter: str | None = None, _env_parse_none_str: str | None = None, _env_parse_enums: bool | None = None, _cli_prog_name: str | None = None, _cli_parse_args: bool | list[str] | tuple[str, ...] | None = None, _cli_settings_source: CliSettingsSource[Any] | None = None, _cli_parse_none_str: str | None = None, _cli_hide_none_type: bool | None = None, _cli_avoid_json: bool | None = None, _cli_enforce_required: bool | None = None, _cli_use_class_docs_for_groups: bool | None = None, _cli_exit_on_error: bool | None = None, _cli_prefix: str | None = None, _cli_flag_prefix_char: str | None = None, _cli_implicit_flags: bool | None = None, _cli_ignore_unknown_args: bool | None = None, _secrets_dir: PathType | None = None, *, api_key: str, webhook_secret: str, environment: Literal['sandbox', 'production'] = 'sandbox', seller_id: str | None = None)[source]¶
Bases:
BaseSettingsPaddle provider configuration.
- api_key: str¶
- environment: Literal['sandbox', 'production']¶
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}¶
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[SettingsConfigDict] = {'arbitrary_types_allowed': True, 'case_sensitive': False, 'cli_avoid_json': False, 'cli_enforce_required': False, 'cli_exit_on_error': True, 'cli_flag_prefix_char': '-', 'cli_hide_none_type': False, 'cli_ignore_unknown_args': False, 'cli_implicit_flags': False, 'cli_parse_args': None, 'cli_parse_none_str': None, 'cli_prefix': '', 'cli_prog_name': None, 'cli_use_class_docs_for_groups': False, 'env_file': None, 'env_file_encoding': None, 'env_ignore_empty': False, 'env_nested_delimiter': None, 'env_parse_enums': None, 'env_parse_none_str': None, 'env_prefix': 'PADDLE_', 'extra': 'forbid', 'json_file': None, 'json_file_encoding': None, 'nested_model_default_partial_update': False, 'protected_namespaces': ('model_', 'settings_'), 'secrets_dir': None, 'toml_file': None, 'validate_default': True, 'yaml_file': None, 'yaml_file_encoding': None}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'api_key': FieldInfo(annotation=str, required=True, description='Paddle API key'), 'environment': FieldInfo(annotation=Literal['sandbox', 'production'], required=False, default='sandbox'), 'seller_id': FieldInfo(annotation=Union[str, NoneType], required=False, default=None, description='Paddle seller/vendor ID'), 'webhook_secret': FieldInfo(annotation=str, required=True, description='Paddle webhook secret key')}¶
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- seller_id: str | None¶
- webhook_secret: str¶
- class subscriptionkore.config.StripeConfig(_case_sensitive: bool | None = None, _nested_model_default_partial_update: bool | None = None, _env_prefix: str | None = None, _env_file: DotenvType | None = PosixPath('.'), _env_file_encoding: str | None = None, _env_ignore_empty: bool | None = None, _env_nested_delimiter: str | None = None, _env_parse_none_str: str | None = None, _env_parse_enums: bool | None = None, _cli_prog_name: str | None = None, _cli_parse_args: bool | list[str] | tuple[str, ...] | None = None, _cli_settings_source: CliSettingsSource[Any] | None = None, _cli_parse_none_str: str | None = None, _cli_hide_none_type: bool | None = None, _cli_avoid_json: bool | None = None, _cli_enforce_required: bool | None = None, _cli_use_class_docs_for_groups: bool | None = None, _cli_exit_on_error: bool | None = None, _cli_prefix: str | None = None, _cli_flag_prefix_char: str | None = None, _cli_implicit_flags: bool | None = None, _cli_ignore_unknown_args: bool | None = None, _secrets_dir: PathType | None = None, *, api_key: str, webhook_secret: str, api_version: str = '2024-06-20')[source]¶
Bases:
BaseSettingsStripe provider configuration.
- api_key: str¶
- api_version: str¶
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}¶
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[SettingsConfigDict] = {'arbitrary_types_allowed': True, 'case_sensitive': False, 'cli_avoid_json': False, 'cli_enforce_required': False, 'cli_exit_on_error': True, 'cli_flag_prefix_char': '-', 'cli_hide_none_type': False, 'cli_ignore_unknown_args': False, 'cli_implicit_flags': False, 'cli_parse_args': None, 'cli_parse_none_str': None, 'cli_prefix': '', 'cli_prog_name': None, 'cli_use_class_docs_for_groups': False, 'env_file': None, 'env_file_encoding': None, 'env_ignore_empty': False, 'env_nested_delimiter': None, 'env_parse_enums': None, 'env_parse_none_str': None, 'env_prefix': 'STRIPE_', 'extra': 'forbid', 'json_file': None, 'json_file_encoding': None, 'nested_model_default_partial_update': False, 'protected_namespaces': ('model_', 'settings_'), 'secrets_dir': None, 'toml_file': None, 'validate_default': True, 'yaml_file': None, 'yaml_file_encoding': None}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'api_key': FieldInfo(annotation=str, required=True, description='Stripe secret API key'), 'api_version': FieldInfo(annotation=str, required=False, default='2024-06-20', description='Stripe API version'), 'webhook_secret': FieldInfo(annotation=str, required=True, description='Stripe webhook signing secret')}¶
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- webhook_secret: str¶
- class subscriptionkore.config.SubscriptionKoreConfig(_case_sensitive: bool | None = None, _nested_model_default_partial_update: bool | None = None, _env_prefix: str | None = None, _env_file: DotenvType | None = PosixPath('.'), _env_file_encoding: str | None = None, _env_ignore_empty: bool | None = None, _env_nested_delimiter: str | None = None, _env_parse_none_str: str | None = None, _env_parse_enums: bool | None = None, _cli_prog_name: str | None = None, _cli_parse_args: bool | list[str] | tuple[str, ...] | None = None, _cli_settings_source: CliSettingsSource[Any] | None = None, _cli_parse_none_str: str | None = None, _cli_hide_none_type: bool | None = None, _cli_avoid_json: bool | None = None, _cli_enforce_required: bool | None = None, _cli_use_class_docs_for_groups: bool | None = None, _cli_exit_on_error: bool | None = None, _cli_prefix: str | None = None, _cli_flag_prefix_char: str | None = None, _cli_implicit_flags: bool | None = None, _cli_ignore_unknown_args: bool | None = None, _secrets_dir: PathType | None = None, *, database_url: str, redis_url: str | None = None, stripe: StripeConfig | None = None, paddle: PaddleConfig | None = None, lemonsqueezy: LemonSqueezyConfig | None = None, chargebee: ChargebeeConfig | None = None, default_provider: ProviderType = ProviderType.STRIPE, webhook_processing: Literal['sync', 'async'] = 'sync', entitlement_cache_ttl: int = 300, processed_event_ttl_days: int = 7)[source]¶
Bases:
BaseSettingsMain configuration for SubscriptionKore.
- chargebee: ChargebeeConfig | None¶
- database_url: str¶
- default_provider: ProviderType¶
- entitlement_cache_ttl: int¶
- get_configured_providers() list[ProviderType][source]¶
Get list of configured providers.
- get_provider_config(provider: ProviderType) StripeConfig | PaddleConfig | LemonSqueezyConfig | ChargebeeConfig | None[source]¶
Get configuration for a specific provider.
- lemonsqueezy: LemonSqueezyConfig | None¶
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}¶
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[SettingsConfigDict] = {'arbitrary_types_allowed': True, 'case_sensitive': False, 'cli_avoid_json': False, 'cli_enforce_required': False, 'cli_exit_on_error': True, 'cli_flag_prefix_char': '-', 'cli_hide_none_type': False, 'cli_ignore_unknown_args': False, 'cli_implicit_flags': False, 'cli_parse_args': None, 'cli_parse_none_str': None, 'cli_prefix': '', 'cli_prog_name': None, 'cli_use_class_docs_for_groups': False, 'env_file': None, 'env_file_encoding': None, 'env_ignore_empty': False, 'env_nested_delimiter': '__', 'env_parse_enums': None, 'env_parse_none_str': None, 'env_prefix': 'SUBSCRIPTIONKORE_', 'extra': 'forbid', 'json_file': None, 'json_file_encoding': None, 'nested_model_default_partial_update': False, 'protected_namespaces': ('model_', 'settings_'), 'secrets_dir': None, 'toml_file': None, 'validate_default': True, 'yaml_file': None, 'yaml_file_encoding': None}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'chargebee': FieldInfo(annotation=Union[ChargebeeConfig, NoneType], required=False, default=None), 'database_url': FieldInfo(annotation=str, required=True, description='PostgreSQL async connection URL'), 'default_provider': FieldInfo(annotation=ProviderType, required=False, default=<ProviderType.STRIPE: 'stripe'>, description='Default payment provider to use'), 'entitlement_cache_ttl': FieldInfo(annotation=int, required=False, default=300, description='Entitlement cache TTL in seconds'), 'lemonsqueezy': FieldInfo(annotation=Union[LemonSqueezyConfig, NoneType], required=False, default=None), 'paddle': FieldInfo(annotation=Union[PaddleConfig, NoneType], required=False, default=None), 'processed_event_ttl_days': FieldInfo(annotation=int, required=False, default=7, description='Days to keep processed event records'), 'redis_url': FieldInfo(annotation=Union[str, NoneType], required=False, default=None, description='Redis connection URL'), 'stripe': FieldInfo(annotation=Union[StripeConfig, NoneType], required=False, default=None), 'webhook_processing': FieldInfo(annotation=Literal['sync', 'async'], required=False, default='sync', description='Webhook processing mode')}¶
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- paddle: PaddleConfig | None¶
- processed_event_ttl_days: int¶
- redis_url: str | None¶
- stripe: StripeConfig | None¶
- validate_default_provider_configured() SubscriptionKoreConfig[source]¶
Ensure default provider has configuration.
- webhook_processing: Literal['sync', 'async']¶
Core Models¶
Subscription domain model.
- class subscriptionkore.core.models.subscription.AppliedDiscount(*, discount_id: str, coupon_code: str | None = None, amount_off: Money | None = None, percent_off: Decimal | None = None, valid_until: datetime | None = None)[source]¶
Bases:
BaseModelDiscount applied to a subscriptionn.
- coupon_code: str | None¶
- discount_id: str¶
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}¶
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'amount_off': FieldInfo(annotation=Union[Money, NoneType], required=False, default=None), 'coupon_code': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'discount_id': FieldInfo(annotation=str, required=True), 'percent_off': FieldInfo(annotation=Union[Decimal, NoneType], required=False, default=None), 'valid_until': FieldInfo(annotation=Union[datetime, NoneType], required=False, default=None)}¶
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- percent_off: Decimal | None¶
- valid_until: datetime | None¶
- class subscriptionkore.core.models.subscription.PauseBehavior(*values)[source]¶
Bases:
StrEnumPause behavior options.
- KEEP_AS_DRAFT = 'keep_as_draft'¶
- MARK_UNCOLLECTIBLE = 'mark_uncollectible'¶
- VOID = 'void'¶
- class subscriptionkore.core.models.subscription.PauseConfig(*, resumes_at: datetime | None = None, behavior: PauseBehavior = PauseBehavior.VOID)[source]¶
Bases:
BaseModelSubscription pause configuration.
- behavior: PauseBehavior¶
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}¶
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'behavior': FieldInfo(annotation=PauseBehavior, required=False, default=<PauseBehavior.VOID: 'void'>), 'resumes_at': FieldInfo(annotation=Union[datetime, NoneType], required=False, default=None)}¶
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- resumes_at: datetime | None¶
- class subscriptionkore.core.models.subscription.Subscription(*, id: str = None, customer_id: str, plan_id: str, provider_ref: ProviderReference, status: SubscriptionStatus = SubscriptionStatus.INCOMPLETE, current_period: DateRange, trial_end: datetime | None = None, cancel_at_period_end: bool = False, canceled_at: datetime | None = None, ended_at: datetime | None = None, pause_collection: PauseConfig | None = None, discount: AppliedDiscount | None = None, quantity: int = 1, metadata: dict[str, Any] = None, created_at: datetime = None, updated_at: datetime = None)[source]¶
Bases:
BaseModelSubscription domain entity.
- apply_discount(discount: AppliedDiscount) None[source]¶
Apply a discount to the subscriptionn.
- cancel_at_period_end: bool¶
- canceled_at: datetime | None¶
- created_at: datetime¶
- customer_id: str¶
- discount: AppliedDiscount | None¶
- ended_at: datetime | None¶
- id: str¶
- metadata: dict[str, Any]¶
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}¶
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'cancel_at_period_end': FieldInfo(annotation=bool, required=False, default=False), 'canceled_at': FieldInfo(annotation=Union[datetime, NoneType], required=False, default=None), 'created_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method), 'current_period': FieldInfo(annotation=DateRange, required=True), 'customer_id': FieldInfo(annotation=str, required=True), 'discount': FieldInfo(annotation=Union[AppliedDiscount, NoneType], required=False, default=None), 'ended_at': FieldInfo(annotation=Union[datetime, NoneType], required=False, default=None), 'id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'pause_collection': FieldInfo(annotation=Union[PauseConfig, NoneType], required=False, default=None), 'plan_id': FieldInfo(annotation=str, required=True), 'provider_ref': FieldInfo(annotation=ProviderReference, required=True), 'quantity': FieldInfo(annotation=int, required=False, default=1), 'status': FieldInfo(annotation=SubscriptionStatus, required=False, default=<SubscriptionStatus.INCOMPLETE: 'incomplete'>), 'trial_end': FieldInfo(annotation=Union[datetime, NoneType], required=False, default=None), 'updated_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method)}¶
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- pause_collection: PauseConfig | None¶
- plan_id: str¶
- provider_ref: ProviderReference¶
- quantity: int¶
- status: SubscriptionStatus¶
- trial_end: datetime | None¶
- updated_at: datetime¶
- class subscriptionkore.core.models.subscription.SubscriptionStatus(*values)[source]¶
Bases:
StrEnumSubscription status values.
- ACTIVE = 'active'¶
- CANCELED = 'canceled'¶
- EXPIRED = 'expired'¶
- INCOMPLETE = 'incomplete'¶
- INCOMPLETE_EXPIRED = 'incomplete_expired'¶
- PAST_DUE = 'past_due'¶
- PAUSED = 'paused'¶
- TRIALING = 'trialing'¶
- UNPAID = 'unpaid'¶
Customer domain model.
- class subscriptionkore.core.models.customer.Address(*, line1: str | None = None, line2: str | None = None, city: str | None = None, state: str | None = None, postal_code: str | None = None, country: str | None = None)[source]¶
Bases:
BaseModelBilling address.
- city: str | None¶
- country: str | None¶
- line1: str | None¶
- line2: str | None¶
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}¶
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'city': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'country': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'line1': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'line2': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'postal_code': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'state': FieldInfo(annotation=Union[str, NoneType], required=False, default=None)}¶
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- postal_code: str | None¶
- state: str | None¶
- class subscriptionkore.core.models.customer.Customer(*, id: str = None, external_id: str, email: EmailStr, name: str | None = None, provider_refs: list[ProviderReference] = None, tax_info: TaxInfo | None = None, billing_address: Address | None = None, metadata: dict[str, Any] = None, created_at: datetime = None, updated_at: datetime = None)[source]¶
Bases:
BaseModelCustomer domain entity.
- add_provider_ref(ref: ProviderReference) None[source]¶
Add or update a provider reference.
- created_at: datetime¶
- email: EmailStr¶
- external_id: str¶
- get_provider_ref(provider_type: str) ProviderReference | None[source]¶
Get provider reference for a specific provider.
- id: str¶
- metadata: dict[str, Any]¶
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}¶
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'billing_address': FieldInfo(annotation=Union[Address, NoneType], required=False, default=None), 'created_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method), 'email': FieldInfo(annotation=EmailStr, required=True), 'external_id': FieldInfo(annotation=str, required=True), 'id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'name': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'provider_refs': FieldInfo(annotation=list[ProviderReference], required=False, default_factory=list), 'tax_info': FieldInfo(annotation=Union[TaxInfo, NoneType], required=False, default=None), 'updated_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method)}¶
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- name: str | None¶
- provider_refs: list[ProviderReference]¶
- update(email: str | None = None, name: str | None = None, tax_info: TaxInfo | None = None, billing_address: Address | None = None, metadata: dict[str, Any] | None = None) None[source]¶
Update customer fields.
- updated_at: datetime¶
- class subscriptionkore.core.models.customer.TaxInfo(*, tax_id: str | None = None, tax_id_type: str | None = None, tax_exempt: bool = False)[source]¶
Bases:
BaseModelCustomer tax information.
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}¶
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'tax_exempt': FieldInfo(annotation=bool, required=False, default=False), 'tax_id': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'tax_id_type': FieldInfo(annotation=Union[str, NoneType], required=False, default=None)}¶
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- tax_exempt: bool¶
- tax_id: str | None¶
- tax_id_type: str | None¶
Plan domain model.
- class subscriptionkore.core.models.plan.Plan(*, id: str = None, product_id: str, name: str, description: str | None = None, provider_refs: list[ProviderReference] = None, price: Money, billing_period: BillingPeriod, trial_period_days: int | None = None, entitlements: list[PlanEntitlement] = None, active: bool = True, tier: int = 0, metadata: dict[str, Any] = None, created_at: datetime = None, updated_at: datetime = None)[source]¶
Bases:
BaseModelPlan domain entity (a pricing tier for a product).
- active: bool¶
- add_provider_ref(ref: ProviderReference) None[source]¶
Add or update a provider reference.
- billing_period: BillingPeriod¶
- created_at: datetime¶
- description: str | None¶
- entitlements: list[PlanEntitlement]¶
- get_provider_ref(provider_type: str) ProviderReference | None[source]¶
Get provider reference for a specific provider.
- id: str¶
- metadata: dict[str, Any]¶
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}¶
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'active': FieldInfo(annotation=bool, required=False, default=True), 'billing_period': FieldInfo(annotation=BillingPeriod, required=True), 'created_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method), 'description': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'entitlements': FieldInfo(annotation=list[PlanEntitlement], required=False, default_factory=list), 'id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'name': FieldInfo(annotation=str, required=True), 'price': FieldInfo(annotation=Money, required=True), 'product_id': FieldInfo(annotation=str, required=True), 'provider_refs': FieldInfo(annotation=list[ProviderReference], required=False, default_factory=list), 'tier': FieldInfo(annotation=int, required=False, default=0, description='For upgrade/downgrade ordering'), 'trial_period_days': FieldInfo(annotation=Union[int, NoneType], required=False, default=None), 'updated_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method)}¶
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- name: str¶
- product_id: str¶
- provider_refs: list[ProviderReference]¶
- tier: int¶
- trial_period_days: int | None¶
- updated_at: datetime¶
- class subscriptionkore.core.models.plan.PlanEntitlement(*, entitlement_id: str, entitlement_key: str, value: bool | int | str | None, value_type: EntitlementValueType)[source]¶
Bases:
BaseModelEntitlement configuration for a plan.
- entitlement_id: str¶
- entitlement_key: str¶
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}¶
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'entitlement_id': FieldInfo(annotation=str, required=True), 'entitlement_key': FieldInfo(annotation=str, required=True), 'value': FieldInfo(annotation=Union[bool, int, str, NoneType], required=True), 'value_type': FieldInfo(annotation=EntitlementValueType, required=True)}¶
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- value: bool | int | str | None¶
- value_type: EntitlementValueType¶
Product domain model.
- class subscriptionkore.core.models.product.Product(*, id: str = None, name: str, description: str | None = None, provider_refs: list[ProviderReference] = None, active: bool = True, metadata: dict[str, Any] = None, created_at: datetime = None, updated_at: datetime = None)[source]¶
Bases:
BaseModelProduct domain entity.
- active: bool¶
- add_provider_ref(ref: ProviderReference) None[source]¶
Add or update a provider reference.
- created_at: datetime¶
- description: str | None¶
- get_provider_ref(provider_type: str) ProviderReference | None[source]¶
Get provider reference for a specific provider.
- id: str¶
- metadata: dict[str, Any]¶
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}¶
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'active': FieldInfo(annotation=bool, required=False, default=True), 'created_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method), 'description': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'name': FieldInfo(annotation=str, required=True), 'provider_refs': FieldInfo(annotation=list[ProviderReference], required=False, default_factory=list), 'updated_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method)}¶
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- name: str¶
- provider_refs: list[ProviderReference]¶
- updated_at: datetime¶
Invoice domain model.
- class subscriptionkore.core.models.invoice.Invoice(*, id: str = None, customer_id: str, subscriptionkore_id: str | None = None, provider_ref: ProviderReference, status: InvoiceStatus = InvoiceStatus.DRAFT, subtotal: Money, tax: Money = None, discount_amount: Money = None, total: Money, amount_paid: Money = None, amount_due: Money, currency: Currency = Currency.USD, line_items: list[InvoiceLineItem] = None, period: DateRange | None = None, due_date: datetime | None = None, paid_at: datetime | None = None, invoice_pdf_url: str | None = None, hosted_invoice_url: str | None = None, metadata: dict[str, Any] = None, created_at: datetime = None)[source]¶
Bases:
BaseModelInvoice domain entity.
- created_at: datetime¶
- customer_id: str¶
- due_date: datetime | None¶
- hosted_invoice_url: str | None¶
- id: str¶
- invoice_pdf_url: str | None¶
- line_items: list[InvoiceLineItem]¶
- metadata: dict[str, Any]¶
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}¶
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'amount_due': FieldInfo(annotation=Money, required=True), 'amount_paid': FieldInfo(annotation=Money, required=False, default_factory=<lambda>), 'created_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method), 'currency': FieldInfo(annotation=Currency, required=False, default=<Currency.USD: 'USD'>), 'customer_id': FieldInfo(annotation=str, required=True), 'discount_amount': FieldInfo(annotation=Money, required=False, default_factory=<lambda>), 'due_date': FieldInfo(annotation=Union[datetime, NoneType], required=False, default=None), 'hosted_invoice_url': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'invoice_pdf_url': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'line_items': FieldInfo(annotation=list[InvoiceLineItem], required=False, default_factory=list), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'paid_at': FieldInfo(annotation=Union[datetime, NoneType], required=False, default=None), 'period': FieldInfo(annotation=Union[DateRange, NoneType], required=False, default=None), 'provider_ref': FieldInfo(annotation=ProviderReference, required=True), 'status': FieldInfo(annotation=InvoiceStatus, required=False, default=<InvoiceStatus.DRAFT: 'draft'>), 'subscriptionkore_id': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'subtotal': FieldInfo(annotation=Money, required=True), 'tax': FieldInfo(annotation=Money, required=False, default_factory=<lambda>), 'total': FieldInfo(annotation=Money, required=True)}¶
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- paid_at: datetime | None¶
- provider_ref: ProviderReference¶
- status: InvoiceStatus¶
- subscriptionkore_id: str | None¶
- class subscriptionkore.core.models.invoice.InvoiceLineItem(*, id: str = None, description: str, quantity: int = 1, unit_amount: Money, amount: Money, period: DateRange | None = None, proration: bool = False, metadata: dict[str, Any] = None)[source]¶
Bases:
BaseModelLine item on an invoice.
- description: str¶
- id: str¶
- metadata: dict[str, Any]¶
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}¶
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'amount': FieldInfo(annotation=Money, required=True), 'description': FieldInfo(annotation=str, required=True), 'id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'period': FieldInfo(annotation=Union[DateRange, NoneType], required=False, default=None), 'proration': FieldInfo(annotation=bool, required=False, default=False), 'quantity': FieldInfo(annotation=int, required=False, default=1), 'unit_amount': FieldInfo(annotation=Money, required=True)}¶
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- proration: bool¶
- quantity: int¶
- class subscriptionkore.core.models.invoice.InvoiceStatus(*values)[source]¶
Bases:
StrEnumInvoice status values.
- DRAFT = 'draft'¶
- OPEN = 'open'¶
- PAID = 'paid'¶
- UNCOLLECTIBLE = 'uncollectible'¶
- VOID = 'void'¶
Payment event domain model.
- class subscriptionkore.core.models.payment_event.PaymentEvent(*, id: str = None, provider_ref: ProviderReference, customer_id: str, subscriptionkore_id: str | None = None, invoice_id: str | None = None, event_type: PaymentEventType, amount: Money, status: PaymentStatus, failure_reason: str | None = None, failure_code: str | None = None, payment_method_type: str | None = None, payment_method_last4: str | None = None, occurred_at: datetime = None, metadata: dict[str, Any] = None)[source]¶
Bases:
BaseModelPayment event domain entity.
- customer_id: str¶
- event_type: PaymentEventType¶
- failure_code: str | None¶
- failure_reason: str | None¶
- id: str¶
- invoice_id: str | None¶
- metadata: dict[str, Any]¶
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}¶
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'amount': FieldInfo(annotation=Money, required=True), 'customer_id': FieldInfo(annotation=str, required=True), 'event_type': FieldInfo(annotation=PaymentEventType, required=True), 'failure_code': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'failure_reason': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'invoice_id': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'occurred_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method), 'payment_method_last4': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'payment_method_type': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'provider_ref': FieldInfo(annotation=ProviderReference, required=True), 'status': FieldInfo(annotation=PaymentStatus, required=True), 'subscriptionkore_id': FieldInfo(annotation=Union[str, NoneType], required=False, default=None)}¶
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- occurred_at: datetime¶
- payment_method_last4: str | None¶
- payment_method_type: str | None¶
- provider_ref: ProviderReference¶
- status: PaymentStatus¶
- subscriptionkore_id: str | None¶
- class subscriptionkore.core.models.payment_event.PaymentEventType(*values)[source]¶
Bases:
StrEnumPayment event types.
- PAYMENT_DISPUTED = 'payment_disputed'¶
- PAYMENT_FAILED = 'payment_failed'¶
- PAYMENT_REFUNDED = 'payment_refunded'¶
- PAYMENT_SUCCEEDED = 'payment_succeeded'¶
- class subscriptionkore.core.models.payment_event.PaymentStatus(*values)[source]¶
Bases:
StrEnumPayment status values.
- DISPUTED = 'disputed'¶
- FAILED = 'failed'¶
- PARTIALLY_REFUNDED = 'partially_refunded'¶
- PENDING = 'pending'¶
- REFUNDED = 'refunded'¶
- SUCCEEDED = 'succeeded'¶
Entitlement domain models.
- class subscriptionkore.core.models.entitlement.CustomerEntitlement(*, customer_id: str, entitlement_key: str, current_value: bool | int | str, value_type: EntitlementValueType, source: EntitlementSource, expires_at: datetime | None = None, subscription_id: str | None = None, plan_id: str | None = None)[source]¶
Bases:
BaseModelResolved entitlement for a customer.
- current_value: bool | int | str¶
- customer_id: str¶
- entitlement_key: str¶
- expires_at: datetime | None¶
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}¶
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'current_value': FieldInfo(annotation=Union[bool, int, str], required=True), 'customer_id': FieldInfo(annotation=str, required=True), 'entitlement_key': FieldInfo(annotation=str, required=True), 'expires_at': FieldInfo(annotation=Union[datetime, NoneType], required=False, default=None), 'plan_id': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'source': FieldInfo(annotation=EntitlementSource, required=True), 'subscription_id': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'value_type': FieldInfo(annotation=EntitlementValueType, required=True)}¶
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- plan_id: str | None¶
- source: EntitlementSource¶
- subscription_id: str | None¶
- value_type: EntitlementValueType¶
- class subscriptionkore.core.models.entitlement.Entitlement(*, id: str = None, key: str, name: str, description: str | None = None, value_type: EntitlementValueType, default_value: bool | int | str | None = None, metadata: dict[str, Any] = None, created_at: datetime = None, updated_at: datetime = None)[source]¶
Bases:
BaseModelEntitlement definition entity.
- created_at: datetime¶
- default_value: bool | int | str | None¶
- description: str | None¶
- id: str¶
- key: str¶
- metadata: dict[str, Any]¶
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}¶
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'created_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method), 'default_value': FieldInfo(annotation=Union[bool, int, str, NoneType], required=False, default=None), 'description': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'key': FieldInfo(annotation=str, required=True), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'name': FieldInfo(annotation=str, required=True), 'updated_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method), 'value_type': FieldInfo(annotation=EntitlementValueType, required=True)}¶
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- name: str¶
- updated_at: datetime¶
- value_type: EntitlementValueType¶
- class subscriptionkore.core.models.entitlement.EntitlementOverride(*, id: str = None, customer_id: str, entitlement_key: str, value: bool | int | str, value_type: EntitlementValueType, reason: str | None = None, expires_at: datetime | None = None, created_by: str | None = None, created_at: datetime = None)[source]¶
Bases:
BaseModelManual entitlement override for a customer.
- created_at: datetime¶
- created_by: str | None¶
- customer_id: str¶
- entitlement_key: str¶
- expires_at: datetime | None¶
- id: str¶
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}¶
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'created_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method), 'created_by': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'customer_id': FieldInfo(annotation=str, required=True), 'entitlement_key': FieldInfo(annotation=str, required=True), 'expires_at': FieldInfo(annotation=Union[datetime, NoneType], required=False, default=None), 'id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'reason': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'value': FieldInfo(annotation=Union[bool, int, str], required=True), 'value_type': FieldInfo(annotation=EntitlementValueType, required=True)}¶
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- reason: str | None¶
- value: bool | int | str¶
- value_type: EntitlementValueType¶
Value Objects¶
Value objects for the domain layer.
- class subscriptionkore.core.models.value_objects.BillingPeriod(*, interval: Interval, interval_count: Annotated[int, Ge(ge=1)] = 1, anchor_date: datetime | None = None)[source]¶
Bases:
BaseModelBilling period configuration.
- anchor_date: datetime | None¶
- property display_name: str¶
- interval_count: int¶
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}¶
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'anchor_date': FieldInfo(annotation=Union[datetime, NoneType], required=False, default=None), 'interval': FieldInfo(annotation=Interval, required=True), 'interval_count': FieldInfo(annotation=int, required=False, default=1, metadata=[Ge(ge=1)])}¶
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- classmethod monthly() BillingPeriod[source]¶
- classmethod weekly() BillingPeriod[source]¶
- classmethod yearly() BillingPeriod[source]¶
- class subscriptionkore.core.models.value_objects.Currency(*values)[source]¶
Bases:
StrEnumISO 4217 currency codes.
- AUD = 'AUD'¶
- BRL = 'BRL'¶
- CAD = 'CAD'¶
- CHF = 'CHF'¶
- EUR = 'EUR'¶
- GBP = 'GBP'¶
- INR = 'INR'¶
- JPY = 'JPY'¶
- MXN = 'MXN'¶
- USD = 'USD'¶
- class subscriptionkore.core.models.value_objects.DateRange(*, start: datetime, end: datetime | None = None)[source]¶
Bases:
BaseModelDate range with start and optional end.
- end: datetime | None¶
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}¶
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'end': FieldInfo(annotation=Union[datetime, NoneType], required=False, default=None), 'start': FieldInfo(annotation=datetime, required=True)}¶
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- start: datetime¶
- class subscriptionkore.core.models.value_objects.Interval(*values)[source]¶
Bases:
StrEnumBilling interval types.
- DAY = 'day'¶
- MONTH = 'month'¶
- WEEK = 'week'¶
- YEAR = 'year'¶
- class subscriptionkore.core.models.value_objects.Money(*, amount: Decimal, currency: Currency = Currency.USD)[source]¶
Bases:
BaseModelImmutable monetary value with currency.
- amount: Decimal¶
- classmethod from_cents(cents: int, currency: Currency = Currency.USD) Money[source]¶
Create Money from minor units (cents).
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}¶
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'amount': FieldInfo(annotation=Decimal, required=True, description='Amount in major currency units'), 'currency': FieldInfo(annotation=Currency, required=False, default=<Currency.USD: 'USD'>)}¶
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- class subscriptionkore.core.models.value_objects.ProviderReference(*, provider: ProviderType, external_id: str, metadata: dict[str, Any] = None)[source]¶
Bases:
BaseModelReference to an entity in a payment provider.
- external_id: str¶
- metadata: dict[str, Any]¶
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}¶
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'external_id': FieldInfo(annotation=str, required=True), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'provider': FieldInfo(annotation=ProviderType, required=True)}¶
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- provider: ProviderType¶
Events¶
Domain events.
- class subscriptionkore.core.events.CustomerCreated(*, event_id: str = None, event_type: str = 'CustomerCreated', occurred_at: datetime = None, metadata: dict[str, Any] = None, customer: Customer)[source]
Bases:
DomainEventEmitted when a customer is created.
- customer: Customer
- event_id: str
- event_type: str
- metadata: dict[str, Any]
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'customer': FieldInfo(annotation=Customer, required=True), 'event_id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'event_type': FieldInfo(annotation=str, required=False, default='CustomerCreated'), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'occurred_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- occurred_at: datetime
- class subscriptionkore.core.events.CustomerUpdated(*, event_id: str = None, event_type: str = 'CustomerUpdated', occurred_at: datetime = None, metadata: dict[str, Any] = None, customer: Customer, changed_fields: list[str])[source]
Bases:
DomainEventEmitted when a customer is updated.
- changed_fields: list[str]
- customer: Customer
- event_id: str
- event_type: str
- metadata: dict[str, Any]
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'changed_fields': FieldInfo(annotation=list[str], required=True), 'customer': FieldInfo(annotation=Customer, required=True), 'event_id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'event_type': FieldInfo(annotation=str, required=False, default='CustomerUpdated'), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'occurred_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- occurred_at: datetime
- class subscriptionkore.core.events.DomainEvent(*, event_id: str = None, event_type: str = '', occurred_at: datetime = None, metadata: dict[str, Any] = None)[source]
Bases:
BaseModelBase class for all domain events.
- event_id: str
- event_type: str
- metadata: dict[str, Any]
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'event_id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'event_type': FieldInfo(annotation=str, required=False, default='SubscriptionPlanChanged'), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'occurred_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- occurred_at: datetime
- class subscriptionkore.core.events.InvoiceCreated(*, event_id: str = None, event_type: str = 'InvoiceCreated', occurred_at: datetime = None, metadata: dict[str, Any] = None, invoice: Invoice, customer_id: str, subscription_id: str | None = None)[source]
Bases:
DomainEventEmitted when an invoice is created.
- customer_id: str
- event_id: str
- event_type: str
- invoice: Invoice
- metadata: dict[str, Any]
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'customer_id': FieldInfo(annotation=str, required=True), 'event_id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'event_type': FieldInfo(annotation=str, required=False, default='InvoiceCreated'), 'invoice': FieldInfo(annotation=Invoice, required=True), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'occurred_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method), 'subscription_id': FieldInfo(annotation=Union[str, NoneType], required=False, default=None)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- occurred_at: datetime
- subscription_id: str | None
- class subscriptionkore.core.events.InvoicePaid(*, event_id: str = None, event_type: str = 'InvoicePaid', occurred_at: datetime = None, metadata: dict[str, Any] = None, invoice: Invoice, customer_id: str, subscription_id: str | None = None, amount_paid: Money)[source]
Bases:
DomainEventEmitted when an invoice is paid.
- amount_paid: Money
- customer_id: str
- event_id: str
- event_type: str
- invoice: Invoice
- metadata: dict[str, Any]
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'amount_paid': FieldInfo(annotation=Money, required=True), 'customer_id': FieldInfo(annotation=str, required=True), 'event_id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'event_type': FieldInfo(annotation=str, required=False, default='InvoicePaid'), 'invoice': FieldInfo(annotation=Invoice, required=True), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'occurred_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method), 'subscription_id': FieldInfo(annotation=Union[str, NoneType], required=False, default=None)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- occurred_at: datetime
- subscription_id: str | None
- class subscriptionkore.core.events.PaymentFailed(*, event_id: str = None, event_type: str = 'PaymentFailed', occurred_at: datetime = None, metadata: dict[str, Any] = None, payment_event: PaymentEvent, customer_id: str, subscription_id: str | None = None, invoice_id: str | None = None, amount: Money, failure_reason: str | None = None, failure_code: str | None = None, attempt_count: int = 1)[source]
Bases:
DomainEventEmitted when a payment fails.
- amount: Money
- attempt_count: int
- customer_id: str
- event_id: str
- event_type: str
- failure_code: str | None
- failure_reason: str | None
- invoice_id: str | None
- metadata: dict[str, Any]
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'amount': FieldInfo(annotation=Money, required=True), 'attempt_count': FieldInfo(annotation=int, required=False, default=1), 'customer_id': FieldInfo(annotation=str, required=True), 'event_id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'event_type': FieldInfo(annotation=str, required=False, default='PaymentFailed'), 'failure_code': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'failure_reason': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'invoice_id': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'occurred_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method), 'payment_event': FieldInfo(annotation=PaymentEvent, required=True), 'subscription_id': FieldInfo(annotation=Union[str, NoneType], required=False, default=None)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- occurred_at: datetime
- payment_event: PaymentEvent
- subscription_id: str | None
- class subscriptionkore.core.events.PaymentSucceeded(*, event_id: str = None, event_type: str = 'PaymentSucceeded', occurred_at: datetime = None, metadata: dict[str, Any] = None, payment_event: PaymentEvent, customer_id: str, subscription_id: str | None = None, invoice_id: str | None = None, amount: Money)[source]
Bases:
DomainEventEmitted when a payment succeeds.
- amount: Money
- customer_id: str
- event_id: str
- event_type: str
- invoice_id: str | None
- metadata: dict[str, Any]
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'amount': FieldInfo(annotation=Money, required=True), 'customer_id': FieldInfo(annotation=str, required=True), 'event_id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'event_type': FieldInfo(annotation=str, required=False, default='PaymentSucceeded'), 'invoice_id': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'occurred_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method), 'payment_event': FieldInfo(annotation=PaymentEvent, required=True), 'subscription_id': FieldInfo(annotation=Union[str, NoneType], required=False, default=None)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- occurred_at: datetime
- payment_event: PaymentEvent
- subscription_id: str | None
- class subscriptionkore.core.events.SubscriptionActivated(*, event_id: str = None, event_type: str = 'SubscriptionActivated', occurred_at: datetime = None, metadata: dict[str, Any] = None, subscriptionkore: Subscription, customer_id: str, plan_id: str)[source]
Bases:
DomainEventEmitted when a subscriptionkore becomes active.
- customer_id: str
- event_id: str
- event_type: str
- metadata: dict[str, Any]
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'customer_id': FieldInfo(annotation=str, required=True), 'event_id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'event_type': FieldInfo(annotation=str, required=False, default='SubscriptionActivated'), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'occurred_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method), 'plan_id': FieldInfo(annotation=str, required=True), 'subscriptionkore': FieldInfo(annotation=Subscription, required=True)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- occurred_at: datetime
- plan_id: str
- subscriptionkore: Subscription
- class subscriptionkore.core.events.SubscriptionCanceled(*, event_id: str = None, event_type: str = 'SubscriptionCanceled', occurred_at: datetime = None, metadata: dict[str, Any] = None, subscriptionkore: Subscription, customer_id: str, plan_id: str, immediate: bool, reason: str | None = None)[source]
Bases:
DomainEventEmitted when a subscriptionkore is canceled.
- customer_id: str
- event_id: str
- event_type: str
- immediate: bool
- metadata: dict[str, Any]
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'customer_id': FieldInfo(annotation=str, required=True), 'event_id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'event_type': FieldInfo(annotation=str, required=False, default='SubscriptionCanceled'), 'immediate': FieldInfo(annotation=bool, required=True), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'occurred_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method), 'plan_id': FieldInfo(annotation=str, required=True), 'reason': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'subscriptionkore': FieldInfo(annotation=Subscription, required=True)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- occurred_at: datetime
- plan_id: str
- reason: str | None
- subscriptionkore: Subscription
- class subscriptionkore.core.events.SubscriptionCreated(*, event_id: str = None, event_type: str = 'SubscriptionCreated', occurred_at: datetime = None, metadata: dict[str, Any] = None, subscriptionkore: Subscription, customer_id: str, plan_id: str)[source]
Bases:
DomainEventEmitted when a subscriptionkore is created.
- customer_id: str
- event_id: str
- event_type: str
- metadata: dict[str, Any]
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'customer_id': FieldInfo(annotation=str, required=True), 'event_id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'event_type': FieldInfo(annotation=str, required=False, default='SubscriptionCreated'), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'occurred_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method), 'plan_id': FieldInfo(annotation=str, required=True), 'subscriptionkore': FieldInfo(annotation=Subscription, required=True)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- occurred_at: datetime
- plan_id: str
- subscriptionkore: Subscription
- class subscriptionkore.core.events.SubscriptionPastDue(*, event_id: str = None, event_type: str = 'SubscriptionPastDue', occurred_at: datetime = None, metadata: dict[str, Any] = None, subscriptionkore: Subscription, customer_id: str, invoice_id: str | None = None)[source]
Bases:
DomainEventEmitted when a subscriptionkore becomes past due.
- customer_id: str
- event_id: str
- event_type: str
- invoice_id: str | None
- metadata: dict[str, Any]
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'customer_id': FieldInfo(annotation=str, required=True), 'event_id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'event_type': FieldInfo(annotation=str, required=False, default='SubscriptionPastDue'), 'invoice_id': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'occurred_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method), 'subscriptionkore': FieldInfo(annotation=Subscription, required=True)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- occurred_at: datetime
- subscriptionkore: Subscription
- class subscriptionkore.core.events.SubscriptionPaused(*, event_id: str = None, event_type: str = 'SubscriptionPaused', occurred_at: datetime = None, metadata: dict[str, Any] = None, subscriptionkore: Subscription, customer_id: str, resumes_at: datetime | None = None)[source]
Bases:
DomainEventEmitted when a subscriptionkore is paused.
- customer_id: str
- event_id: str
- event_type: str
- metadata: dict[str, Any]
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'customer_id': FieldInfo(annotation=str, required=True), 'event_id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'event_type': FieldInfo(annotation=str, required=False, default='SubscriptionPaused'), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'occurred_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method), 'resumes_at': FieldInfo(annotation=Union[datetime, NoneType], required=False, default=None), 'subscriptionkore': FieldInfo(annotation=Subscription, required=True)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- occurred_at: datetime
- resumes_at: datetime | None
- subscriptionkore: Subscription
- class subscriptionkore.core.events.SubscriptionPlanChanged(*, event_id: str = None, event_type: str = 'SubscriptionPlanChanged', occurred_at: datetime = None, metadata: dict[str, Any] = None, subscriptionkore: Subscription, customer_id: str, previous_plan_id: str, new_plan_id: str, is_upgrade: bool)[source]
Bases:
DomainEventEmitted when subscriptionkore plan is changed.
- customer_id: str
- event_id: str
- event_type: str
- is_upgrade: bool
- metadata: dict[str, Any]
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'customer_id': FieldInfo(annotation=str, required=True), 'event_id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'event_type': FieldInfo(annotation=str, required=False, default='SubscriptionPlanChanged'), 'is_upgrade': FieldInfo(annotation=bool, required=True), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'new_plan_id': FieldInfo(annotation=str, required=True), 'occurred_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method), 'previous_plan_id': FieldInfo(annotation=str, required=True), 'subscriptionkore': FieldInfo(annotation=Subscription, required=True)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- new_plan_id: str
- occurred_at: datetime
- previous_plan_id: str
- subscriptionkore: Subscription
- class subscriptionkore.core.events.SubscriptionResumed(*, event_id: str = None, event_type: str = 'SubscriptionResumed', occurred_at: datetime = None, metadata: dict[str, Any] = None, subscriptionkore: Subscription, customer_id: str)[source]
Bases:
DomainEventEmitted when a subscriptionkore is resumed.
- customer_id: str
- event_id: str
- event_type: str
- metadata: dict[str, Any]
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'customer_id': FieldInfo(annotation=str, required=True), 'event_id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'event_type': FieldInfo(annotation=str, required=False, default='SubscriptionResumed'), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'occurred_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method), 'subscriptionkore': FieldInfo(annotation=Subscription, required=True)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- occurred_at: datetime
- subscriptionkore: Subscription
- class subscriptionkore.core.events.SubscriptionTrialEnded(*, event_id: str = None, event_type: str = 'SubscriptionTrialEnded', occurred_at: datetime = None, metadata: dict[str, Any] = None, subscriptionkore: Subscription, customer_id: str, converted: bool)[source]
Bases:
DomainEventEmitted when a trial ends.
- converted: bool
- customer_id: str
- event_id: str
- event_type: str
- metadata: dict[str, Any]
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'converted': FieldInfo(annotation=bool, required=True), 'customer_id': FieldInfo(annotation=str, required=True), 'event_id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'event_type': FieldInfo(annotation=str, required=False, default='SubscriptionTrialEnded'), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'occurred_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method), 'subscriptionkore': FieldInfo(annotation=Subscription, required=True)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- occurred_at: datetime
- subscriptionkore: Subscription
- class subscriptionkore.core.events.SubscriptionTrialStarted(*, event_id: str = None, event_type: str = 'SubscriptionTrialStarted', occurred_at: datetime = None, metadata: dict[str, Any] = None, subscriptionkore: Subscription, customer_id: str, trial_end: datetime)[source]
Bases:
DomainEventEmitted when a trial starts.
- customer_id: str
- event_id: str
- event_type: str
- metadata: dict[str, Any]
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'customer_id': FieldInfo(annotation=str, required=True), 'event_id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'event_type': FieldInfo(annotation=str, required=False, default='SubscriptionTrialStarted'), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'occurred_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method), 'subscriptionkore': FieldInfo(annotation=Subscription, required=True), 'trial_end': FieldInfo(annotation=datetime, required=True)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- occurred_at: datetime
- subscriptionkore: Subscription
- trial_end: datetime
- class subscriptionkore.core.events.SubscriptionUpdated(*, event_id: str = None, event_type: str = 'SubscriptionUpdated', occurred_at: datetime = None, metadata: dict[str, Any] = None, subscriptionkore: Subscription, customer_id: str, changed_fields: list[str])[source]
Bases:
DomainEventEmitted when a subscriptionkore is updated.
- changed_fields: list[str]
- customer_id: str
- event_id: str
- event_type: str
- metadata: dict[str, Any]
- model_computed_fields: ClassVar[Dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[Dict[str, FieldInfo]] = {'changed_fields': FieldInfo(annotation=list[str], required=True), 'customer_id': FieldInfo(annotation=str, required=True), 'event_id': FieldInfo(annotation=str, required=False, default_factory=<lambda>), 'event_type': FieldInfo(annotation=str, required=False, default='SubscriptionUpdated'), 'metadata': FieldInfo(annotation=dict[str, Any], required=False, default_factory=dict), 'occurred_at': FieldInfo(annotation=datetime, required=False, default_factory=builtin_function_or_method), 'subscriptionkore': FieldInfo(annotation=Subscription, required=True)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__ from Pydantic V1.
- occurred_at: datetime
- subscriptionkore: Subscription
Exceptions¶
Domain exceptions.
- exception subscriptionkore.core.exceptions.ConfigurationError(message: str, details: dict[str, Any] | None = None)[source]¶
Bases:
SubscriptionKoreErrorBase class for configuration errors.
- exception subscriptionkore.core.exceptions.DomainError(message: str, details: dict[str, Any] | None = None)[source]¶
Bases:
SubscriptionKoreErrorBase class for domain errors.
- exception subscriptionkore.core.exceptions.DuplicateEntityError(entity_type: str, identifier: str)[source]¶
Bases:
DomainErrorRaised when attempting to create a duplicate entity.
- exception subscriptionkore.core.exceptions.EntitlementError(message: str, details: dict[str, Any] | None = None)[source]¶
Bases:
SubscriptionKoreErrorBase class for entitlement errors.
- exception subscriptionkore.core.exceptions.EntitlementNotFoundError(key: str)[source]¶
Bases:
EntitlementErrorRaised when an entitlement is not found.
- exception subscriptionkore.core.exceptions.EntityNotFoundError(entity_type: str, entity_id: str)[source]¶
Bases:
DomainErrorRaised when an entity is not found.
- exception subscriptionkore.core.exceptions.InvalidConfigurationError(message: str, details: dict[str, Any] | None = None)[source]¶
Bases:
ConfigurationErrorRaised when configuration is invalid.
- exception subscriptionkore.core.exceptions.InvalidStateTransitionError(from_state: SubscriptionStatus, to_state: SubscriptionStatus, reason: str | None = None)[source]¶
Bases:
DomainErrorRaised when an invalid state transition is attempted.
- exception subscriptionkore.core.exceptions.MissingProviderCredentialsError(provider: str, missing_fields: list[str])[source]¶
Bases:
ConfigurationErrorRaised when provider credentials are missing.
- exception subscriptionkore.core.exceptions.ProviderAPIError(message: str, provider: str, status_code: int, provider_message: str | None = None, provider_code: str | None = None)[source]¶
Bases:
ProviderErrorRaised for non-recoverable API errors from providers.
- exception subscriptionkore.core.exceptions.ProviderAuthenticationError(provider: str, message: str | None = None)[source]¶
Bases:
ProviderErrorRaised when authentication fails. Non-recoverable.
- exception subscriptionkore.core.exceptions.ProviderError(message: str, provider: str, details: dict[str, Any] | None = None)[source]¶
Bases:
SubscriptionKoreErrorBase class for provider errors.
- exception subscriptionkore.core.exceptions.ProviderNetworkError(provider: str, original_error: Exception)[source]¶
Bases:
ProviderErrorRaised for network errors. Recoverable with retry.
- exception subscriptionkore.core.exceptions.ProviderRateLimitError(provider: str, retry_after: int | None = None)[source]¶
Bases:
ProviderErrorRaised when provider rate limit is exceeded. Recoverable with retry.
- exception subscriptionkore.core.exceptions.RepositoryError(operation: str, entity_type: str, original_error: Exception)[source]¶
Bases:
SubscriptionKoreErrorRaised when a repository operation fails.
- exception subscriptionkore.core.exceptions.SubscriptionKoreError(message: str, details: dict[str, Any] | None = None)[source]¶
Bases:
ExceptionBase exception for all subscriptionkore errors.
- exception subscriptionkore.core.exceptions.UsageLimitExceededError(entitlement_key: str, limit: int, current_usage: int, requested: int)[source]¶
Bases:
EntitlementErrorRaised when a usage limit is exceeded.
- exception subscriptionkore.core.exceptions.ValidationError(field: str, message: str)[source]¶
Bases:
DomainErrorRaised when validation fails.
- exception subscriptionkore.core.exceptions.WebhookError(message: str, details: dict[str, Any] | None = None)[source]¶
Bases:
SubscriptionKoreErrorBase class for webhook errors.
- exception subscriptionkore.core.exceptions.WebhookPayloadInvalidError(provider: str, reason: str)[source]¶
Bases:
WebhookErrorRaised when webhook payload cannot be parsed.
- exception subscriptionkore.core.exceptions.WebhookProcessingError(event_id: str, reason: str)[source]¶
Bases:
WebhookErrorRaised when webhook processing fails.
- exception subscriptionkore.core.exceptions.WebhookSignatureInvalidError(provider: str)[source]¶
Bases:
WebhookErrorRaised when webhook signature verification fails.
Adapters¶
Stripe adapter.
- class subscriptionkore.adapters.stripe.StripeAdapter(config: StripeConfig)[source]¶
Bases:
PaymentProviderPortStripe payment provider implementation.
- BASE_URL = 'https://api.stripe.com/v1'¶
- INVOICE_STATUS_MAP = {'draft': InvoiceStatus.DRAFT, 'open': InvoiceStatus.OPEN, 'paid': InvoiceStatus.PAID, 'uncollectible': InvoiceStatus.UNCOLLECTIBLE, 'void': InvoiceStatus.VOID}¶
- STATUS_MAP = {'active': SubscriptionStatus.ACTIVE, 'canceled': SubscriptionStatus.CANCELED, 'incomplete': SubscriptionStatus.INCOMPLETE, 'incomplete_expired': SubscriptionStatus.INCOMPLETE_EXPIRED, 'past_due': SubscriptionStatus.PAST_DUE, 'paused': SubscriptionStatus.PAUSED, 'trialing': SubscriptionStatus.TRIALING, 'unpaid': SubscriptionStatus.UNPAID}¶
- async apply_discount(subscriptionkore_provider_ref: ProviderReference, discount: DiscountRequest) Subscription[source]¶
Apply a discount to a subscriptionkore.
- async cancel_subscriptionkore(subscriptionkore_provider_ref: ProviderReference, immediate: bool = False) Subscription[source]¶
Cancel a subscriptionkore.
- property capabilities: ProviderCapabilities¶
Return provider capabilities.
- async change_plan(request: ChangePlanRequest, subscriptionkore_provider_ref: ProviderReference, new_plan_provider_ref: ProviderReference) Subscription[source]¶
Change subscriptionkore plan (upgrade/downgrade).
- async create_checkout_session(request: CheckoutRequest, plan_provider_ref: ProviderReference, customer_provider_ref: ProviderReference | None = None) CheckoutSession[source]¶
Create a checkout session.
- async create_customer(customer: Customer) ProviderReference[source]¶
Create a customer in the provider.
- async create_portal_session(customer_provider_ref: ProviderReference, return_url: str) PortalSession[source]¶
Create a customer portal session.
- async create_subscriptionkore(request: CreateSubscriptionRequest, customer_provider_ref: ProviderReference, plan_provider_ref: ProviderReference) Subscription[source]¶
Create a subscriptionkore.
- async delete_customer(provider_ref: ProviderReference) None[source]¶
Delete a customer from the provider.
- async get_customer(provider_ref: ProviderReference) Customer[source]¶
Get a customer from the provider.
- async get_invoice(provider_ref: ProviderReference) Invoice[source]¶
Get an invoice from the provider.
- async get_subscriptionkore(provider_ref: ProviderReference) Subscription[source]¶
Get a subscriptionkore from the provider.
- async get_upcoming_invoice(subscriptionkore_provider_ref: ProviderReference) Invoice | None[source]¶
Get upcoming invoice for a subscriptionkore.
- async list_invoices(customer_provider_ref: ProviderReference, limit: int = 10, starting_after: str | None = None) list[Invoice][source]¶
List invoices for a customer.
- async parse_webhook(payload: bytes, headers: dict[str, str]) ProviderWebhookEvent[source]¶
Parse Stripe webhook payload.
- async pause_subscriptionkore(subscriptionkore_provider_ref: ProviderReference, resumes_at: datetime | None = None) Subscription[source]¶
Pause a subscriptionkore.
- async preview_plan_change(request: ChangePlanRequest, subscriptionkore_provider_ref: ProviderReference, new_plan_provider_ref: ProviderReference) ChangePreview[source]¶
Preview plan change costs.
- property provider_type: ProviderType¶
Return the provider type.
- async remove_discount(subscriptionkore_provider_ref: ProviderReference) Subscription[source]¶
Remove discount from a subscriptionkore.
- async resume_subscriptionkore(subscriptionkore_provider_ref: ProviderReference) Subscription[source]¶
Resume a paused subscriptionkore.
- async sync_plans(product_provider_ref: ProviderReference) list[Plan][source]¶
Sync all plans for a product from provider.
- async update_subscriptionkore(request: UpdateSubscriptionRequest, subscriptionkore_provider_ref: ProviderReference) Subscription[source]¶
Update a subscriptionkore.
Chargebee adapter.
- class subscriptionkore.adapters.chargebee.ChargebeeAdapter(config: ChargebeeConfig)[source]¶
Bases:
PaymentProviderPortChargebee payment provider implementation.
Implements the Chargebee API for subscriptionkore management. Reference: https://apidocs.eu.chargebee. com/docs/api/
- INVOICE_STATUS_MAP = {'not_paid': InvoiceStatus.OPEN, 'paid': InvoiceStatus.PAID, 'payment_due': InvoiceStatus.OPEN, 'pending': InvoiceStatus.DRAFT, 'posted': InvoiceStatus.OPEN, 'voided': InvoiceStatus.VOID}¶
- STATUS_MAP = {'active': SubscriptionStatus.ACTIVE, 'cancelled': SubscriptionStatus.CANCELED, 'future': SubscriptionStatus.INCOMPLETE, 'in_trial': SubscriptionStatus.TRIALING, 'non_renewing': SubscriptionStatus.ACTIVE, 'paused': SubscriptionStatus.PAUSED}¶
- async apply_discount(subscriptionkore_provider_ref: ProviderReference, discount: DiscountRequest) Subscription[source]¶
Apply a discount to a subscriptionkore.
- async cancel_subscriptionkore(subscriptionkore_provider_ref: ProviderReference, immediate: bool = False) Subscription[source]¶
Cancel a subscriptionkore.
- property capabilities: ProviderCapabilities¶
Return provider capabilities.
- async change_plan(request: ChangePlanRequest, subscriptionkore_provider_ref: ProviderReference, new_plan_provider_ref: ProviderReference) Subscription[source]¶
Change subscriptionkore plan (upgrade/downgrade).
- async create_checkout_session(request: CheckoutRequest, plan_provider_ref: ProviderReference, customer_provider_ref: ProviderReference | None = None) CheckoutSession[source]¶
Create a checkout session.
- async create_customer(customer: Customer) ProviderReference[source]¶
Create a customer in the provider.
- async create_portal_session(customer_provider_ref: ProviderReference, return_url: str) PortalSession[source]¶
Create a customer portal session.
- async create_subscriptionkore(request: CreateSubscriptionRequest, customer_provider_ref: ProviderReference, plan_provider_ref: ProviderReference) Subscription[source]¶
Create a subscriptionkore.
- async delete_customer(provider_ref: ProviderReference) None[source]¶
Delete a customer from the provider.
- async get_customer(provider_ref: ProviderReference) Customer[source]¶
Get a customer from the provider.
- async get_invoice(provider_ref: ProviderReference) Invoice[source]¶
Get an invoice from the provider.
- async get_subscriptionkore(provider_ref: ProviderReference) Subscription[source]¶
Get a subscriptionkore from the provider.
- async get_upcoming_invoice(subscriptionkore_provider_ref: ProviderReference) Invoice | None[source]¶
Get upcoming invoice for a subscriptionkore.
- async list_invoices(customer_provider_ref: ProviderReference, limit: int = 10, starting_after: str | None = None) list[Invoice][source]¶
List invoices for a customer.
- async parse_webhook(payload: bytes, headers: dict[str, str]) ProviderWebhookEvent[source]¶
Parse Chargebee webhook payload.
- async pause_subscriptionkore(subscriptionkore_provider_ref: ProviderReference, resumes_at: datetime | None = None) Subscription[source]¶
Pause a subscriptionkore.
- async preview_plan_change(request: ChangePlanRequest, subscriptionkore_provider_ref: ProviderReference, new_plan_provider_ref: ProviderReference) ChangePreview[source]¶
Preview plan change costs.
- property provider_type: ProviderType¶
Return the provider type.
- async remove_discount(subscriptionkore_provider_ref: ProviderReference) Subscription[source]¶
Remove discount from a subscriptionkore.
- async resume_subscriptionkore(subscriptionkore_provider_ref: ProviderReference) Subscription[source]¶
Resume a paused subscriptionkore.
- async sync_plans(product_provider_ref: ProviderReference) list[Plan][source]¶
Sync all plans for a product from provider.
- async update_subscriptionkore(request: UpdateSubscriptionRequest, subscriptionkore_provider_ref: ProviderReference) Subscription[source]¶
Update a subscriptionkore.
Paddle adapter.
- class subscriptionkore.adapters.paddle.PaddleAdapter(config: PaddleConfig)[source]¶
Bases:
PaymentProviderPortPaddle Billing payment provider implementation.
Implements the Paddle Billing API (v1) for subscriptionkore management. Reference: https://developer.paddle.com/api-reference/overview
- STATUS_MAP = {'active': SubscriptionStatus.ACTIVE, 'canceled': SubscriptionStatus.CANCELED, 'past_due': SubscriptionStatus.PAST_DUE, 'paused': SubscriptionStatus.PAUSED, 'trialing': SubscriptionStatus.TRIALING}¶
- async apply_discount(subscriptionkore_provider_ref: ProviderReference, discount: DiscountRequest) Subscription[source]¶
Apply a discount to a subscriptionkore.
- async cancel_subscriptionkore(subscriptionkore_provider_ref: ProviderReference, immediate: bool = False) Subscription[source]¶
Cancel a subscriptionkore.
- property capabilities: ProviderCapabilities¶
Return provider capabilities.
- async change_plan(request: ChangePlanRequest, subscriptionkore_provider_ref: ProviderReference, new_plan_provider_ref: ProviderReference) Subscription[source]¶
Change subscriptionkore plan (upgrade/downgrade).
- async create_checkout_session(request: CheckoutRequest, plan_provider_ref: ProviderReference, customer_provider_ref: ProviderReference | None = None) CheckoutSession[source]¶
Create a checkout session.
- async create_customer(customer: Customer) ProviderReference[source]¶
Create a customer in the provider.
- async create_portal_session(customer_provider_ref: ProviderReference, return_url: str) PortalSession[source]¶
Create a customer portal session.
- async create_subscriptionkore(request: CreateSubscriptionRequest, customer_provider_ref: ProviderReference, plan_provider_ref: ProviderReference) Subscription[source]¶
Create a subscriptionkore in Paddle.
Note: Paddle subscriptionkores are typically created through checkout. This method creates a subscriptionkore directly via API.
- async delete_customer(provider_ref: ProviderReference) None[source]¶
Delete a customer from the provider.
- async get_customer(provider_ref: ProviderReference) Customer[source]¶
Get a customer from the provider.
- async get_invoice(provider_ref: ProviderReference) Invoice[source]¶
Get an invoice from the provider.
- async get_subscriptionkore(provider_ref: ProviderReference) Subscription[source]¶
Get a subscriptionkore from the provider.
- async get_upcoming_invoice(subscriptionkore_provider_ref: ProviderReference) Invoice | None[source]¶
Get upcoming invoice for a subscriptionkore.
- async list_invoices(customer_provider_ref: ProviderReference, limit: int = 10, starting_after: str | None = None) list[Invoice][source]¶
List invoices for a customer.
- async parse_webhook(payload: bytes, headers: dict[str, str]) ProviderWebhookEvent[source]¶
Parse Paddle webhook payload.
- async pause_subscriptionkore(subscriptionkore_provider_ref: ProviderReference, resumes_at: datetime | None = None) Subscription[source]¶
Pause a subscriptionkore.
- async preview_plan_change(request: ChangePlanRequest, subscriptionkore_provider_ref: ProviderReference, new_plan_provider_ref: ProviderReference) ChangePreview[source]¶
Preview plan change costs.
- property provider_type: ProviderType¶
Return the provider type.
- async remove_discount(subscriptionkore_provider_ref: ProviderReference) Subscription[source]¶
Remove discount from a subscriptionkore.
- async resume_subscriptionkore(subscriptionkore_provider_ref: ProviderReference) Subscription[source]¶
Resume a paused subscriptionkore.
- async sync_plans(product_provider_ref: ProviderReference) list[Plan][source]¶
Sync all plans for a product from provider.
- async update_subscriptionkore(request: UpdateSubscriptionRequest, subscriptionkore_provider_ref: ProviderReference) Subscription[source]¶
Update a subscriptionkore.
LemonSqueezy adapter.
- class subscriptionkore.adapters.lemonsqueezy.LemonSqueezyAdapter(config: LemonSqueezyConfig)[source]¶
Bases:
PaymentProviderPortLemonSqueezy payment provider implementation.
Implements the LemonSqueezy API for subscriptionkore management. Reference: https://docs.lemonsqueezy.com/api
- BASE_URL = 'https://api.lemonsqueezy.com/v1'¶
- STATUS_MAP = {'active': SubscriptionStatus.ACTIVE, 'cancelled': SubscriptionStatus.CANCELED, 'expired': SubscriptionStatus.EXPIRED, 'on_trial': SubscriptionStatus.TRIALING, 'past_due': SubscriptionStatus.PAST_DUE, 'paused': SubscriptionStatus.PAUSED, 'unpaid': SubscriptionStatus.UNPAID}¶
- async apply_discount(subscriptionkore_provider_ref: ProviderReference, discount: DiscountRequest) Subscription[source]¶
Apply a discount to a subscriptionkore.
- async cancel_subscriptionkore(subscriptionkore_provider_ref: ProviderReference, immediate: bool = False) Subscription[source]¶
Cancel a subscriptionkore.
- property capabilities: ProviderCapabilities¶
Return provider capabilities.
- async change_plan(request: ChangePlanRequest, subscriptionkore_provider_ref: ProviderReference, new_plan_provider_ref: ProviderReference) Subscription[source]¶
Change subscriptionkore plan (upgrade/downgrade).
- async create_checkout_session(request: CheckoutRequest, plan_provider_ref: ProviderReference, customer_provider_ref: ProviderReference | None = None) CheckoutSession[source]¶
Create a checkout session.
- async create_customer(customer: Customer) ProviderReference[source]¶
Create a customer in the provider.
- async create_portal_session(customer_provider_ref: ProviderReference, return_url: str) PortalSession[source]¶
Create a customer portal session.
- async create_subscriptionkore(request: CreateSubscriptionRequest, customer_provider_ref: ProviderReference, plan_provider_ref: ProviderReference) Subscription[source]¶
Create a subscriptionkore.
- async delete_customer(provider_ref: ProviderReference) None[source]¶
Delete a customer from the provider.
- async get_customer(provider_ref: ProviderReference) Customer[source]¶
Get a customer from the provider.
- async get_invoice(provider_ref: ProviderReference) Invoice[source]¶
Get an invoice from the provider.
- async get_subscriptionkore(provider_ref: ProviderReference) Subscription[source]¶
Get a subscriptionkore from the provider.
- async get_upcoming_invoice(subscriptionkore_provider_ref: ProviderReference) Invoice | None[source]¶
Get upcoming invoice for a subscriptionkore.
- async list_invoices(customer_provider_ref: ProviderReference, limit: int = 10, starting_after: str | None = None) list[Invoice][source]¶
List invoices for a customer.
- async parse_webhook(payload: bytes, headers: dict[str, str]) ProviderWebhookEvent[source]¶
Parse LemonSqueezy webhook payload.
- async pause_subscriptionkore(subscriptionkore_provider_ref: ProviderReference, resumes_at: datetime | None = None) Subscription[source]¶
Pause a subscriptionkore.
- async preview_plan_change(request: ChangePlanRequest, subscriptionkore_provider_ref: ProviderReference, new_plan_provider_ref: ProviderReference) ChangePreview[source]¶
Preview plan change costs.
- property provider_type: ProviderType¶
Return the provider type.
- async remove_discount(subscriptionkore_provider_ref: ProviderReference) Subscription[source]¶
Remove discount from a subscriptionkore.
- async resume_subscriptionkore(subscriptionkore_provider_ref: ProviderReference) Subscription[source]¶
Resume a paused subscriptionkore.
- async sync_plans(product_provider_ref: ProviderReference) list[Plan][source]¶
Sync all plans for a product from provider.
- async update_subscriptionkore(request: UpdateSubscriptionRequest, subscriptionkore_provider_ref: ProviderReference) Subscription[source]¶
Update a subscriptionkore.
Services¶
Application services.
- class subscriptionkore.services.CustomerManager(customer_repo: CustomerRepository, provider: PaymentProviderPort, event_bus: EventBusPort)[source]¶
Bases:
objectManages customer lifecycle operations.
Provides a unified interface for customer operations across providers.
- async create(external_id: str, email: str, name: str | None = None, tax_info: TaxInfo | None = None, billing_address: Address | None = None, metadata: dict | None = None, sync_to_provider: bool = True) Customer[source]¶
Create a new customer.
- Parameters:
external_id – Your application’s user ID
email – Customer email
name – Customer name
tax_info – Tax information
billing_address – Billing address
metadata – Additional metadata
sync_to_provider – Whether to create in payment provider
- Returns:
Created customer
- Raises:
DuplicateEntityError – If customer with external_id exists
- async delete(customer_id: str, delete_from_provider: bool = True) bool[source]¶
Delete a customer.
- Parameters:
customer_id – Customer ID
delete_from_provider – Whether to delete from payment provider
- Returns:
True if deleted
- async get_by_external_id(external_id: str) Customer[source]¶
Get customer by external (application) ID.
- async get_or_create(external_id: str, email: str, name: str | None = None, sync_to_provider: bool = True) tuple[Customer, bool][source]¶
Get existing customer or create new one.
- Returns:
Tuple of (customer, created) where created is True if new
- async list(limit: int = 100, offset: int = 0) list[Customer][source]¶
List customers with pagination.
- async sync_to_provider(customer_id: str, provider: ProviderType | None = None) Customer[source]¶
Sync customer to payment provider.
Creates customer in provider if not exists, or updates if exists.
- class subscriptionkore.services.EntitlementService(entitlement_repo: EntitlementRepository, override_repo: EntitlementOverrideRepository, subscriptionkore_repo: SubscriptionRepository, plan_repo: PlanRepository, cache: CachePort | None = None, cache_ttl: int = 300)[source]¶
Bases:
objectResolves and manages customer entitlements.
Entitlements are derived from: 1. Customer-level overrides (highest priority) 2. Active subscriptionkore plan entitlements 3. Trial entitlements 4. Default entitlements (lowest priority)
- async check(customer_id: str, entitlement_key: str) CustomerEntitlement[source]¶
Check a specific entitlement for a customer.
- Parameters:
customer_id – Customer ID
entitlement_key – Entitlement key to check
- Returns:
Resolved CustomerEntitlement
- Raises:
EntitlementNotFoundError – If entitlement key doesn’t exist
- async check_all(customer_id: str) list[CustomerEntitlement][source]¶
Get all resolved entitlements for a customer.
Results are cached for performance.
- async check_many(customer_id: str, entitlement_keys: list[str]) dict[str, CustomerEntitlement][source]¶
Check multiple entitlements at once.
- async check_within_limit(customer_id: str, entitlement_key: str, current_usage: int, requested: int = 1) tuple[bool, int | None][source]¶
Check if usage is within limit.
- Parameters:
customer_id – Customer ID
entitlement_key – Entitlement key
current_usage – Current usage count
requested – Additional usage being requested
- Returns:
Tuple of (within_limit, remaining) remaining is None for unlimited
- async enforce_limit(customer_id: str, entitlement_key: str, current_usage: int, requested: int = 1) int | None[source]¶
Enforce usage limit, raising exception if exceeded.
- Parameters:
customer_id – Customer ID
entitlement_key – Entitlement key
current_usage – Current usage count
requested – Additional usage being requested
- Returns:
Remaining quota (None for unlimited)
- Raises:
UsageLimitExceededError – If limit would be exceeded
- async get_limit(customer_id: str, entitlement_key: str) int | None[source]¶
Get numeric limit for an entitlement.
Returns None for unlimited entitlements.
- async grant_override(customer_id: str, entitlement_key: str, value: bool | int | str, expires_at: datetime | None = None, reason: str | None = None, created_by: str | None = None) EntitlementOverride[source]¶
Grant an entitlement override to a customer.
- Parameters:
customer_id – Customer ID
entitlement_key – Entitlement key
value – Override value
expires_at – When override expires (None for permanent)
reason – Reason for override
created_by – Who created the override
- Returns:
Created override
- async has_access(customer_id: str, entitlement_key: str) bool[source]¶
Check if customer has access to a feature.
- async list_overrides(customer_id: str, include_expired: bool = False) list[EntitlementOverride][source]¶
List all overrides for a customer.
- class subscriptionkore.services.SubscriptionManager(subscriptionkore_repo: SubscriptionRepository, customer_repo: CustomerRepository, plan_repo: PlanRepository, provider: PaymentProviderPort, event_bus: EventBusPort)[source]¶
Bases:
objectManages subscriptionkore lifecycle operations.
Provides a unified interface for subscriptionkore operations across providers.
- async apply_discount(subscriptionkore_id: str, coupon_code: str) Subscription[source]¶
Apply a discount to a subscriptionkore.
- async cancel(subscriptionkore_id: str, immediate: bool = False, reason: str | None = None) Subscription[source]¶
Cancel a subscriptionkore.
- Parameters:
subscriptionkore_id – Subscription ID
immediate – If True, cancel immediately. If False, cancel at period end.
reason – Optional cancellation reason
- Returns:
Updated subscriptionkore
- async change_plan(subscriptionkore_id: str, new_plan_id: str, proration_behavior: ProrationBehavior = ProrationBehavior.CREATE_PRORATIONS) Subscription[source]¶
Change subscriptionkore plan (upgrade/downgrade).
- Parameters:
subscriptionkore_id – Subscription ID
new_plan_id – New plan ID
proration_behavior – How to handle proration
- Returns:
Updated subscriptionkore
- async create(customer_id: str, plan_id: str, quantity: int = 1, trial_period_days: int | None = None, coupon_code: str | None = None, metadata: dict | None = None) Subscription[source]¶
Create a new subscriptionkore.
- Parameters:
customer_id – Internal customer ID
plan_id – Internal plan ID
quantity – Subscription quantity
trial_period_days – Override trial period (None uses plan default)
coupon_code – Optional coupon code to apply
metadata – Additional metadata
- Returns:
Created subscriptionkore
- Raises:
EntityNotFoundError – If customer or plan not found
- async get(subscriptionkore_id: str) Subscription[source]¶
Get subscriptionkore by ID.
- async get_active_by_customer(customer_id: str) list[Subscription][source]¶
Get active subscriptionkores for a customer.
- async get_by_customer(customer_id: str, include_canceled: bool = False) list[Subscription][source]¶
Get all subscriptionkores for a customer.
- async pause(subscriptionkore_id: str, resumes_at: datetime | None = None) Subscription[source]¶
Pause a subscriptionkore.
- async preview_plan_change(subscriptionkore_id: str, new_plan_id: str, proration_behavior: ProrationBehavior = ProrationBehavior.CREATE_PRORATIONS) ChangePreview[source]¶
Preview costs for a plan change.
- async reactivate(subscriptionkore_id: str) Subscription[source]¶
Reactivate a subscriptionkore that was scheduled to cancel.
Removes the cancel_at_period_end flag.
- async remove_discount(subscriptionkore_id: str) Subscription[source]¶
Remove discount from a subscriptionkore.
- async resume(subscriptionkore_id: str) Subscription[source]¶
Resume a paused subscriptionkore.
- async update(subscriptionkore_id: str, quantity: int | None = None, metadata: dict | None = None) Subscription[source]¶
Update subscriptionkore quantity or metadata.
- class subscriptionkore.services.WebhookProcessor(providers: dict[ProviderType, PaymentProviderPort], subscriptionkore_repo: SubscriptionRepository, customer_repo: CustomerRepository, plan_repo: PlanRepository, invoice_repo: InvoiceRepository, payment_event_repo: PaymentEventRepository, processed_event_repo: ProcessedEventRepository, event_bus: EventBusPort, entitlement_service: EntitlementService)[source]¶
Bases:
objectProcesses webhooks from payment providers.
Responsibilities: - Verify webhook signatures - Parse provider-specific payloads - Normalize to canonical event format - Apply state changes - Emit domain events - Ensure idempotency
- async process(provider: str, payload: bytes, headers: dict[str, str]) WebhookResult[source]¶
Process a webhook from a payment provider.
- Parameters:
provider – Provider name (e.g., “stripe”, “paddle”)
payload – Raw webhook payload bytes
headers – HTTP headers from webhook request
- Returns:
WebhookResult with processing outcome
- Raises:
WebhookSignatureInvalidError – If signature verification fails
WebhookPayloadInvalidError – If payload cannot be parsed
WebhookProcessingError – If processing fails
Integrations¶
Framework integrations.