# This file was auto-generated by Fern from our API Definition.

import datetime as dt
import typing

from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from ..core.request_options import RequestOptions
from ..types.billing_product_pricing import BillingProductPricing
from ..types.billing_subscription_discount import BillingSubscriptionDiscount
from ..types.create_billing_price_tier_request_body import CreateBillingPriceTierRequestBody
from .raw_client import AsyncRawBillingClient, RawBillingClient
from .types.count_billing_products_request_price_usage_type import CountBillingProductsRequestPriceUsageType
from .types.count_billing_products_response import CountBillingProductsResponse
from .types.count_customers_response import CountCustomersResponse
from .types.create_billing_price_request_body_billing_scheme import CreateBillingPriceRequestBodyBillingScheme
from .types.create_billing_price_request_body_tier_mode import CreateBillingPriceRequestBodyTierMode
from .types.create_billing_price_request_body_usage_type import CreateBillingPriceRequestBodyUsageType
from .types.create_billing_subscriptions_request_body_trial_end_setting import (
    CreateBillingSubscriptionsRequestBodyTrialEndSetting,
)
from .types.delete_billing_product_response import DeleteBillingProductResponse
from .types.delete_product_price_response import DeleteProductPriceResponse
from .types.list_billing_products_request_price_usage_type import ListBillingProductsRequestPriceUsageType
from .types.list_billing_products_response import ListBillingProductsResponse
from .types.list_coupons_response import ListCouponsResponse
from .types.list_customers_with_subscriptions_response import ListCustomersWithSubscriptionsResponse
from .types.list_invoices_response import ListInvoicesResponse
from .types.list_meters_response import ListMetersResponse
from .types.list_payment_methods_response import ListPaymentMethodsResponse
from .types.list_product_prices_request_price_usage_type import ListProductPricesRequestPriceUsageType
from .types.list_product_prices_response import ListProductPricesResponse
from .types.search_billing_prices_request_usage_type import SearchBillingPricesRequestUsageType
from .types.search_billing_prices_response import SearchBillingPricesResponse
from .types.upsert_billing_coupon_response import UpsertBillingCouponResponse
from .types.upsert_billing_customer_response import UpsertBillingCustomerResponse
from .types.upsert_billing_meter_response import UpsertBillingMeterResponse
from .types.upsert_billing_price_response import UpsertBillingPriceResponse
from .types.upsert_billing_product_response import UpsertBillingProductResponse
from .types.upsert_billing_subscription_response import UpsertBillingSubscriptionResponse
from .types.upsert_invoice_response import UpsertInvoiceResponse
from .types.upsert_payment_method_response import UpsertPaymentMethodResponse

# this is used as the default value for optional parameters
OMIT = typing.cast(typing.Any, ...)


class BillingClient:
    def __init__(self, *, client_wrapper: SyncClientWrapper):
        self._raw_client = RawBillingClient(client_wrapper=client_wrapper)

    @property
    def with_raw_response(self) -> RawBillingClient:
        """
        Retrieves a raw implementation of this client that returns raw responses.

        Returns
        -------
        RawBillingClient
        """
        return self._raw_client

    def list_coupons(
        self,
        *,
        is_active: typing.Optional[bool] = None,
        q: typing.Optional[str] = None,
        limit: typing.Optional[int] = None,
        offset: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ListCouponsResponse:
        """
        Parameters
        ----------
        is_active : typing.Optional[bool]

        q : typing.Optional[str]

        limit : typing.Optional[int]
            Page limit (default 100)

        offset : typing.Optional[int]
            Page offset (default 0)

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        ListCouponsResponse
            OK

        Examples
        --------
        from schematic import Schematic

        client = Schematic(
            api_key="YOUR_API_KEY",
        )
        client.billing.list_coupons()
        """
        _response = self._raw_client.list_coupons(
            is_active=is_active, q=q, limit=limit, offset=offset, request_options=request_options
        )
        return _response.data

    def upsert_billing_coupon(
        self,
        *,
        amount_off: int,
        duration: str,
        duration_in_months: int,
        external_id: str,
        max_redemptions: int,
        name: str,
        percent_off: float,
        times_redeemed: int,
        currency: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> UpsertBillingCouponResponse:
        """
        Parameters
        ----------
        amount_off : int

        duration : str

        duration_in_months : int

        external_id : str

        max_redemptions : int

        name : str

        percent_off : float

        times_redeemed : int

        currency : typing.Optional[str]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        UpsertBillingCouponResponse
            Created

        Examples
        --------
        from schematic import Schematic

        client = Schematic(
            api_key="YOUR_API_KEY",
        )
        client.billing.upsert_billing_coupon(
            amount_off=1,
            duration="duration",
            duration_in_months=1,
            external_id="external_id",
            max_redemptions=1,
            name="name",
            percent_off=1.1,
            times_redeemed=1,
        )
        """
        _response = self._raw_client.upsert_billing_coupon(
            amount_off=amount_off,
            duration=duration,
            duration_in_months=duration_in_months,
            external_id=external_id,
            max_redemptions=max_redemptions,
            name=name,
            percent_off=percent_off,
            times_redeemed=times_redeemed,
            currency=currency,
            request_options=request_options,
        )
        return _response.data

    def upsert_billing_customer(
        self,
        *,
        email: str,
        external_id: str,
        failed_to_import: bool,
        meta: typing.Dict[str, str],
        name: str,
        company_id: typing.Optional[str] = OMIT,
        default_payment_method_id: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> UpsertBillingCustomerResponse:
        """
        Parameters
        ----------
        email : str

        external_id : str

        failed_to_import : bool

        meta : typing.Dict[str, str]

        name : str

        company_id : typing.Optional[str]

        default_payment_method_id : typing.Optional[str]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        UpsertBillingCustomerResponse
            Created

        Examples
        --------
        from schematic import Schematic

        client = Schematic(
            api_key="YOUR_API_KEY",
        )
        client.billing.upsert_billing_customer(
            email="email",
            external_id="external_id",
            failed_to_import=True,
            meta={"key": "value"},
            name="name",
        )
        """
        _response = self._raw_client.upsert_billing_customer(
            email=email,
            external_id=external_id,
            failed_to_import=failed_to_import,
            meta=meta,
            name=name,
            company_id=company_id,
            default_payment_method_id=default_payment_method_id,
            request_options=request_options,
        )
        return _response.data

    def list_customers_with_subscriptions(
        self,
        *,
        company_ids: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
        name: typing.Optional[str] = None,
        failed_to_import: typing.Optional[bool] = None,
        q: typing.Optional[str] = None,
        limit: typing.Optional[int] = None,
        offset: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ListCustomersWithSubscriptionsResponse:
        """
        Parameters
        ----------
        company_ids : typing.Optional[typing.Union[str, typing.Sequence[str]]]

        name : typing.Optional[str]

        failed_to_import : typing.Optional[bool]

        q : typing.Optional[str]

        limit : typing.Optional[int]
            Page limit (default 100)

        offset : typing.Optional[int]
            Page offset (default 0)

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        ListCustomersWithSubscriptionsResponse
            OK

        Examples
        --------
        from schematic import Schematic

        client = Schematic(
            api_key="YOUR_API_KEY",
        )
        client.billing.list_customers_with_subscriptions()
        """
        _response = self._raw_client.list_customers_with_subscriptions(
            company_ids=company_ids,
            name=name,
            failed_to_import=failed_to_import,
            q=q,
            limit=limit,
            offset=offset,
            request_options=request_options,
        )
        return _response.data

    def count_customers(
        self,
        *,
        company_ids: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
        name: typing.Optional[str] = None,
        failed_to_import: typing.Optional[bool] = None,
        q: typing.Optional[str] = None,
        limit: typing.Optional[int] = None,
        offset: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> CountCustomersResponse:
        """
        Parameters
        ----------
        company_ids : typing.Optional[typing.Union[str, typing.Sequence[str]]]

        name : typing.Optional[str]

        failed_to_import : typing.Optional[bool]

        q : typing.Optional[str]

        limit : typing.Optional[int]
            Page limit (default 100)

        offset : typing.Optional[int]
            Page offset (default 0)

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        CountCustomersResponse
            OK

        Examples
        --------
        from schematic import Schematic

        client = Schematic(
            api_key="YOUR_API_KEY",
        )
        client.billing.count_customers()
        """
        _response = self._raw_client.count_customers(
            company_ids=company_ids,
            name=name,
            failed_to_import=failed_to_import,
            q=q,
            limit=limit,
            offset=offset,
            request_options=request_options,
        )
        return _response.data

    def list_invoices(
        self,
        *,
        customer_external_id: str,
        company_id: typing.Optional[str] = None,
        subscription_external_id: typing.Optional[str] = None,
        limit: typing.Optional[int] = None,
        offset: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ListInvoicesResponse:
        """
        Parameters
        ----------
        customer_external_id : str

        company_id : typing.Optional[str]

        subscription_external_id : typing.Optional[str]

        limit : typing.Optional[int]
            Page limit (default 100)

        offset : typing.Optional[int]
            Page offset (default 0)

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        ListInvoicesResponse
            OK

        Examples
        --------
        from schematic import Schematic

        client = Schematic(
            api_key="YOUR_API_KEY",
        )
        client.billing.list_invoices(
            customer_external_id="customer_external_id",
        )
        """
        _response = self._raw_client.list_invoices(
            customer_external_id=customer_external_id,
            company_id=company_id,
            subscription_external_id=subscription_external_id,
            limit=limit,
            offset=offset,
            request_options=request_options,
        )
        return _response.data

    def upsert_invoice(
        self,
        *,
        amount_due: int,
        amount_paid: int,
        amount_remaining: int,
        collection_method: str,
        currency: str,
        customer_external_id: str,
        subtotal: int,
        due_date: typing.Optional[dt.datetime] = OMIT,
        external_id: typing.Optional[str] = OMIT,
        payment_method_external_id: typing.Optional[str] = OMIT,
        subscription_external_id: typing.Optional[str] = OMIT,
        url: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> UpsertInvoiceResponse:
        """
        Parameters
        ----------
        amount_due : int

        amount_paid : int

        amount_remaining : int

        collection_method : str

        currency : str

        customer_external_id : str

        subtotal : int

        due_date : typing.Optional[dt.datetime]

        external_id : typing.Optional[str]

        payment_method_external_id : typing.Optional[str]

        subscription_external_id : typing.Optional[str]

        url : typing.Optional[str]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        UpsertInvoiceResponse
            Created

        Examples
        --------
        from schematic import Schematic

        client = Schematic(
            api_key="YOUR_API_KEY",
        )
        client.billing.upsert_invoice(
            amount_due=1,
            amount_paid=1,
            amount_remaining=1,
            collection_method="collection_method",
            currency="currency",
            customer_external_id="customer_external_id",
            subtotal=1,
        )
        """
        _response = self._raw_client.upsert_invoice(
            amount_due=amount_due,
            amount_paid=amount_paid,
            amount_remaining=amount_remaining,
            collection_method=collection_method,
            currency=currency,
            customer_external_id=customer_external_id,
            subtotal=subtotal,
            due_date=due_date,
            external_id=external_id,
            payment_method_external_id=payment_method_external_id,
            subscription_external_id=subscription_external_id,
            url=url,
            request_options=request_options,
        )
        return _response.data

    def list_meters(
        self,
        *,
        display_name: typing.Optional[str] = None,
        limit: typing.Optional[int] = None,
        offset: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ListMetersResponse:
        """
        Parameters
        ----------
        display_name : typing.Optional[str]

        limit : typing.Optional[int]
            Page limit (default 100)

        offset : typing.Optional[int]
            Page offset (default 0)

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        ListMetersResponse
            OK

        Examples
        --------
        from schematic import Schematic

        client = Schematic(
            api_key="YOUR_API_KEY",
        )
        client.billing.list_meters()
        """
        _response = self._raw_client.list_meters(
            display_name=display_name, limit=limit, offset=offset, request_options=request_options
        )
        return _response.data

    def upsert_billing_meter(
        self,
        *,
        display_name: str,
        event_name: str,
        event_payload_key: str,
        external_id: str,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> UpsertBillingMeterResponse:
        """
        Parameters
        ----------
        display_name : str

        event_name : str

        event_payload_key : str

        external_id : str

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        UpsertBillingMeterResponse
            Created

        Examples
        --------
        from schematic import Schematic

        client = Schematic(
            api_key="YOUR_API_KEY",
        )
        client.billing.upsert_billing_meter(
            display_name="display_name",
            event_name="event_name",
            event_payload_key="event_payload_key",
            external_id="external_id",
        )
        """
        _response = self._raw_client.upsert_billing_meter(
            display_name=display_name,
            event_name=event_name,
            event_payload_key=event_payload_key,
            external_id=external_id,
            request_options=request_options,
        )
        return _response.data

    def list_payment_methods(
        self,
        *,
        customer_external_id: str,
        company_id: typing.Optional[str] = None,
        limit: typing.Optional[int] = None,
        offset: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ListPaymentMethodsResponse:
        """
        Parameters
        ----------
        customer_external_id : str

        company_id : typing.Optional[str]

        limit : typing.Optional[int]
            Page limit (default 100)

        offset : typing.Optional[int]
            Page offset (default 0)

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        ListPaymentMethodsResponse
            OK

        Examples
        --------
        from schematic import Schematic

        client = Schematic(
            api_key="YOUR_API_KEY",
        )
        client.billing.list_payment_methods(
            customer_external_id="customer_external_id",
        )
        """
        _response = self._raw_client.list_payment_methods(
            customer_external_id=customer_external_id,
            company_id=company_id,
            limit=limit,
            offset=offset,
            request_options=request_options,
        )
        return _response.data

    def upsert_payment_method(
        self,
        *,
        customer_external_id: str,
        external_id: str,
        payment_method_type: str,
        account_last_4: typing.Optional[str] = OMIT,
        account_name: typing.Optional[str] = OMIT,
        bank_name: typing.Optional[str] = OMIT,
        billing_email: typing.Optional[str] = OMIT,
        billing_name: typing.Optional[str] = OMIT,
        card_brand: typing.Optional[str] = OMIT,
        card_exp_month: typing.Optional[int] = OMIT,
        card_exp_year: typing.Optional[int] = OMIT,
        card_last_4: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> UpsertPaymentMethodResponse:
        """
        Parameters
        ----------
        customer_external_id : str

        external_id : str

        payment_method_type : str

        account_last_4 : typing.Optional[str]

        account_name : typing.Optional[str]

        bank_name : typing.Optional[str]

        billing_email : typing.Optional[str]

        billing_name : typing.Optional[str]

        card_brand : typing.Optional[str]

        card_exp_month : typing.Optional[int]

        card_exp_year : typing.Optional[int]

        card_last_4 : typing.Optional[str]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        UpsertPaymentMethodResponse
            Created

        Examples
        --------
        from schematic import Schematic

        client = Schematic(
            api_key="YOUR_API_KEY",
        )
        client.billing.upsert_payment_method(
            customer_external_id="customer_external_id",
            external_id="external_id",
            payment_method_type="payment_method_type",
        )
        """
        _response = self._raw_client.upsert_payment_method(
            customer_external_id=customer_external_id,
            external_id=external_id,
            payment_method_type=payment_method_type,
            account_last_4=account_last_4,
            account_name=account_name,
            bank_name=bank_name,
            billing_email=billing_email,
            billing_name=billing_name,
            card_brand=card_brand,
            card_exp_month=card_exp_month,
            card_exp_year=card_exp_year,
            card_last_4=card_last_4,
            request_options=request_options,
        )
        return _response.data

    def search_billing_prices(
        self,
        *,
        ids: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
        q: typing.Optional[str] = None,
        interval: typing.Optional[str] = None,
        usage_type: typing.Optional[SearchBillingPricesRequestUsageType] = None,
        price: typing.Optional[int] = None,
        limit: typing.Optional[int] = None,
        offset: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> SearchBillingPricesResponse:
        """
        Parameters
        ----------
        ids : typing.Optional[typing.Union[str, typing.Sequence[str]]]

        q : typing.Optional[str]

        interval : typing.Optional[str]

        usage_type : typing.Optional[SearchBillingPricesRequestUsageType]

        price : typing.Optional[int]

        limit : typing.Optional[int]
            Page limit (default 100)

        offset : typing.Optional[int]
            Page offset (default 0)

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        SearchBillingPricesResponse
            OK

        Examples
        --------
        from schematic import Schematic

        client = Schematic(
            api_key="YOUR_API_KEY",
        )
        client.billing.search_billing_prices()
        """
        _response = self._raw_client.search_billing_prices(
            ids=ids,
            q=q,
            interval=interval,
            usage_type=usage_type,
            price=price,
            limit=limit,
            offset=offset,
            request_options=request_options,
        )
        return _response.data

    def upsert_billing_price(
        self,
        *,
        billing_scheme: CreateBillingPriceRequestBodyBillingScheme,
        currency: str,
        external_account_id: str,
        interval: str,
        is_active: bool,
        price: int,
        price_external_id: str,
        price_tiers: typing.Sequence[CreateBillingPriceTierRequestBody],
        product_external_id: str,
        usage_type: CreateBillingPriceRequestBodyUsageType,
        meter_id: typing.Optional[str] = OMIT,
        package_size: typing.Optional[int] = OMIT,
        price_decimal: typing.Optional[str] = OMIT,
        tier_mode: typing.Optional[CreateBillingPriceRequestBodyTierMode] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> UpsertBillingPriceResponse:
        """
        Parameters
        ----------
        billing_scheme : CreateBillingPriceRequestBodyBillingScheme

        currency : str

        external_account_id : str

        interval : str

        is_active : bool

        price : int

        price_external_id : str

        price_tiers : typing.Sequence[CreateBillingPriceTierRequestBody]

        product_external_id : str

        usage_type : CreateBillingPriceRequestBodyUsageType

        meter_id : typing.Optional[str]

        package_size : typing.Optional[int]

        price_decimal : typing.Optional[str]

        tier_mode : typing.Optional[CreateBillingPriceRequestBodyTierMode]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        UpsertBillingPriceResponse
            Created

        Examples
        --------
        from schematic import CreateBillingPriceTierRequestBody, Schematic

        client = Schematic(
            api_key="YOUR_API_KEY",
        )
        client.billing.upsert_billing_price(
            billing_scheme="per_unit",
            currency="currency",
            external_account_id="external_account_id",
            interval="interval",
            is_active=True,
            price=1,
            price_external_id="price_external_id",
            price_tiers=[
                CreateBillingPriceTierRequestBody(
                    price_external_id="price_external_id",
                )
            ],
            product_external_id="product_external_id",
            usage_type="licensed",
        )
        """
        _response = self._raw_client.upsert_billing_price(
            billing_scheme=billing_scheme,
            currency=currency,
            external_account_id=external_account_id,
            interval=interval,
            is_active=is_active,
            price=price,
            price_external_id=price_external_id,
            price_tiers=price_tiers,
            product_external_id=product_external_id,
            usage_type=usage_type,
            meter_id=meter_id,
            package_size=package_size,
            price_decimal=price_decimal,
            tier_mode=tier_mode,
            request_options=request_options,
        )
        return _response.data

    def delete_billing_product(
        self, billing_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> DeleteBillingProductResponse:
        """
        Parameters
        ----------
        billing_id : str
            billing_id

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        DeleteBillingProductResponse
            OK

        Examples
        --------
        from schematic import Schematic

        client = Schematic(
            api_key="YOUR_API_KEY",
        )
        client.billing.delete_billing_product(
            billing_id="billing_id",
        )
        """
        _response = self._raw_client.delete_billing_product(billing_id, request_options=request_options)
        return _response.data

    def list_product_prices(
        self,
        *,
        ids: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
        name: typing.Optional[str] = None,
        q: typing.Optional[str] = None,
        price_usage_type: typing.Optional[ListProductPricesRequestPriceUsageType] = None,
        without_linked_to_plan: typing.Optional[bool] = None,
        with_one_time_charges: typing.Optional[bool] = None,
        with_zero_price: typing.Optional[bool] = None,
        with_prices_only: typing.Optional[bool] = None,
        is_active: typing.Optional[bool] = None,
        limit: typing.Optional[int] = None,
        offset: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ListProductPricesResponse:
        """
        Parameters
        ----------
        ids : typing.Optional[typing.Union[str, typing.Sequence[str]]]

        name : typing.Optional[str]

        q : typing.Optional[str]

        price_usage_type : typing.Optional[ListProductPricesRequestPriceUsageType]

        without_linked_to_plan : typing.Optional[bool]
            Filter products that are not linked to any plan

        with_one_time_charges : typing.Optional[bool]
            Filter products that are one time charges

        with_zero_price : typing.Optional[bool]
            Filter products that have zero price for free subscription type

        with_prices_only : typing.Optional[bool]
            Filter products that have prices

        is_active : typing.Optional[bool]
            Filter products that are active

        limit : typing.Optional[int]
            Page limit (default 100)

        offset : typing.Optional[int]
            Page offset (default 0)

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        ListProductPricesResponse
            OK

        Examples
        --------
        from schematic import Schematic

        client = Schematic(
            api_key="YOUR_API_KEY",
        )
        client.billing.list_product_prices()
        """
        _response = self._raw_client.list_product_prices(
            ids=ids,
            name=name,
            q=q,
            price_usage_type=price_usage_type,
            without_linked_to_plan=without_linked_to_plan,
            with_one_time_charges=with_one_time_charges,
            with_zero_price=with_zero_price,
            with_prices_only=with_prices_only,
            is_active=is_active,
            limit=limit,
            offset=offset,
            request_options=request_options,
        )
        return _response.data

    def delete_product_price(
        self, billing_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> DeleteProductPriceResponse:
        """
        Parameters
        ----------
        billing_id : str
            billing_id

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        DeleteProductPriceResponse
            OK

        Examples
        --------
        from schematic import Schematic

        client = Schematic(
            api_key="YOUR_API_KEY",
        )
        client.billing.delete_product_price(
            billing_id="billing_id",
        )
        """
        _response = self._raw_client.delete_product_price(billing_id, request_options=request_options)
        return _response.data

    def upsert_billing_product(
        self,
        *,
        external_id: str,
        name: str,
        price: float,
        is_active: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> UpsertBillingProductResponse:
        """
        Parameters
        ----------
        external_id : str

        name : str

        price : float

        is_active : typing.Optional[bool]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        UpsertBillingProductResponse
            Created

        Examples
        --------
        from schematic import Schematic

        client = Schematic(
            api_key="YOUR_API_KEY",
        )
        client.billing.upsert_billing_product(
            external_id="external_id",
            name="name",
            price=1.1,
        )
        """
        _response = self._raw_client.upsert_billing_product(
            external_id=external_id, name=name, price=price, is_active=is_active, request_options=request_options
        )
        return _response.data

    def list_billing_products(
        self,
        *,
        ids: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
        name: typing.Optional[str] = None,
        q: typing.Optional[str] = None,
        price_usage_type: typing.Optional[ListBillingProductsRequestPriceUsageType] = None,
        without_linked_to_plan: typing.Optional[bool] = None,
        with_one_time_charges: typing.Optional[bool] = None,
        with_zero_price: typing.Optional[bool] = None,
        with_prices_only: typing.Optional[bool] = None,
        is_active: typing.Optional[bool] = None,
        limit: typing.Optional[int] = None,
        offset: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ListBillingProductsResponse:
        """
        Parameters
        ----------
        ids : typing.Optional[typing.Union[str, typing.Sequence[str]]]

        name : typing.Optional[str]

        q : typing.Optional[str]

        price_usage_type : typing.Optional[ListBillingProductsRequestPriceUsageType]

        without_linked_to_plan : typing.Optional[bool]
            Filter products that are not linked to any plan

        with_one_time_charges : typing.Optional[bool]
            Filter products that are one time charges

        with_zero_price : typing.Optional[bool]
            Filter products that have zero price for free subscription type

        with_prices_only : typing.Optional[bool]
            Filter products that have prices

        is_active : typing.Optional[bool]
            Filter products that are active

        limit : typing.Optional[int]
            Page limit (default 100)

        offset : typing.Optional[int]
            Page offset (default 0)

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        ListBillingProductsResponse
            OK

        Examples
        --------
        from schematic import Schematic

        client = Schematic(
            api_key="YOUR_API_KEY",
        )
        client.billing.list_billing_products()
        """
        _response = self._raw_client.list_billing_products(
            ids=ids,
            name=name,
            q=q,
            price_usage_type=price_usage_type,
            without_linked_to_plan=without_linked_to_plan,
            with_one_time_charges=with_one_time_charges,
            with_zero_price=with_zero_price,
            with_prices_only=with_prices_only,
            is_active=is_active,
            limit=limit,
            offset=offset,
            request_options=request_options,
        )
        return _response.data

    def count_billing_products(
        self,
        *,
        ids: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
        name: typing.Optional[str] = None,
        q: typing.Optional[str] = None,
        price_usage_type: typing.Optional[CountBillingProductsRequestPriceUsageType] = None,
        without_linked_to_plan: typing.Optional[bool] = None,
        with_one_time_charges: typing.Optional[bool] = None,
        with_zero_price: typing.Optional[bool] = None,
        with_prices_only: typing.Optional[bool] = None,
        is_active: typing.Optional[bool] = None,
        limit: typing.Optional[int] = None,
        offset: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> CountBillingProductsResponse:
        """
        Parameters
        ----------
        ids : typing.Optional[typing.Union[str, typing.Sequence[str]]]

        name : typing.Optional[str]

        q : typing.Optional[str]

        price_usage_type : typing.Optional[CountBillingProductsRequestPriceUsageType]

        without_linked_to_plan : typing.Optional[bool]
            Filter products that are not linked to any plan

        with_one_time_charges : typing.Optional[bool]
            Filter products that are one time charges

        with_zero_price : typing.Optional[bool]
            Filter products that have zero price for free subscription type

        with_prices_only : typing.Optional[bool]
            Filter products that have prices

        is_active : typing.Optional[bool]
            Filter products that are active

        limit : typing.Optional[int]
            Page limit (default 100)

        offset : typing.Optional[int]
            Page offset (default 0)

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        CountBillingProductsResponse
            OK

        Examples
        --------
        from schematic import Schematic

        client = Schematic(
            api_key="YOUR_API_KEY",
        )
        client.billing.count_billing_products()
        """
        _response = self._raw_client.count_billing_products(
            ids=ids,
            name=name,
            q=q,
            price_usage_type=price_usage_type,
            without_linked_to_plan=without_linked_to_plan,
            with_one_time_charges=with_one_time_charges,
            with_zero_price=with_zero_price,
            with_prices_only=with_prices_only,
            is_active=is_active,
            limit=limit,
            offset=offset,
            request_options=request_options,
        )
        return _response.data

    def upsert_billing_subscription(
        self,
        *,
        cancel_at_period_end: bool,
        currency: str,
        customer_external_id: str,
        discounts: typing.Sequence[BillingSubscriptionDiscount],
        expired_at: dt.datetime,
        product_external_ids: typing.Sequence[BillingProductPricing],
        subscription_external_id: str,
        total_price: int,
        cancel_at: typing.Optional[int] = OMIT,
        default_payment_method_id: typing.Optional[str] = OMIT,
        interval: typing.Optional[str] = OMIT,
        metadata: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
        period_end: typing.Optional[int] = OMIT,
        period_start: typing.Optional[int] = OMIT,
        status: typing.Optional[str] = OMIT,
        trial_end: typing.Optional[int] = OMIT,
        trial_end_setting: typing.Optional[CreateBillingSubscriptionsRequestBodyTrialEndSetting] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> UpsertBillingSubscriptionResponse:
        """
        Parameters
        ----------
        cancel_at_period_end : bool

        currency : str

        customer_external_id : str

        discounts : typing.Sequence[BillingSubscriptionDiscount]

        expired_at : dt.datetime

        product_external_ids : typing.Sequence[BillingProductPricing]

        subscription_external_id : str

        total_price : int

        cancel_at : typing.Optional[int]

        default_payment_method_id : typing.Optional[str]

        interval : typing.Optional[str]

        metadata : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]

        period_end : typing.Optional[int]

        period_start : typing.Optional[int]

        status : typing.Optional[str]

        trial_end : typing.Optional[int]

        trial_end_setting : typing.Optional[CreateBillingSubscriptionsRequestBodyTrialEndSetting]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        UpsertBillingSubscriptionResponse
            Created

        Examples
        --------
        import datetime

        from schematic import (
            BillingProductPricing,
            BillingSubscriptionDiscount,
            Schematic,
        )

        client = Schematic(
            api_key="YOUR_API_KEY",
        )
        client.billing.upsert_billing_subscription(
            cancel_at_period_end=True,
            currency="currency",
            customer_external_id="customer_external_id",
            discounts=[
                BillingSubscriptionDiscount(
                    coupon_external_id="coupon_external_id",
                    external_id="external_id",
                    is_active=True,
                    started_at=datetime.datetime.fromisoformat(
                        "2024-01-15 09:30:00+00:00",
                    ),
                )
            ],
            expired_at=datetime.datetime.fromisoformat(
                "2024-01-15 09:30:00+00:00",
            ),
            product_external_ids=[
                BillingProductPricing(
                    currency="currency",
                    interval="interval",
                    price=1,
                    price_external_id="price_external_id",
                    product_external_id="product_external_id",
                    quantity=1,
                    usage_type="licensed",
                )
            ],
            subscription_external_id="subscription_external_id",
            total_price=1,
        )
        """
        _response = self._raw_client.upsert_billing_subscription(
            cancel_at_period_end=cancel_at_period_end,
            currency=currency,
            customer_external_id=customer_external_id,
            discounts=discounts,
            expired_at=expired_at,
            product_external_ids=product_external_ids,
            subscription_external_id=subscription_external_id,
            total_price=total_price,
            cancel_at=cancel_at,
            default_payment_method_id=default_payment_method_id,
            interval=interval,
            metadata=metadata,
            period_end=period_end,
            period_start=period_start,
            status=status,
            trial_end=trial_end,
            trial_end_setting=trial_end_setting,
            request_options=request_options,
        )
        return _response.data


class AsyncBillingClient:
    def __init__(self, *, client_wrapper: AsyncClientWrapper):
        self._raw_client = AsyncRawBillingClient(client_wrapper=client_wrapper)

    @property
    def with_raw_response(self) -> AsyncRawBillingClient:
        """
        Retrieves a raw implementation of this client that returns raw responses.

        Returns
        -------
        AsyncRawBillingClient
        """
        return self._raw_client

    async def list_coupons(
        self,
        *,
        is_active: typing.Optional[bool] = None,
        q: typing.Optional[str] = None,
        limit: typing.Optional[int] = None,
        offset: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ListCouponsResponse:
        """
        Parameters
        ----------
        is_active : typing.Optional[bool]

        q : typing.Optional[str]

        limit : typing.Optional[int]
            Page limit (default 100)

        offset : typing.Optional[int]
            Page offset (default 0)

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        ListCouponsResponse
            OK

        Examples
        --------
        import asyncio

        from schematic import AsyncSchematic

        client = AsyncSchematic(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.billing.list_coupons()


        asyncio.run(main())
        """
        _response = await self._raw_client.list_coupons(
            is_active=is_active, q=q, limit=limit, offset=offset, request_options=request_options
        )
        return _response.data

    async def upsert_billing_coupon(
        self,
        *,
        amount_off: int,
        duration: str,
        duration_in_months: int,
        external_id: str,
        max_redemptions: int,
        name: str,
        percent_off: float,
        times_redeemed: int,
        currency: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> UpsertBillingCouponResponse:
        """
        Parameters
        ----------
        amount_off : int

        duration : str

        duration_in_months : int

        external_id : str

        max_redemptions : int

        name : str

        percent_off : float

        times_redeemed : int

        currency : typing.Optional[str]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        UpsertBillingCouponResponse
            Created

        Examples
        --------
        import asyncio

        from schematic import AsyncSchematic

        client = AsyncSchematic(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.billing.upsert_billing_coupon(
                amount_off=1,
                duration="duration",
                duration_in_months=1,
                external_id="external_id",
                max_redemptions=1,
                name="name",
                percent_off=1.1,
                times_redeemed=1,
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.upsert_billing_coupon(
            amount_off=amount_off,
            duration=duration,
            duration_in_months=duration_in_months,
            external_id=external_id,
            max_redemptions=max_redemptions,
            name=name,
            percent_off=percent_off,
            times_redeemed=times_redeemed,
            currency=currency,
            request_options=request_options,
        )
        return _response.data

    async def upsert_billing_customer(
        self,
        *,
        email: str,
        external_id: str,
        failed_to_import: bool,
        meta: typing.Dict[str, str],
        name: str,
        company_id: typing.Optional[str] = OMIT,
        default_payment_method_id: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> UpsertBillingCustomerResponse:
        """
        Parameters
        ----------
        email : str

        external_id : str

        failed_to_import : bool

        meta : typing.Dict[str, str]

        name : str

        company_id : typing.Optional[str]

        default_payment_method_id : typing.Optional[str]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        UpsertBillingCustomerResponse
            Created

        Examples
        --------
        import asyncio

        from schematic import AsyncSchematic

        client = AsyncSchematic(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.billing.upsert_billing_customer(
                email="email",
                external_id="external_id",
                failed_to_import=True,
                meta={"key": "value"},
                name="name",
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.upsert_billing_customer(
            email=email,
            external_id=external_id,
            failed_to_import=failed_to_import,
            meta=meta,
            name=name,
            company_id=company_id,
            default_payment_method_id=default_payment_method_id,
            request_options=request_options,
        )
        return _response.data

    async def list_customers_with_subscriptions(
        self,
        *,
        company_ids: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
        name: typing.Optional[str] = None,
        failed_to_import: typing.Optional[bool] = None,
        q: typing.Optional[str] = None,
        limit: typing.Optional[int] = None,
        offset: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ListCustomersWithSubscriptionsResponse:
        """
        Parameters
        ----------
        company_ids : typing.Optional[typing.Union[str, typing.Sequence[str]]]

        name : typing.Optional[str]

        failed_to_import : typing.Optional[bool]

        q : typing.Optional[str]

        limit : typing.Optional[int]
            Page limit (default 100)

        offset : typing.Optional[int]
            Page offset (default 0)

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        ListCustomersWithSubscriptionsResponse
            OK

        Examples
        --------
        import asyncio

        from schematic import AsyncSchematic

        client = AsyncSchematic(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.billing.list_customers_with_subscriptions()


        asyncio.run(main())
        """
        _response = await self._raw_client.list_customers_with_subscriptions(
            company_ids=company_ids,
            name=name,
            failed_to_import=failed_to_import,
            q=q,
            limit=limit,
            offset=offset,
            request_options=request_options,
        )
        return _response.data

    async def count_customers(
        self,
        *,
        company_ids: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
        name: typing.Optional[str] = None,
        failed_to_import: typing.Optional[bool] = None,
        q: typing.Optional[str] = None,
        limit: typing.Optional[int] = None,
        offset: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> CountCustomersResponse:
        """
        Parameters
        ----------
        company_ids : typing.Optional[typing.Union[str, typing.Sequence[str]]]

        name : typing.Optional[str]

        failed_to_import : typing.Optional[bool]

        q : typing.Optional[str]

        limit : typing.Optional[int]
            Page limit (default 100)

        offset : typing.Optional[int]
            Page offset (default 0)

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        CountCustomersResponse
            OK

        Examples
        --------
        import asyncio

        from schematic import AsyncSchematic

        client = AsyncSchematic(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.billing.count_customers()


        asyncio.run(main())
        """
        _response = await self._raw_client.count_customers(
            company_ids=company_ids,
            name=name,
            failed_to_import=failed_to_import,
            q=q,
            limit=limit,
            offset=offset,
            request_options=request_options,
        )
        return _response.data

    async def list_invoices(
        self,
        *,
        customer_external_id: str,
        company_id: typing.Optional[str] = None,
        subscription_external_id: typing.Optional[str] = None,
        limit: typing.Optional[int] = None,
        offset: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ListInvoicesResponse:
        """
        Parameters
        ----------
        customer_external_id : str

        company_id : typing.Optional[str]

        subscription_external_id : typing.Optional[str]

        limit : typing.Optional[int]
            Page limit (default 100)

        offset : typing.Optional[int]
            Page offset (default 0)

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        ListInvoicesResponse
            OK

        Examples
        --------
        import asyncio

        from schematic import AsyncSchematic

        client = AsyncSchematic(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.billing.list_invoices(
                customer_external_id="customer_external_id",
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.list_invoices(
            customer_external_id=customer_external_id,
            company_id=company_id,
            subscription_external_id=subscription_external_id,
            limit=limit,
            offset=offset,
            request_options=request_options,
        )
        return _response.data

    async def upsert_invoice(
        self,
        *,
        amount_due: int,
        amount_paid: int,
        amount_remaining: int,
        collection_method: str,
        currency: str,
        customer_external_id: str,
        subtotal: int,
        due_date: typing.Optional[dt.datetime] = OMIT,
        external_id: typing.Optional[str] = OMIT,
        payment_method_external_id: typing.Optional[str] = OMIT,
        subscription_external_id: typing.Optional[str] = OMIT,
        url: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> UpsertInvoiceResponse:
        """
        Parameters
        ----------
        amount_due : int

        amount_paid : int

        amount_remaining : int

        collection_method : str

        currency : str

        customer_external_id : str

        subtotal : int

        due_date : typing.Optional[dt.datetime]

        external_id : typing.Optional[str]

        payment_method_external_id : typing.Optional[str]

        subscription_external_id : typing.Optional[str]

        url : typing.Optional[str]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        UpsertInvoiceResponse
            Created

        Examples
        --------
        import asyncio

        from schematic import AsyncSchematic

        client = AsyncSchematic(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.billing.upsert_invoice(
                amount_due=1,
                amount_paid=1,
                amount_remaining=1,
                collection_method="collection_method",
                currency="currency",
                customer_external_id="customer_external_id",
                subtotal=1,
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.upsert_invoice(
            amount_due=amount_due,
            amount_paid=amount_paid,
            amount_remaining=amount_remaining,
            collection_method=collection_method,
            currency=currency,
            customer_external_id=customer_external_id,
            subtotal=subtotal,
            due_date=due_date,
            external_id=external_id,
            payment_method_external_id=payment_method_external_id,
            subscription_external_id=subscription_external_id,
            url=url,
            request_options=request_options,
        )
        return _response.data

    async def list_meters(
        self,
        *,
        display_name: typing.Optional[str] = None,
        limit: typing.Optional[int] = None,
        offset: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ListMetersResponse:
        """
        Parameters
        ----------
        display_name : typing.Optional[str]

        limit : typing.Optional[int]
            Page limit (default 100)

        offset : typing.Optional[int]
            Page offset (default 0)

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        ListMetersResponse
            OK

        Examples
        --------
        import asyncio

        from schematic import AsyncSchematic

        client = AsyncSchematic(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.billing.list_meters()


        asyncio.run(main())
        """
        _response = await self._raw_client.list_meters(
            display_name=display_name, limit=limit, offset=offset, request_options=request_options
        )
        return _response.data

    async def upsert_billing_meter(
        self,
        *,
        display_name: str,
        event_name: str,
        event_payload_key: str,
        external_id: str,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> UpsertBillingMeterResponse:
        """
        Parameters
        ----------
        display_name : str

        event_name : str

        event_payload_key : str

        external_id : str

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        UpsertBillingMeterResponse
            Created

        Examples
        --------
        import asyncio

        from schematic import AsyncSchematic

        client = AsyncSchematic(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.billing.upsert_billing_meter(
                display_name="display_name",
                event_name="event_name",
                event_payload_key="event_payload_key",
                external_id="external_id",
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.upsert_billing_meter(
            display_name=display_name,
            event_name=event_name,
            event_payload_key=event_payload_key,
            external_id=external_id,
            request_options=request_options,
        )
        return _response.data

    async def list_payment_methods(
        self,
        *,
        customer_external_id: str,
        company_id: typing.Optional[str] = None,
        limit: typing.Optional[int] = None,
        offset: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ListPaymentMethodsResponse:
        """
        Parameters
        ----------
        customer_external_id : str

        company_id : typing.Optional[str]

        limit : typing.Optional[int]
            Page limit (default 100)

        offset : typing.Optional[int]
            Page offset (default 0)

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        ListPaymentMethodsResponse
            OK

        Examples
        --------
        import asyncio

        from schematic import AsyncSchematic

        client = AsyncSchematic(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.billing.list_payment_methods(
                customer_external_id="customer_external_id",
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.list_payment_methods(
            customer_external_id=customer_external_id,
            company_id=company_id,
            limit=limit,
            offset=offset,
            request_options=request_options,
        )
        return _response.data

    async def upsert_payment_method(
        self,
        *,
        customer_external_id: str,
        external_id: str,
        payment_method_type: str,
        account_last_4: typing.Optional[str] = OMIT,
        account_name: typing.Optional[str] = OMIT,
        bank_name: typing.Optional[str] = OMIT,
        billing_email: typing.Optional[str] = OMIT,
        billing_name: typing.Optional[str] = OMIT,
        card_brand: typing.Optional[str] = OMIT,
        card_exp_month: typing.Optional[int] = OMIT,
        card_exp_year: typing.Optional[int] = OMIT,
        card_last_4: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> UpsertPaymentMethodResponse:
        """
        Parameters
        ----------
        customer_external_id : str

        external_id : str

        payment_method_type : str

        account_last_4 : typing.Optional[str]

        account_name : typing.Optional[str]

        bank_name : typing.Optional[str]

        billing_email : typing.Optional[str]

        billing_name : typing.Optional[str]

        card_brand : typing.Optional[str]

        card_exp_month : typing.Optional[int]

        card_exp_year : typing.Optional[int]

        card_last_4 : typing.Optional[str]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        UpsertPaymentMethodResponse
            Created

        Examples
        --------
        import asyncio

        from schematic import AsyncSchematic

        client = AsyncSchematic(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.billing.upsert_payment_method(
                customer_external_id="customer_external_id",
                external_id="external_id",
                payment_method_type="payment_method_type",
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.upsert_payment_method(
            customer_external_id=customer_external_id,
            external_id=external_id,
            payment_method_type=payment_method_type,
            account_last_4=account_last_4,
            account_name=account_name,
            bank_name=bank_name,
            billing_email=billing_email,
            billing_name=billing_name,
            card_brand=card_brand,
            card_exp_month=card_exp_month,
            card_exp_year=card_exp_year,
            card_last_4=card_last_4,
            request_options=request_options,
        )
        return _response.data

    async def search_billing_prices(
        self,
        *,
        ids: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
        q: typing.Optional[str] = None,
        interval: typing.Optional[str] = None,
        usage_type: typing.Optional[SearchBillingPricesRequestUsageType] = None,
        price: typing.Optional[int] = None,
        limit: typing.Optional[int] = None,
        offset: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> SearchBillingPricesResponse:
        """
        Parameters
        ----------
        ids : typing.Optional[typing.Union[str, typing.Sequence[str]]]

        q : typing.Optional[str]

        interval : typing.Optional[str]

        usage_type : typing.Optional[SearchBillingPricesRequestUsageType]

        price : typing.Optional[int]

        limit : typing.Optional[int]
            Page limit (default 100)

        offset : typing.Optional[int]
            Page offset (default 0)

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        SearchBillingPricesResponse
            OK

        Examples
        --------
        import asyncio

        from schematic import AsyncSchematic

        client = AsyncSchematic(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.billing.search_billing_prices()


        asyncio.run(main())
        """
        _response = await self._raw_client.search_billing_prices(
            ids=ids,
            q=q,
            interval=interval,
            usage_type=usage_type,
            price=price,
            limit=limit,
            offset=offset,
            request_options=request_options,
        )
        return _response.data

    async def upsert_billing_price(
        self,
        *,
        billing_scheme: CreateBillingPriceRequestBodyBillingScheme,
        currency: str,
        external_account_id: str,
        interval: str,
        is_active: bool,
        price: int,
        price_external_id: str,
        price_tiers: typing.Sequence[CreateBillingPriceTierRequestBody],
        product_external_id: str,
        usage_type: CreateBillingPriceRequestBodyUsageType,
        meter_id: typing.Optional[str] = OMIT,
        package_size: typing.Optional[int] = OMIT,
        price_decimal: typing.Optional[str] = OMIT,
        tier_mode: typing.Optional[CreateBillingPriceRequestBodyTierMode] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> UpsertBillingPriceResponse:
        """
        Parameters
        ----------
        billing_scheme : CreateBillingPriceRequestBodyBillingScheme

        currency : str

        external_account_id : str

        interval : str

        is_active : bool

        price : int

        price_external_id : str

        price_tiers : typing.Sequence[CreateBillingPriceTierRequestBody]

        product_external_id : str

        usage_type : CreateBillingPriceRequestBodyUsageType

        meter_id : typing.Optional[str]

        package_size : typing.Optional[int]

        price_decimal : typing.Optional[str]

        tier_mode : typing.Optional[CreateBillingPriceRequestBodyTierMode]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        UpsertBillingPriceResponse
            Created

        Examples
        --------
        import asyncio

        from schematic import AsyncSchematic, CreateBillingPriceTierRequestBody

        client = AsyncSchematic(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.billing.upsert_billing_price(
                billing_scheme="per_unit",
                currency="currency",
                external_account_id="external_account_id",
                interval="interval",
                is_active=True,
                price=1,
                price_external_id="price_external_id",
                price_tiers=[
                    CreateBillingPriceTierRequestBody(
                        price_external_id="price_external_id",
                    )
                ],
                product_external_id="product_external_id",
                usage_type="licensed",
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.upsert_billing_price(
            billing_scheme=billing_scheme,
            currency=currency,
            external_account_id=external_account_id,
            interval=interval,
            is_active=is_active,
            price=price,
            price_external_id=price_external_id,
            price_tiers=price_tiers,
            product_external_id=product_external_id,
            usage_type=usage_type,
            meter_id=meter_id,
            package_size=package_size,
            price_decimal=price_decimal,
            tier_mode=tier_mode,
            request_options=request_options,
        )
        return _response.data

    async def delete_billing_product(
        self, billing_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> DeleteBillingProductResponse:
        """
        Parameters
        ----------
        billing_id : str
            billing_id

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        DeleteBillingProductResponse
            OK

        Examples
        --------
        import asyncio

        from schematic import AsyncSchematic

        client = AsyncSchematic(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.billing.delete_billing_product(
                billing_id="billing_id",
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.delete_billing_product(billing_id, request_options=request_options)
        return _response.data

    async def list_product_prices(
        self,
        *,
        ids: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
        name: typing.Optional[str] = None,
        q: typing.Optional[str] = None,
        price_usage_type: typing.Optional[ListProductPricesRequestPriceUsageType] = None,
        without_linked_to_plan: typing.Optional[bool] = None,
        with_one_time_charges: typing.Optional[bool] = None,
        with_zero_price: typing.Optional[bool] = None,
        with_prices_only: typing.Optional[bool] = None,
        is_active: typing.Optional[bool] = None,
        limit: typing.Optional[int] = None,
        offset: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ListProductPricesResponse:
        """
        Parameters
        ----------
        ids : typing.Optional[typing.Union[str, typing.Sequence[str]]]

        name : typing.Optional[str]

        q : typing.Optional[str]

        price_usage_type : typing.Optional[ListProductPricesRequestPriceUsageType]

        without_linked_to_plan : typing.Optional[bool]
            Filter products that are not linked to any plan

        with_one_time_charges : typing.Optional[bool]
            Filter products that are one time charges

        with_zero_price : typing.Optional[bool]
            Filter products that have zero price for free subscription type

        with_prices_only : typing.Optional[bool]
            Filter products that have prices

        is_active : typing.Optional[bool]
            Filter products that are active

        limit : typing.Optional[int]
            Page limit (default 100)

        offset : typing.Optional[int]
            Page offset (default 0)

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        ListProductPricesResponse
            OK

        Examples
        --------
        import asyncio

        from schematic import AsyncSchematic

        client = AsyncSchematic(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.billing.list_product_prices()


        asyncio.run(main())
        """
        _response = await self._raw_client.list_product_prices(
            ids=ids,
            name=name,
            q=q,
            price_usage_type=price_usage_type,
            without_linked_to_plan=without_linked_to_plan,
            with_one_time_charges=with_one_time_charges,
            with_zero_price=with_zero_price,
            with_prices_only=with_prices_only,
            is_active=is_active,
            limit=limit,
            offset=offset,
            request_options=request_options,
        )
        return _response.data

    async def delete_product_price(
        self, billing_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> DeleteProductPriceResponse:
        """
        Parameters
        ----------
        billing_id : str
            billing_id

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        DeleteProductPriceResponse
            OK

        Examples
        --------
        import asyncio

        from schematic import AsyncSchematic

        client = AsyncSchematic(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.billing.delete_product_price(
                billing_id="billing_id",
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.delete_product_price(billing_id, request_options=request_options)
        return _response.data

    async def upsert_billing_product(
        self,
        *,
        external_id: str,
        name: str,
        price: float,
        is_active: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> UpsertBillingProductResponse:
        """
        Parameters
        ----------
        external_id : str

        name : str

        price : float

        is_active : typing.Optional[bool]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        UpsertBillingProductResponse
            Created

        Examples
        --------
        import asyncio

        from schematic import AsyncSchematic

        client = AsyncSchematic(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.billing.upsert_billing_product(
                external_id="external_id",
                name="name",
                price=1.1,
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.upsert_billing_product(
            external_id=external_id, name=name, price=price, is_active=is_active, request_options=request_options
        )
        return _response.data

    async def list_billing_products(
        self,
        *,
        ids: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
        name: typing.Optional[str] = None,
        q: typing.Optional[str] = None,
        price_usage_type: typing.Optional[ListBillingProductsRequestPriceUsageType] = None,
        without_linked_to_plan: typing.Optional[bool] = None,
        with_one_time_charges: typing.Optional[bool] = None,
        with_zero_price: typing.Optional[bool] = None,
        with_prices_only: typing.Optional[bool] = None,
        is_active: typing.Optional[bool] = None,
        limit: typing.Optional[int] = None,
        offset: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ListBillingProductsResponse:
        """
        Parameters
        ----------
        ids : typing.Optional[typing.Union[str, typing.Sequence[str]]]

        name : typing.Optional[str]

        q : typing.Optional[str]

        price_usage_type : typing.Optional[ListBillingProductsRequestPriceUsageType]

        without_linked_to_plan : typing.Optional[bool]
            Filter products that are not linked to any plan

        with_one_time_charges : typing.Optional[bool]
            Filter products that are one time charges

        with_zero_price : typing.Optional[bool]
            Filter products that have zero price for free subscription type

        with_prices_only : typing.Optional[bool]
            Filter products that have prices

        is_active : typing.Optional[bool]
            Filter products that are active

        limit : typing.Optional[int]
            Page limit (default 100)

        offset : typing.Optional[int]
            Page offset (default 0)

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        ListBillingProductsResponse
            OK

        Examples
        --------
        import asyncio

        from schematic import AsyncSchematic

        client = AsyncSchematic(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.billing.list_billing_products()


        asyncio.run(main())
        """
        _response = await self._raw_client.list_billing_products(
            ids=ids,
            name=name,
            q=q,
            price_usage_type=price_usage_type,
            without_linked_to_plan=without_linked_to_plan,
            with_one_time_charges=with_one_time_charges,
            with_zero_price=with_zero_price,
            with_prices_only=with_prices_only,
            is_active=is_active,
            limit=limit,
            offset=offset,
            request_options=request_options,
        )
        return _response.data

    async def count_billing_products(
        self,
        *,
        ids: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
        name: typing.Optional[str] = None,
        q: typing.Optional[str] = None,
        price_usage_type: typing.Optional[CountBillingProductsRequestPriceUsageType] = None,
        without_linked_to_plan: typing.Optional[bool] = None,
        with_one_time_charges: typing.Optional[bool] = None,
        with_zero_price: typing.Optional[bool] = None,
        with_prices_only: typing.Optional[bool] = None,
        is_active: typing.Optional[bool] = None,
        limit: typing.Optional[int] = None,
        offset: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> CountBillingProductsResponse:
        """
        Parameters
        ----------
        ids : typing.Optional[typing.Union[str, typing.Sequence[str]]]

        name : typing.Optional[str]

        q : typing.Optional[str]

        price_usage_type : typing.Optional[CountBillingProductsRequestPriceUsageType]

        without_linked_to_plan : typing.Optional[bool]
            Filter products that are not linked to any plan

        with_one_time_charges : typing.Optional[bool]
            Filter products that are one time charges

        with_zero_price : typing.Optional[bool]
            Filter products that have zero price for free subscription type

        with_prices_only : typing.Optional[bool]
            Filter products that have prices

        is_active : typing.Optional[bool]
            Filter products that are active

        limit : typing.Optional[int]
            Page limit (default 100)

        offset : typing.Optional[int]
            Page offset (default 0)

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        CountBillingProductsResponse
            OK

        Examples
        --------
        import asyncio

        from schematic import AsyncSchematic

        client = AsyncSchematic(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.billing.count_billing_products()


        asyncio.run(main())
        """
        _response = await self._raw_client.count_billing_products(
            ids=ids,
            name=name,
            q=q,
            price_usage_type=price_usage_type,
            without_linked_to_plan=without_linked_to_plan,
            with_one_time_charges=with_one_time_charges,
            with_zero_price=with_zero_price,
            with_prices_only=with_prices_only,
            is_active=is_active,
            limit=limit,
            offset=offset,
            request_options=request_options,
        )
        return _response.data

    async def upsert_billing_subscription(
        self,
        *,
        cancel_at_period_end: bool,
        currency: str,
        customer_external_id: str,
        discounts: typing.Sequence[BillingSubscriptionDiscount],
        expired_at: dt.datetime,
        product_external_ids: typing.Sequence[BillingProductPricing],
        subscription_external_id: str,
        total_price: int,
        cancel_at: typing.Optional[int] = OMIT,
        default_payment_method_id: typing.Optional[str] = OMIT,
        interval: typing.Optional[str] = OMIT,
        metadata: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
        period_end: typing.Optional[int] = OMIT,
        period_start: typing.Optional[int] = OMIT,
        status: typing.Optional[str] = OMIT,
        trial_end: typing.Optional[int] = OMIT,
        trial_end_setting: typing.Optional[CreateBillingSubscriptionsRequestBodyTrialEndSetting] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> UpsertBillingSubscriptionResponse:
        """
        Parameters
        ----------
        cancel_at_period_end : bool

        currency : str

        customer_external_id : str

        discounts : typing.Sequence[BillingSubscriptionDiscount]

        expired_at : dt.datetime

        product_external_ids : typing.Sequence[BillingProductPricing]

        subscription_external_id : str

        total_price : int

        cancel_at : typing.Optional[int]

        default_payment_method_id : typing.Optional[str]

        interval : typing.Optional[str]

        metadata : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]

        period_end : typing.Optional[int]

        period_start : typing.Optional[int]

        status : typing.Optional[str]

        trial_end : typing.Optional[int]

        trial_end_setting : typing.Optional[CreateBillingSubscriptionsRequestBodyTrialEndSetting]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        UpsertBillingSubscriptionResponse
            Created

        Examples
        --------
        import asyncio
        import datetime

        from schematic import (
            AsyncSchematic,
            BillingProductPricing,
            BillingSubscriptionDiscount,
        )

        client = AsyncSchematic(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.billing.upsert_billing_subscription(
                cancel_at_period_end=True,
                currency="currency",
                customer_external_id="customer_external_id",
                discounts=[
                    BillingSubscriptionDiscount(
                        coupon_external_id="coupon_external_id",
                        external_id="external_id",
                        is_active=True,
                        started_at=datetime.datetime.fromisoformat(
                            "2024-01-15 09:30:00+00:00",
                        ),
                    )
                ],
                expired_at=datetime.datetime.fromisoformat(
                    "2024-01-15 09:30:00+00:00",
                ),
                product_external_ids=[
                    BillingProductPricing(
                        currency="currency",
                        interval="interval",
                        price=1,
                        price_external_id="price_external_id",
                        product_external_id="product_external_id",
                        quantity=1,
                        usage_type="licensed",
                    )
                ],
                subscription_external_id="subscription_external_id",
                total_price=1,
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.upsert_billing_subscription(
            cancel_at_period_end=cancel_at_period_end,
            currency=currency,
            customer_external_id=customer_external_id,
            discounts=discounts,
            expired_at=expired_at,
            product_external_ids=product_external_ids,
            subscription_external_id=subscription_external_id,
            total_price=total_price,
            cancel_at=cancel_at,
            default_payment_method_id=default_payment_method_id,
            interval=interval,
            metadata=metadata,
            period_end=period_end,
            period_start=period_start,
            status=status,
            trial_end=trial_end,
            trial_end_setting=trial_end_setting,
            request_options=request_options,
        )
        return _response.data
