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

import typing
from ..core.client_wrapper import SyncClientWrapper
from ..core.request_options import RequestOptions
from .types.upsert_billing_coupon_response import UpsertBillingCouponResponse
from ..core.pydantic_utilities import parse_obj_as
from ..errors.bad_request_error import BadRequestError
from ..types.api_error import ApiError as types_api_error_ApiError
from ..errors.unauthorized_error import UnauthorizedError
from ..errors.forbidden_error import ForbiddenError
from ..errors.internal_server_error import InternalServerError
from json.decoder import JSONDecodeError
from ..core.api_error import ApiError as core_api_error_ApiError
from .types.upsert_billing_customer_response import UpsertBillingCustomerResponse
from .types.list_customers_response import ListCustomersResponse
from .types.count_customers_response import CountCustomersResponse
from .types.list_invoices_response import ListInvoicesResponse
import datetime as dt
from .types.upsert_invoice_response import UpsertInvoiceResponse
from .types.list_meters_response import ListMetersResponse
from .types.upsert_billing_meter_response import UpsertBillingMeterResponse
from .types.list_payment_methods_response import ListPaymentMethodsResponse
from .types.upsert_payment_method_response import UpsertPaymentMethodResponse
from .types.search_billing_prices_response import SearchBillingPricesResponse
from .types.upsert_billing_price_response import UpsertBillingPriceResponse
from .types.list_product_prices_response import ListProductPricesResponse
from .types.delete_product_price_response import DeleteProductPriceResponse
from ..core.jsonable_encoder import jsonable_encoder
from .types.upsert_billing_product_response import UpsertBillingProductResponse
from .types.list_billing_products_response import ListBillingProductsResponse
from .types.count_billing_products_response import CountBillingProductsResponse
from ..types.billing_subscription_discount import BillingSubscriptionDiscount
from ..types.billing_product_pricing import BillingProductPricing
from .types.upsert_billing_subscription_response import UpsertBillingSubscriptionResponse
from ..core.serialization import convert_and_respect_annotation_metadata
from ..core.client_wrapper import AsyncClientWrapper

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


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

    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._client_wrapper.httpx_client.request(
            "billing/coupons",
            method="POST",
            json={
                "amount_off": amount_off,
                "currency": currency,
                "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,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    UpsertBillingCouponResponse,
                    parse_obj_as(
                        type_=UpsertBillingCouponResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(status_code=_response.status_code, body=_response.text)
        raise core_api_error_ApiError(status_code=_response.status_code, body=_response_json)

    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,
        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]

        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._client_wrapper.httpx_client.request(
            "billing/customer/upsert",
            method="POST",
            json={
                "company_id": company_id,
                "email": email,
                "external_id": external_id,
                "failed_to_import": failed_to_import,
                "meta": meta,
                "name": name,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    UpsertBillingCustomerResponse,
                    parse_obj_as(
                        type_=UpsertBillingCustomerResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(status_code=_response.status_code, body=_response.text)
        raise core_api_error_ApiError(status_code=_response.status_code, body=_response_json)

    def list_customers(
        self,
        *,
        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,
    ) -> ListCustomersResponse:
        """
        Parameters
        ----------
        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
        -------
        ListCustomersResponse
            OK

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

        client = Schematic(
            api_key="YOUR_API_KEY",
        )
        client.billing.list_customers()
        """
        _response = self._client_wrapper.httpx_client.request(
            "billing/customers",
            method="GET",
            params={
                "name": name,
                "failed_to_import": failed_to_import,
                "q": q,
                "limit": limit,
                "offset": offset,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    ListCustomersResponse,
                    parse_obj_as(
                        type_=ListCustomersResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(status_code=_response.status_code, body=_response.text)
        raise core_api_error_ApiError(status_code=_response.status_code, body=_response_json)

    def count_customers(
        self,
        *,
        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
        ----------
        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._client_wrapper.httpx_client.request(
            "billing/customers/count",
            method="GET",
            params={
                "name": name,
                "failed_to_import": failed_to_import,
                "q": q,
                "limit": limit,
                "offset": offset,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    CountCustomersResponse,
                    parse_obj_as(
                        type_=CountCustomersResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(status_code=_response.status_code, body=_response.text)
        raise core_api_error_ApiError(status_code=_response.status_code, body=_response_json)

    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._client_wrapper.httpx_client.request(
            "billing/invoices",
            method="GET",
            params={
                "company_id": company_id,
                "customer_external_id": customer_external_id,
                "subscription_external_id": subscription_external_id,
                "limit": limit,
                "offset": offset,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    ListInvoicesResponse,
                    parse_obj_as(
                        type_=ListInvoicesResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(status_code=_response.status_code, body=_response.text)
        raise core_api_error_ApiError(status_code=_response.status_code, body=_response_json)

    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._client_wrapper.httpx_client.request(
            "billing/invoices",
            method="POST",
            json={
                "amount_due": amount_due,
                "amount_paid": amount_paid,
                "amount_remaining": amount_remaining,
                "collection_method": collection_method,
                "currency": currency,
                "customer_external_id": customer_external_id,
                "due_date": due_date,
                "external_id": external_id,
                "payment_method_external_id": payment_method_external_id,
                "subscription_external_id": subscription_external_id,
                "subtotal": subtotal,
                "url": url,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    UpsertInvoiceResponse,
                    parse_obj_as(
                        type_=UpsertInvoiceResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(status_code=_response.status_code, body=_response.text)
        raise core_api_error_ApiError(status_code=_response.status_code, body=_response_json)

    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._client_wrapper.httpx_client.request(
            "billing/meter",
            method="GET",
            params={
                "display_name": display_name,
                "limit": limit,
                "offset": offset,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    ListMetersResponse,
                    parse_obj_as(
                        type_=ListMetersResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(status_code=_response.status_code, body=_response.text)
        raise core_api_error_ApiError(status_code=_response.status_code, body=_response_json)

    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._client_wrapper.httpx_client.request(
            "billing/meter/upsert",
            method="POST",
            json={
                "display_name": display_name,
                "event_name": event_name,
                "event_payload_key": event_payload_key,
                "external_id": external_id,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    UpsertBillingMeterResponse,
                    parse_obj_as(
                        type_=UpsertBillingMeterResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(status_code=_response.status_code, body=_response.text)
        raise core_api_error_ApiError(status_code=_response.status_code, body=_response_json)

    def list_payment_methods(
        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,
    ) -> ListPaymentMethodsResponse:
        """
        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
        -------
        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._client_wrapper.httpx_client.request(
            "billing/payment-methods",
            method="GET",
            params={
                "company_id": company_id,
                "customer_external_id": customer_external_id,
                "subscription_external_id": subscription_external_id,
                "limit": limit,
                "offset": offset,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    ListPaymentMethodsResponse,
                    parse_obj_as(
                        type_=ListPaymentMethodsResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(status_code=_response.status_code, body=_response.text)
        raise core_api_error_ApiError(status_code=_response.status_code, body=_response_json)

    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,
        subscription_external_id: 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]

        subscription_external_id : 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._client_wrapper.httpx_client.request(
            "billing/payment-methods",
            method="POST",
            json={
                "account_last4": 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_last4": card_last_4,
                "customer_external_id": customer_external_id,
                "external_id": external_id,
                "payment_method_type": payment_method_type,
                "subscription_external_id": subscription_external_id,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    UpsertPaymentMethodResponse,
                    parse_obj_as(
                        type_=UpsertPaymentMethodResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(status_code=_response.status_code, body=_response.text)
        raise core_api_error_ApiError(status_code=_response.status_code, body=_response_json)

    def search_billing_prices(
        self,
        *,
        ids: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
        interval: typing.Optional[str] = None,
        usage_type: typing.Optional[str] = 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]]]

        interval : typing.Optional[str]

        usage_type : typing.Optional[str]

        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._client_wrapper.httpx_client.request(
            "billing/price",
            method="GET",
            params={
                "ids": ids,
                "interval": interval,
                "usage_type": usage_type,
                "price": price,
                "limit": limit,
                "offset": offset,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    SearchBillingPricesResponse,
                    parse_obj_as(
                        type_=SearchBillingPricesResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(status_code=_response.status_code, body=_response.text)
        raise core_api_error_ApiError(status_code=_response.status_code, body=_response_json)

    def upsert_billing_price(
        self,
        *,
        currency: str,
        interval: str,
        is_active: bool,
        price: int,
        price_external_id: str,
        product_external_id: str,
        usage_type: str,
        meter_id: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> UpsertBillingPriceResponse:
        """
        Parameters
        ----------
        currency : str

        interval : str

        is_active : bool

        price : int

        price_external_id : str

        product_external_id : str

        usage_type : str

        meter_id : typing.Optional[str]

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

        Returns
        -------
        UpsertBillingPriceResponse
            Created

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

        client = Schematic(
            api_key="YOUR_API_KEY",
        )
        client.billing.upsert_billing_price(
            currency="currency",
            interval="interval",
            is_active=True,
            price=1,
            price_external_id="price_external_id",
            product_external_id="product_external_id",
            usage_type="usage_type",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            "billing/price/upsert",
            method="POST",
            json={
                "currency": currency,
                "interval": interval,
                "is_active": is_active,
                "meter_id": meter_id,
                "price": price,
                "price_external_id": price_external_id,
                "product_external_id": product_external_id,
                "usage_type": usage_type,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    UpsertBillingPriceResponse,
                    parse_obj_as(
                        type_=UpsertBillingPriceResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(status_code=_response.status_code, body=_response.text)
        raise core_api_error_ApiError(status_code=_response.status_code, body=_response_json)

    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[str] = None,
        without_linked_to_plan: typing.Optional[bool] = None,
        with_zero_price: typing.Optional[bool] = None,
        with_prices_only: 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[str]

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

        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

        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._client_wrapper.httpx_client.request(
            "billing/product/prices",
            method="GET",
            params={
                "ids": ids,
                "name": name,
                "q": q,
                "price_usage_type": price_usage_type,
                "without_linked_to_plan": without_linked_to_plan,
                "with_zero_price": with_zero_price,
                "with_prices_only": with_prices_only,
                "limit": limit,
                "offset": offset,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    ListProductPricesResponse,
                    parse_obj_as(
                        type_=ListProductPricesResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(status_code=_response.status_code, body=_response.text)
        raise core_api_error_ApiError(status_code=_response.status_code, body=_response_json)

    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._client_wrapper.httpx_client.request(
            f"billing/product/prices/{jsonable_encoder(billing_id)}",
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    DeleteProductPriceResponse,
                    parse_obj_as(
                        type_=DeleteProductPriceResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(status_code=_response.status_code, body=_response.text)
        raise core_api_error_ApiError(status_code=_response.status_code, body=_response_json)

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

        external_id : str

        name : str

        price : float

        quantity : int

        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(
            currency="currency",
            external_id="external_id",
            name="name",
            price=1.1,
            quantity=1,
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            "billing/product/upsert",
            method="POST",
            json={
                "currency": currency,
                "external_id": external_id,
                "name": name,
                "price": price,
                "quantity": quantity,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    UpsertBillingProductResponse,
                    parse_obj_as(
                        type_=UpsertBillingProductResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(status_code=_response.status_code, body=_response.text)
        raise core_api_error_ApiError(status_code=_response.status_code, body=_response_json)

    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[str] = None,
        without_linked_to_plan: typing.Optional[bool] = None,
        with_zero_price: typing.Optional[bool] = None,
        with_prices_only: 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[str]

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

        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

        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._client_wrapper.httpx_client.request(
            "billing/products",
            method="GET",
            params={
                "ids": ids,
                "name": name,
                "q": q,
                "price_usage_type": price_usage_type,
                "without_linked_to_plan": without_linked_to_plan,
                "with_zero_price": with_zero_price,
                "with_prices_only": with_prices_only,
                "limit": limit,
                "offset": offset,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    ListBillingProductsResponse,
                    parse_obj_as(
                        type_=ListBillingProductsResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(status_code=_response.status_code, body=_response.text)
        raise core_api_error_ApiError(status_code=_response.status_code, body=_response_json)

    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[str] = None,
        without_linked_to_plan: typing.Optional[bool] = None,
        with_zero_price: typing.Optional[bool] = None,
        with_prices_only: 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[str]

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

        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

        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._client_wrapper.httpx_client.request(
            "billing/products/count",
            method="GET",
            params={
                "ids": ids,
                "name": name,
                "q": q,
                "price_usage_type": price_usage_type,
                "without_linked_to_plan": without_linked_to_plan,
                "with_zero_price": with_zero_price,
                "with_prices_only": with_prices_only,
                "limit": limit,
                "offset": offset,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    CountBillingProductsResponse,
                    parse_obj_as(
                        type_=CountBillingProductsResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(status_code=_response.status_code, body=_response.text)
        raise core_api_error_ApiError(status_code=_response.status_code, body=_response_json)

    def upsert_billing_subscription(
        self,
        *,
        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,
        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[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> UpsertBillingSubscriptionResponse:
        """
        Parameters
        ----------
        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

        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[str]

        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(
            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="usage_type",
                )
            ],
            subscription_external_id="subscription_external_id",
            total_price=1,
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            "billing/subscription/upsert",
            method="POST",
            json={
                "currency": currency,
                "customer_external_id": customer_external_id,
                "discounts": convert_and_respect_annotation_metadata(
                    object_=discounts, annotation=typing.Sequence[BillingSubscriptionDiscount], direction="write"
                ),
                "expired_at": expired_at,
                "interval": interval,
                "metadata": metadata,
                "period_end": period_end,
                "period_start": period_start,
                "product_external_ids": convert_and_respect_annotation_metadata(
                    object_=product_external_ids, annotation=typing.Sequence[BillingProductPricing], direction="write"
                ),
                "status": status,
                "subscription_external_id": subscription_external_id,
                "total_price": total_price,
                "trial_end": trial_end,
                "trial_end_setting": trial_end_setting,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    UpsertBillingSubscriptionResponse,
                    parse_obj_as(
                        type_=UpsertBillingSubscriptionResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(status_code=_response.status_code, body=_response.text)
        raise core_api_error_ApiError(status_code=_response.status_code, body=_response_json)


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

    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._client_wrapper.httpx_client.request(
            "billing/coupons",
            method="POST",
            json={
                "amount_off": amount_off,
                "currency": currency,
                "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,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    UpsertBillingCouponResponse,
                    parse_obj_as(
                        type_=UpsertBillingCouponResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(status_code=_response.status_code, body=_response.text)
        raise core_api_error_ApiError(status_code=_response.status_code, body=_response_json)

    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,
        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]

        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._client_wrapper.httpx_client.request(
            "billing/customer/upsert",
            method="POST",
            json={
                "company_id": company_id,
                "email": email,
                "external_id": external_id,
                "failed_to_import": failed_to_import,
                "meta": meta,
                "name": name,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    UpsertBillingCustomerResponse,
                    parse_obj_as(
                        type_=UpsertBillingCustomerResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(status_code=_response.status_code, body=_response.text)
        raise core_api_error_ApiError(status_code=_response.status_code, body=_response_json)

    async def list_customers(
        self,
        *,
        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,
    ) -> ListCustomersResponse:
        """
        Parameters
        ----------
        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
        -------
        ListCustomersResponse
            OK

        Examples
        --------
        import asyncio

        from schematic import AsyncSchematic

        client = AsyncSchematic(
            api_key="YOUR_API_KEY",
        )


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


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            "billing/customers",
            method="GET",
            params={
                "name": name,
                "failed_to_import": failed_to_import,
                "q": q,
                "limit": limit,
                "offset": offset,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    ListCustomersResponse,
                    parse_obj_as(
                        type_=ListCustomersResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(status_code=_response.status_code, body=_response.text)
        raise core_api_error_ApiError(status_code=_response.status_code, body=_response_json)

    async def count_customers(
        self,
        *,
        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
        ----------
        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._client_wrapper.httpx_client.request(
            "billing/customers/count",
            method="GET",
            params={
                "name": name,
                "failed_to_import": failed_to_import,
                "q": q,
                "limit": limit,
                "offset": offset,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    CountCustomersResponse,
                    parse_obj_as(
                        type_=CountCustomersResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(status_code=_response.status_code, body=_response.text)
        raise core_api_error_ApiError(status_code=_response.status_code, body=_response_json)

    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._client_wrapper.httpx_client.request(
            "billing/invoices",
            method="GET",
            params={
                "company_id": company_id,
                "customer_external_id": customer_external_id,
                "subscription_external_id": subscription_external_id,
                "limit": limit,
                "offset": offset,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    ListInvoicesResponse,
                    parse_obj_as(
                        type_=ListInvoicesResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(status_code=_response.status_code, body=_response.text)
        raise core_api_error_ApiError(status_code=_response.status_code, body=_response_json)

    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._client_wrapper.httpx_client.request(
            "billing/invoices",
            method="POST",
            json={
                "amount_due": amount_due,
                "amount_paid": amount_paid,
                "amount_remaining": amount_remaining,
                "collection_method": collection_method,
                "currency": currency,
                "customer_external_id": customer_external_id,
                "due_date": due_date,
                "external_id": external_id,
                "payment_method_external_id": payment_method_external_id,
                "subscription_external_id": subscription_external_id,
                "subtotal": subtotal,
                "url": url,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    UpsertInvoiceResponse,
                    parse_obj_as(
                        type_=UpsertInvoiceResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(status_code=_response.status_code, body=_response.text)
        raise core_api_error_ApiError(status_code=_response.status_code, body=_response_json)

    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._client_wrapper.httpx_client.request(
            "billing/meter",
            method="GET",
            params={
                "display_name": display_name,
                "limit": limit,
                "offset": offset,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    ListMetersResponse,
                    parse_obj_as(
                        type_=ListMetersResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(status_code=_response.status_code, body=_response.text)
        raise core_api_error_ApiError(status_code=_response.status_code, body=_response_json)

    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._client_wrapper.httpx_client.request(
            "billing/meter/upsert",
            method="POST",
            json={
                "display_name": display_name,
                "event_name": event_name,
                "event_payload_key": event_payload_key,
                "external_id": external_id,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    UpsertBillingMeterResponse,
                    parse_obj_as(
                        type_=UpsertBillingMeterResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(status_code=_response.status_code, body=_response.text)
        raise core_api_error_ApiError(status_code=_response.status_code, body=_response_json)

    async def list_payment_methods(
        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,
    ) -> ListPaymentMethodsResponse:
        """
        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
        -------
        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._client_wrapper.httpx_client.request(
            "billing/payment-methods",
            method="GET",
            params={
                "company_id": company_id,
                "customer_external_id": customer_external_id,
                "subscription_external_id": subscription_external_id,
                "limit": limit,
                "offset": offset,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    ListPaymentMethodsResponse,
                    parse_obj_as(
                        type_=ListPaymentMethodsResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(status_code=_response.status_code, body=_response.text)
        raise core_api_error_ApiError(status_code=_response.status_code, body=_response_json)

    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,
        subscription_external_id: 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]

        subscription_external_id : 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._client_wrapper.httpx_client.request(
            "billing/payment-methods",
            method="POST",
            json={
                "account_last4": 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_last4": card_last_4,
                "customer_external_id": customer_external_id,
                "external_id": external_id,
                "payment_method_type": payment_method_type,
                "subscription_external_id": subscription_external_id,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    UpsertPaymentMethodResponse,
                    parse_obj_as(
                        type_=UpsertPaymentMethodResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(status_code=_response.status_code, body=_response.text)
        raise core_api_error_ApiError(status_code=_response.status_code, body=_response_json)

    async def search_billing_prices(
        self,
        *,
        ids: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
        interval: typing.Optional[str] = None,
        usage_type: typing.Optional[str] = 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]]]

        interval : typing.Optional[str]

        usage_type : typing.Optional[str]

        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._client_wrapper.httpx_client.request(
            "billing/price",
            method="GET",
            params={
                "ids": ids,
                "interval": interval,
                "usage_type": usage_type,
                "price": price,
                "limit": limit,
                "offset": offset,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    SearchBillingPricesResponse,
                    parse_obj_as(
                        type_=SearchBillingPricesResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(status_code=_response.status_code, body=_response.text)
        raise core_api_error_ApiError(status_code=_response.status_code, body=_response_json)

    async def upsert_billing_price(
        self,
        *,
        currency: str,
        interval: str,
        is_active: bool,
        price: int,
        price_external_id: str,
        product_external_id: str,
        usage_type: str,
        meter_id: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> UpsertBillingPriceResponse:
        """
        Parameters
        ----------
        currency : str

        interval : str

        is_active : bool

        price : int

        price_external_id : str

        product_external_id : str

        usage_type : str

        meter_id : typing.Optional[str]

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

        Returns
        -------
        UpsertBillingPriceResponse
            Created

        Examples
        --------
        import asyncio

        from schematic import AsyncSchematic

        client = AsyncSchematic(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.billing.upsert_billing_price(
                currency="currency",
                interval="interval",
                is_active=True,
                price=1,
                price_external_id="price_external_id",
                product_external_id="product_external_id",
                usage_type="usage_type",
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            "billing/price/upsert",
            method="POST",
            json={
                "currency": currency,
                "interval": interval,
                "is_active": is_active,
                "meter_id": meter_id,
                "price": price,
                "price_external_id": price_external_id,
                "product_external_id": product_external_id,
                "usage_type": usage_type,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    UpsertBillingPriceResponse,
                    parse_obj_as(
                        type_=UpsertBillingPriceResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(status_code=_response.status_code, body=_response.text)
        raise core_api_error_ApiError(status_code=_response.status_code, body=_response_json)

    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[str] = None,
        without_linked_to_plan: typing.Optional[bool] = None,
        with_zero_price: typing.Optional[bool] = None,
        with_prices_only: 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[str]

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

        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

        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._client_wrapper.httpx_client.request(
            "billing/product/prices",
            method="GET",
            params={
                "ids": ids,
                "name": name,
                "q": q,
                "price_usage_type": price_usage_type,
                "without_linked_to_plan": without_linked_to_plan,
                "with_zero_price": with_zero_price,
                "with_prices_only": with_prices_only,
                "limit": limit,
                "offset": offset,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    ListProductPricesResponse,
                    parse_obj_as(
                        type_=ListProductPricesResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(status_code=_response.status_code, body=_response.text)
        raise core_api_error_ApiError(status_code=_response.status_code, body=_response_json)

    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._client_wrapper.httpx_client.request(
            f"billing/product/prices/{jsonable_encoder(billing_id)}",
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    DeleteProductPriceResponse,
                    parse_obj_as(
                        type_=DeleteProductPriceResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(status_code=_response.status_code, body=_response.text)
        raise core_api_error_ApiError(status_code=_response.status_code, body=_response_json)

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

        external_id : str

        name : str

        price : float

        quantity : int

        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(
                currency="currency",
                external_id="external_id",
                name="name",
                price=1.1,
                quantity=1,
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            "billing/product/upsert",
            method="POST",
            json={
                "currency": currency,
                "external_id": external_id,
                "name": name,
                "price": price,
                "quantity": quantity,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    UpsertBillingProductResponse,
                    parse_obj_as(
                        type_=UpsertBillingProductResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(status_code=_response.status_code, body=_response.text)
        raise core_api_error_ApiError(status_code=_response.status_code, body=_response_json)

    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[str] = None,
        without_linked_to_plan: typing.Optional[bool] = None,
        with_zero_price: typing.Optional[bool] = None,
        with_prices_only: 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[str]

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

        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

        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._client_wrapper.httpx_client.request(
            "billing/products",
            method="GET",
            params={
                "ids": ids,
                "name": name,
                "q": q,
                "price_usage_type": price_usage_type,
                "without_linked_to_plan": without_linked_to_plan,
                "with_zero_price": with_zero_price,
                "with_prices_only": with_prices_only,
                "limit": limit,
                "offset": offset,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    ListBillingProductsResponse,
                    parse_obj_as(
                        type_=ListBillingProductsResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(status_code=_response.status_code, body=_response.text)
        raise core_api_error_ApiError(status_code=_response.status_code, body=_response_json)

    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[str] = None,
        without_linked_to_plan: typing.Optional[bool] = None,
        with_zero_price: typing.Optional[bool] = None,
        with_prices_only: 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[str]

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

        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

        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._client_wrapper.httpx_client.request(
            "billing/products/count",
            method="GET",
            params={
                "ids": ids,
                "name": name,
                "q": q,
                "price_usage_type": price_usage_type,
                "without_linked_to_plan": without_linked_to_plan,
                "with_zero_price": with_zero_price,
                "with_prices_only": with_prices_only,
                "limit": limit,
                "offset": offset,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    CountBillingProductsResponse,
                    parse_obj_as(
                        type_=CountBillingProductsResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(status_code=_response.status_code, body=_response.text)
        raise core_api_error_ApiError(status_code=_response.status_code, body=_response_json)

    async def upsert_billing_subscription(
        self,
        *,
        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,
        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[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> UpsertBillingSubscriptionResponse:
        """
        Parameters
        ----------
        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

        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[str]

        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(
                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="usage_type",
                    )
                ],
                subscription_external_id="subscription_external_id",
                total_price=1,
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            "billing/subscription/upsert",
            method="POST",
            json={
                "currency": currency,
                "customer_external_id": customer_external_id,
                "discounts": convert_and_respect_annotation_metadata(
                    object_=discounts, annotation=typing.Sequence[BillingSubscriptionDiscount], direction="write"
                ),
                "expired_at": expired_at,
                "interval": interval,
                "metadata": metadata,
                "period_end": period_end,
                "period_start": period_start,
                "product_external_ids": convert_and_respect_annotation_metadata(
                    object_=product_external_ids, annotation=typing.Sequence[BillingProductPricing], direction="write"
                ),
                "status": status,
                "subscription_external_id": subscription_external_id,
                "total_price": total_price,
                "trial_end": trial_end,
                "trial_end_setting": trial_end_setting,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    UpsertBillingSubscriptionResponse,
                    parse_obj_as(
                        type_=UpsertBillingSubscriptionResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(status_code=_response.status_code, body=_response.text)
        raise core_api_error_ApiError(status_code=_response.status_code, body=_response_json)
