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

import typing
from ..core.client_wrapper import SyncClientWrapper
from ..requests.money import MoneyParams
from ..requests.subscription_source import SubscriptionSourceParams
from ..requests.phase import PhaseParams
from ..core.request_options import RequestOptions
from ..core.http_response import HttpResponse
from ..types.create_subscription_response import CreateSubscriptionResponse
from ..core.serialization import convert_and_respect_annotation_metadata
from ..core.unchecked_base_model import construct_type
from json.decoder import JSONDecodeError
from ..core.api_error import ApiError
from ..types.bulk_swap_plan_response import BulkSwapPlanResponse
from ..requests.search_subscriptions_query import SearchSubscriptionsQueryParams
from ..types.search_subscriptions_response import SearchSubscriptionsResponse
from ..types.get_subscription_response import GetSubscriptionResponse
from ..core.jsonable_encoder import jsonable_encoder
from ..requests.subscription import SubscriptionParams
from ..types.update_subscription_response import UpdateSubscriptionResponse
from ..types.delete_subscription_action_response import DeleteSubscriptionActionResponse
from ..types.change_billing_anchor_date_response import ChangeBillingAnchorDateResponse
from ..types.cancel_subscription_response import CancelSubscriptionResponse
from ..types.change_timing import ChangeTiming
from ..types.pause_subscription_response import PauseSubscriptionResponse
from ..types.resume_subscription_response import ResumeSubscriptionResponse
from ..requests.phase_input import PhaseInputParams
from ..types.swap_plan_response import SwapPlanResponse
from ..core.client_wrapper import AsyncClientWrapper
from ..core.http_response import AsyncHttpResponse

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


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

    def create(
        self,
        *,
        location_id: str,
        customer_id: str,
        idempotency_key: typing.Optional[str] = OMIT,
        plan_variation_id: typing.Optional[str] = OMIT,
        start_date: typing.Optional[str] = OMIT,
        canceled_date: typing.Optional[str] = OMIT,
        tax_percentage: typing.Optional[str] = OMIT,
        price_override_money: typing.Optional[MoneyParams] = OMIT,
        card_id: typing.Optional[str] = OMIT,
        timezone: typing.Optional[str] = OMIT,
        source: typing.Optional[SubscriptionSourceParams] = OMIT,
        monthly_billing_anchor_date: typing.Optional[int] = OMIT,
        phases: typing.Optional[typing.Sequence[PhaseParams]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[CreateSubscriptionResponse]:
        """
        Enrolls a customer in a subscription.

        If you provide a card on file in the request, Square charges the card for
        the subscription. Otherwise, Square sends an invoice to the customer's email
        address. The subscription starts immediately, unless the request includes
        the optional `start_date`. Each individual subscription is associated with a particular location.

        For more information, see [Create a subscription](https://developer.squareup.com/docs/subscriptions-api/manage-subscriptions#create-a-subscription).

        Parameters
        ----------
        location_id : str
            The ID of the location the subscription is associated with.

        customer_id : str
            The ID of the [customer](entity:Customer) subscribing to the subscription plan variation.

        idempotency_key : typing.Optional[str]
            A unique string that identifies this `CreateSubscription` request.
            If you do not provide a unique string (or provide an empty string as the value),
            the endpoint treats each request as independent.

            For more information, see [Idempotency keys](https://developer.squareup.com/docs/build-basics/common-api-patterns/idempotency).

        plan_variation_id : typing.Optional[str]
            The ID of the [subscription plan variation](https://developer.squareup.com/docs/subscriptions-api/plans-and-variations#plan-variations) created using the Catalog API.

        start_date : typing.Optional[str]
            The `YYYY-MM-DD`-formatted date to start the subscription.
            If it is unspecified, the subscription starts immediately.

        canceled_date : typing.Optional[str]
            The `YYYY-MM-DD`-formatted date when the newly created subscription is scheduled for cancellation.

            This date overrides the cancellation date set in the plan variation configuration.
            If the cancellation date is earlier than the end date of a subscription cycle, the subscription stops
            at the canceled date and the subscriber is sent a prorated invoice at the beginning of the canceled cycle.

            When the subscription plan of the newly created subscription has a fixed number of cycles and the `canceled_date`
            occurs before the subscription plan expires, the specified `canceled_date` sets the date when the subscription
            stops through the end of the last cycle.

        tax_percentage : typing.Optional[str]
            The tax to add when billing the subscription.
            The percentage is expressed in decimal form, using a `'.'` as the decimal
            separator and without a `'%'` sign. For example, a value of 7.5
            corresponds to 7.5%.

        price_override_money : typing.Optional[MoneyParams]
            A custom price which overrides the cost of a subscription plan variation with `STATIC` pricing.
            This field does not affect itemized subscriptions with `RELATIVE` pricing. Instead,
            you should edit the Subscription's [order template](https://developer.squareup.com/docs/subscriptions-api/manage-subscriptions#phases-and-order-templates).

        card_id : typing.Optional[str]
            The ID of the [subscriber's](entity:Customer) [card](entity:Card) to charge.
            If it is not specified, the subscriber receives an invoice via email with a link to pay for their subscription.

        timezone : typing.Optional[str]
            The timezone that is used in date calculations for the subscription. If unset, defaults to
            the location timezone. If a timezone is not configured for the location, defaults to "America/New_York".
            Format: the IANA Timezone Database identifier for the location timezone. For
            a list of time zones, see [List of tz database time zones](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).

        source : typing.Optional[SubscriptionSourceParams]
            The origination details of the subscription.

        monthly_billing_anchor_date : typing.Optional[int]
            The day-of-the-month to change the billing date to.

        phases : typing.Optional[typing.Sequence[PhaseParams]]
            array of phases for this subscription

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

        Returns
        -------
        HttpResponse[CreateSubscriptionResponse]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            "v2/subscriptions",
            method="POST",
            json={
                "idempotency_key": idempotency_key,
                "location_id": location_id,
                "plan_variation_id": plan_variation_id,
                "customer_id": customer_id,
                "start_date": start_date,
                "canceled_date": canceled_date,
                "tax_percentage": tax_percentage,
                "price_override_money": convert_and_respect_annotation_metadata(
                    object_=price_override_money, annotation=MoneyParams, direction="write"
                ),
                "card_id": card_id,
                "timezone": timezone,
                "source": convert_and_respect_annotation_metadata(
                    object_=source, annotation=SubscriptionSourceParams, direction="write"
                ),
                "monthly_billing_anchor_date": monthly_billing_anchor_date,
                "phases": convert_and_respect_annotation_metadata(
                    object_=phases, annotation=typing.Sequence[PhaseParams], direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    CreateSubscriptionResponse,
                    construct_type(
                        type_=CreateSubscriptionResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def bulk_swap_plan(
        self,
        *,
        new_plan_variation_id: str,
        old_plan_variation_id: str,
        location_id: str,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[BulkSwapPlanResponse]:
        """
        Schedules a plan variation change for all active subscriptions under a given plan
        variation. For more information, see [Swap Subscription Plan Variations](https://developer.squareup.com/docs/subscriptions-api/swap-plan-variations).

        Parameters
        ----------
        new_plan_variation_id : str
            The ID of the new subscription plan variation.

            This field is required.

        old_plan_variation_id : str
            The ID of the plan variation whose subscriptions should be swapped. Active subscriptions
            using this plan variation will be subscribed to the new plan variation on their next billing
            day.

        location_id : str
            The ID of the location to associate with the swapped subscriptions.

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

        Returns
        -------
        HttpResponse[BulkSwapPlanResponse]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            "v2/subscriptions/bulk-swap-plan",
            method="POST",
            json={
                "new_plan_variation_id": new_plan_variation_id,
                "old_plan_variation_id": old_plan_variation_id,
                "location_id": location_id,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    BulkSwapPlanResponse,
                    construct_type(
                        type_=BulkSwapPlanResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def search(
        self,
        *,
        cursor: typing.Optional[str] = OMIT,
        limit: typing.Optional[int] = OMIT,
        query: typing.Optional[SearchSubscriptionsQueryParams] = OMIT,
        include: typing.Optional[typing.Sequence[str]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[SearchSubscriptionsResponse]:
        """
        Searches for subscriptions.

        Results are ordered chronologically by subscription creation date. If
        the request specifies more than one location ID,
        the endpoint orders the result
        by location ID, and then by creation date within each location. If no locations are given
        in the query, all locations are searched.

        You can also optionally specify `customer_ids` to search by customer.
        If left unset, all customers
        associated with the specified locations are returned.
        If the request specifies customer IDs, the endpoint orders results
        first by location, within location by customer ID, and within
        customer by subscription creation date.

        Parameters
        ----------
        cursor : typing.Optional[str]
            When the total number of resulting subscriptions exceeds the limit of a paged response,
            specify the cursor returned from a preceding response here to fetch the next set of results.
            If the cursor is unset, the response contains the last page of the results.

            For more information, see [Pagination](https://developer.squareup.com/docs/build-basics/common-api-patterns/pagination).

        limit : typing.Optional[int]
            The upper limit on the number of subscriptions to return
            in a paged response.

        query : typing.Optional[SearchSubscriptionsQueryParams]
            A subscription query consisting of specified filtering conditions.

            If this `query` field is unspecified, the `SearchSubscriptions` call will return all subscriptions.

        include : typing.Optional[typing.Sequence[str]]
            An option to include related information in the response.

            The supported values are:

            - `actions`: to include scheduled actions on the targeted subscriptions.

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

        Returns
        -------
        HttpResponse[SearchSubscriptionsResponse]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            "v2/subscriptions/search",
            method="POST",
            json={
                "cursor": cursor,
                "limit": limit,
                "query": convert_and_respect_annotation_metadata(
                    object_=query, annotation=SearchSubscriptionsQueryParams, direction="write"
                ),
                "include": include,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    SearchSubscriptionsResponse,
                    construct_type(
                        type_=SearchSubscriptionsResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def get(
        self,
        subscription_id: str,
        *,
        include: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[GetSubscriptionResponse]:
        """
        Retrieves a specific subscription.

        Parameters
        ----------
        subscription_id : str
            The ID of the subscription to retrieve.

        include : typing.Optional[str]
            A query parameter to specify related information to be included in the response.

            The supported query parameter values are:

            - `actions`: to include scheduled actions on the targeted subscription.

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

        Returns
        -------
        HttpResponse[GetSubscriptionResponse]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/subscriptions/{jsonable_encoder(subscription_id)}",
            method="GET",
            params={
                "include": include,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    GetSubscriptionResponse,
                    construct_type(
                        type_=GetSubscriptionResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def update(
        self,
        subscription_id: str,
        *,
        subscription: typing.Optional[SubscriptionParams] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[UpdateSubscriptionResponse]:
        """
        Updates a subscription by modifying or clearing `subscription` field values.
        To clear a field, set its value to `null`.

        Parameters
        ----------
        subscription_id : str
            The ID of the subscription to update.

        subscription : typing.Optional[SubscriptionParams]
            The subscription object containing the current version, and fields to update.
            Unset fields will be left at their current server values, and JSON `null` values will
            be treated as a request to clear the relevant data.

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

        Returns
        -------
        HttpResponse[UpdateSubscriptionResponse]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/subscriptions/{jsonable_encoder(subscription_id)}",
            method="PUT",
            json={
                "subscription": convert_and_respect_annotation_metadata(
                    object_=subscription, annotation=SubscriptionParams, direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    UpdateSubscriptionResponse,
                    construct_type(
                        type_=UpdateSubscriptionResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def delete_action(
        self, subscription_id: str, action_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[DeleteSubscriptionActionResponse]:
        """
        Deletes a scheduled action for a subscription.

        Parameters
        ----------
        subscription_id : str
            The ID of the subscription the targeted action is to act upon.

        action_id : str
            The ID of the targeted action to be deleted.

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

        Returns
        -------
        HttpResponse[DeleteSubscriptionActionResponse]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/subscriptions/{jsonable_encoder(subscription_id)}/actions/{jsonable_encoder(action_id)}",
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    DeleteSubscriptionActionResponse,
                    construct_type(
                        type_=DeleteSubscriptionActionResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def change_billing_anchor_date(
        self,
        subscription_id: str,
        *,
        monthly_billing_anchor_date: typing.Optional[int] = OMIT,
        effective_date: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[ChangeBillingAnchorDateResponse]:
        """
        Changes the [billing anchor date](https://developer.squareup.com/docs/subscriptions-api/subscription-billing#billing-dates)
        for a subscription.

        Parameters
        ----------
        subscription_id : str
            The ID of the subscription to update the billing anchor date.

        monthly_billing_anchor_date : typing.Optional[int]
            The anchor day for the billing cycle.

        effective_date : typing.Optional[str]
            The `YYYY-MM-DD`-formatted date when the scheduled `BILLING_ANCHOR_CHANGE` action takes
            place on the subscription.

            When this date is unspecified or falls within the current billing cycle, the billing anchor date
            is changed immediately.

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

        Returns
        -------
        HttpResponse[ChangeBillingAnchorDateResponse]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/subscriptions/{jsonable_encoder(subscription_id)}/billing-anchor",
            method="POST",
            json={
                "monthly_billing_anchor_date": monthly_billing_anchor_date,
                "effective_date": effective_date,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    ChangeBillingAnchorDateResponse,
                    construct_type(
                        type_=ChangeBillingAnchorDateResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def cancel(
        self, subscription_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[CancelSubscriptionResponse]:
        """
        Schedules a `CANCEL` action to cancel an active subscription. This
        sets the `canceled_date` field to the end of the active billing period. After this date,
        the subscription status changes from ACTIVE to CANCELED.

        Parameters
        ----------
        subscription_id : str
            The ID of the subscription to cancel.

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

        Returns
        -------
        HttpResponse[CancelSubscriptionResponse]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/subscriptions/{jsonable_encoder(subscription_id)}/cancel",
            method="POST",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    CancelSubscriptionResponse,
                    construct_type(
                        type_=CancelSubscriptionResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def pause(
        self,
        subscription_id: str,
        *,
        pause_effective_date: typing.Optional[str] = OMIT,
        pause_cycle_duration: typing.Optional[int] = OMIT,
        resume_effective_date: typing.Optional[str] = OMIT,
        resume_change_timing: typing.Optional[ChangeTiming] = OMIT,
        pause_reason: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[PauseSubscriptionResponse]:
        """
        Schedules a `PAUSE` action to pause an active subscription.

        Parameters
        ----------
        subscription_id : str
            The ID of the subscription to pause.

        pause_effective_date : typing.Optional[str]
            The `YYYY-MM-DD`-formatted date when the scheduled `PAUSE` action takes place on the subscription.

            When this date is unspecified or falls within the current billing cycle, the subscription is paused
            on the starting date of the next billing cycle.

        pause_cycle_duration : typing.Optional[int]
            The number of billing cycles the subscription will be paused before it is reactivated.

            When this is set, a `RESUME` action is also scheduled to take place on the subscription at
            the end of the specified pause cycle duration. In this case, neither `resume_effective_date`
            nor `resume_change_timing` may be specified.

        resume_effective_date : typing.Optional[str]
            The date when the subscription is reactivated by a scheduled `RESUME` action.
            This date must be at least one billing cycle ahead of `pause_effective_date`.

        resume_change_timing : typing.Optional[ChangeTiming]
            The timing whether the subscription is reactivated immediately or at the end of the billing cycle, relative to
            `resume_effective_date`.
            See [ChangeTiming](#type-changetiming) for possible values

        pause_reason : typing.Optional[str]
            The user-provided reason to pause the subscription.

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

        Returns
        -------
        HttpResponse[PauseSubscriptionResponse]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/subscriptions/{jsonable_encoder(subscription_id)}/pause",
            method="POST",
            json={
                "pause_effective_date": pause_effective_date,
                "pause_cycle_duration": pause_cycle_duration,
                "resume_effective_date": resume_effective_date,
                "resume_change_timing": resume_change_timing,
                "pause_reason": pause_reason,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    PauseSubscriptionResponse,
                    construct_type(
                        type_=PauseSubscriptionResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def resume(
        self,
        subscription_id: str,
        *,
        resume_effective_date: typing.Optional[str] = OMIT,
        resume_change_timing: typing.Optional[ChangeTiming] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[ResumeSubscriptionResponse]:
        """
        Schedules a `RESUME` action to resume a paused or a deactivated subscription.

        Parameters
        ----------
        subscription_id : str
            The ID of the subscription to resume.

        resume_effective_date : typing.Optional[str]
            The `YYYY-MM-DD`-formatted date when the subscription reactivated.

        resume_change_timing : typing.Optional[ChangeTiming]
            The timing to resume a subscription, relative to the specified
            `resume_effective_date` attribute value.
            See [ChangeTiming](#type-changetiming) for possible values

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

        Returns
        -------
        HttpResponse[ResumeSubscriptionResponse]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/subscriptions/{jsonable_encoder(subscription_id)}/resume",
            method="POST",
            json={
                "resume_effective_date": resume_effective_date,
                "resume_change_timing": resume_change_timing,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    ResumeSubscriptionResponse,
                    construct_type(
                        type_=ResumeSubscriptionResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def swap_plan(
        self,
        subscription_id: str,
        *,
        new_plan_variation_id: typing.Optional[str] = OMIT,
        phases: typing.Optional[typing.Sequence[PhaseInputParams]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[SwapPlanResponse]:
        """
        Schedules a `SWAP_PLAN` action to swap a subscription plan variation in an existing subscription.
        For more information, see [Swap Subscription Plan Variations](https://developer.squareup.com/docs/subscriptions-api/swap-plan-variations).

        Parameters
        ----------
        subscription_id : str
            The ID of the subscription to swap the subscription plan for.

        new_plan_variation_id : typing.Optional[str]
            The ID of the new subscription plan variation.

            This field is required.

        phases : typing.Optional[typing.Sequence[PhaseInputParams]]
            A list of PhaseInputs, to pass phase-specific information used in the swap.

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

        Returns
        -------
        HttpResponse[SwapPlanResponse]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/subscriptions/{jsonable_encoder(subscription_id)}/swap-plan",
            method="POST",
            json={
                "new_plan_variation_id": new_plan_variation_id,
                "phases": convert_and_respect_annotation_metadata(
                    object_=phases, annotation=typing.Optional[typing.Sequence[PhaseInputParams]], direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    SwapPlanResponse,
                    construct_type(
                        type_=SwapPlanResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)


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

    async def create(
        self,
        *,
        location_id: str,
        customer_id: str,
        idempotency_key: typing.Optional[str] = OMIT,
        plan_variation_id: typing.Optional[str] = OMIT,
        start_date: typing.Optional[str] = OMIT,
        canceled_date: typing.Optional[str] = OMIT,
        tax_percentage: typing.Optional[str] = OMIT,
        price_override_money: typing.Optional[MoneyParams] = OMIT,
        card_id: typing.Optional[str] = OMIT,
        timezone: typing.Optional[str] = OMIT,
        source: typing.Optional[SubscriptionSourceParams] = OMIT,
        monthly_billing_anchor_date: typing.Optional[int] = OMIT,
        phases: typing.Optional[typing.Sequence[PhaseParams]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[CreateSubscriptionResponse]:
        """
        Enrolls a customer in a subscription.

        If you provide a card on file in the request, Square charges the card for
        the subscription. Otherwise, Square sends an invoice to the customer's email
        address. The subscription starts immediately, unless the request includes
        the optional `start_date`. Each individual subscription is associated with a particular location.

        For more information, see [Create a subscription](https://developer.squareup.com/docs/subscriptions-api/manage-subscriptions#create-a-subscription).

        Parameters
        ----------
        location_id : str
            The ID of the location the subscription is associated with.

        customer_id : str
            The ID of the [customer](entity:Customer) subscribing to the subscription plan variation.

        idempotency_key : typing.Optional[str]
            A unique string that identifies this `CreateSubscription` request.
            If you do not provide a unique string (or provide an empty string as the value),
            the endpoint treats each request as independent.

            For more information, see [Idempotency keys](https://developer.squareup.com/docs/build-basics/common-api-patterns/idempotency).

        plan_variation_id : typing.Optional[str]
            The ID of the [subscription plan variation](https://developer.squareup.com/docs/subscriptions-api/plans-and-variations#plan-variations) created using the Catalog API.

        start_date : typing.Optional[str]
            The `YYYY-MM-DD`-formatted date to start the subscription.
            If it is unspecified, the subscription starts immediately.

        canceled_date : typing.Optional[str]
            The `YYYY-MM-DD`-formatted date when the newly created subscription is scheduled for cancellation.

            This date overrides the cancellation date set in the plan variation configuration.
            If the cancellation date is earlier than the end date of a subscription cycle, the subscription stops
            at the canceled date and the subscriber is sent a prorated invoice at the beginning of the canceled cycle.

            When the subscription plan of the newly created subscription has a fixed number of cycles and the `canceled_date`
            occurs before the subscription plan expires, the specified `canceled_date` sets the date when the subscription
            stops through the end of the last cycle.

        tax_percentage : typing.Optional[str]
            The tax to add when billing the subscription.
            The percentage is expressed in decimal form, using a `'.'` as the decimal
            separator and without a `'%'` sign. For example, a value of 7.5
            corresponds to 7.5%.

        price_override_money : typing.Optional[MoneyParams]
            A custom price which overrides the cost of a subscription plan variation with `STATIC` pricing.
            This field does not affect itemized subscriptions with `RELATIVE` pricing. Instead,
            you should edit the Subscription's [order template](https://developer.squareup.com/docs/subscriptions-api/manage-subscriptions#phases-and-order-templates).

        card_id : typing.Optional[str]
            The ID of the [subscriber's](entity:Customer) [card](entity:Card) to charge.
            If it is not specified, the subscriber receives an invoice via email with a link to pay for their subscription.

        timezone : typing.Optional[str]
            The timezone that is used in date calculations for the subscription. If unset, defaults to
            the location timezone. If a timezone is not configured for the location, defaults to "America/New_York".
            Format: the IANA Timezone Database identifier for the location timezone. For
            a list of time zones, see [List of tz database time zones](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).

        source : typing.Optional[SubscriptionSourceParams]
            The origination details of the subscription.

        monthly_billing_anchor_date : typing.Optional[int]
            The day-of-the-month to change the billing date to.

        phases : typing.Optional[typing.Sequence[PhaseParams]]
            array of phases for this subscription

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

        Returns
        -------
        AsyncHttpResponse[CreateSubscriptionResponse]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v2/subscriptions",
            method="POST",
            json={
                "idempotency_key": idempotency_key,
                "location_id": location_id,
                "plan_variation_id": plan_variation_id,
                "customer_id": customer_id,
                "start_date": start_date,
                "canceled_date": canceled_date,
                "tax_percentage": tax_percentage,
                "price_override_money": convert_and_respect_annotation_metadata(
                    object_=price_override_money, annotation=MoneyParams, direction="write"
                ),
                "card_id": card_id,
                "timezone": timezone,
                "source": convert_and_respect_annotation_metadata(
                    object_=source, annotation=SubscriptionSourceParams, direction="write"
                ),
                "monthly_billing_anchor_date": monthly_billing_anchor_date,
                "phases": convert_and_respect_annotation_metadata(
                    object_=phases, annotation=typing.Sequence[PhaseParams], direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    CreateSubscriptionResponse,
                    construct_type(
                        type_=CreateSubscriptionResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def bulk_swap_plan(
        self,
        *,
        new_plan_variation_id: str,
        old_plan_variation_id: str,
        location_id: str,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[BulkSwapPlanResponse]:
        """
        Schedules a plan variation change for all active subscriptions under a given plan
        variation. For more information, see [Swap Subscription Plan Variations](https://developer.squareup.com/docs/subscriptions-api/swap-plan-variations).

        Parameters
        ----------
        new_plan_variation_id : str
            The ID of the new subscription plan variation.

            This field is required.

        old_plan_variation_id : str
            The ID of the plan variation whose subscriptions should be swapped. Active subscriptions
            using this plan variation will be subscribed to the new plan variation on their next billing
            day.

        location_id : str
            The ID of the location to associate with the swapped subscriptions.

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

        Returns
        -------
        AsyncHttpResponse[BulkSwapPlanResponse]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v2/subscriptions/bulk-swap-plan",
            method="POST",
            json={
                "new_plan_variation_id": new_plan_variation_id,
                "old_plan_variation_id": old_plan_variation_id,
                "location_id": location_id,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    BulkSwapPlanResponse,
                    construct_type(
                        type_=BulkSwapPlanResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def search(
        self,
        *,
        cursor: typing.Optional[str] = OMIT,
        limit: typing.Optional[int] = OMIT,
        query: typing.Optional[SearchSubscriptionsQueryParams] = OMIT,
        include: typing.Optional[typing.Sequence[str]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[SearchSubscriptionsResponse]:
        """
        Searches for subscriptions.

        Results are ordered chronologically by subscription creation date. If
        the request specifies more than one location ID,
        the endpoint orders the result
        by location ID, and then by creation date within each location. If no locations are given
        in the query, all locations are searched.

        You can also optionally specify `customer_ids` to search by customer.
        If left unset, all customers
        associated with the specified locations are returned.
        If the request specifies customer IDs, the endpoint orders results
        first by location, within location by customer ID, and within
        customer by subscription creation date.

        Parameters
        ----------
        cursor : typing.Optional[str]
            When the total number of resulting subscriptions exceeds the limit of a paged response,
            specify the cursor returned from a preceding response here to fetch the next set of results.
            If the cursor is unset, the response contains the last page of the results.

            For more information, see [Pagination](https://developer.squareup.com/docs/build-basics/common-api-patterns/pagination).

        limit : typing.Optional[int]
            The upper limit on the number of subscriptions to return
            in a paged response.

        query : typing.Optional[SearchSubscriptionsQueryParams]
            A subscription query consisting of specified filtering conditions.

            If this `query` field is unspecified, the `SearchSubscriptions` call will return all subscriptions.

        include : typing.Optional[typing.Sequence[str]]
            An option to include related information in the response.

            The supported values are:

            - `actions`: to include scheduled actions on the targeted subscriptions.

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

        Returns
        -------
        AsyncHttpResponse[SearchSubscriptionsResponse]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v2/subscriptions/search",
            method="POST",
            json={
                "cursor": cursor,
                "limit": limit,
                "query": convert_and_respect_annotation_metadata(
                    object_=query, annotation=SearchSubscriptionsQueryParams, direction="write"
                ),
                "include": include,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    SearchSubscriptionsResponse,
                    construct_type(
                        type_=SearchSubscriptionsResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def get(
        self,
        subscription_id: str,
        *,
        include: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[GetSubscriptionResponse]:
        """
        Retrieves a specific subscription.

        Parameters
        ----------
        subscription_id : str
            The ID of the subscription to retrieve.

        include : typing.Optional[str]
            A query parameter to specify related information to be included in the response.

            The supported query parameter values are:

            - `actions`: to include scheduled actions on the targeted subscription.

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

        Returns
        -------
        AsyncHttpResponse[GetSubscriptionResponse]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/subscriptions/{jsonable_encoder(subscription_id)}",
            method="GET",
            params={
                "include": include,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    GetSubscriptionResponse,
                    construct_type(
                        type_=GetSubscriptionResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def update(
        self,
        subscription_id: str,
        *,
        subscription: typing.Optional[SubscriptionParams] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[UpdateSubscriptionResponse]:
        """
        Updates a subscription by modifying or clearing `subscription` field values.
        To clear a field, set its value to `null`.

        Parameters
        ----------
        subscription_id : str
            The ID of the subscription to update.

        subscription : typing.Optional[SubscriptionParams]
            The subscription object containing the current version, and fields to update.
            Unset fields will be left at their current server values, and JSON `null` values will
            be treated as a request to clear the relevant data.

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

        Returns
        -------
        AsyncHttpResponse[UpdateSubscriptionResponse]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/subscriptions/{jsonable_encoder(subscription_id)}",
            method="PUT",
            json={
                "subscription": convert_and_respect_annotation_metadata(
                    object_=subscription, annotation=SubscriptionParams, direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    UpdateSubscriptionResponse,
                    construct_type(
                        type_=UpdateSubscriptionResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def delete_action(
        self, subscription_id: str, action_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[DeleteSubscriptionActionResponse]:
        """
        Deletes a scheduled action for a subscription.

        Parameters
        ----------
        subscription_id : str
            The ID of the subscription the targeted action is to act upon.

        action_id : str
            The ID of the targeted action to be deleted.

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

        Returns
        -------
        AsyncHttpResponse[DeleteSubscriptionActionResponse]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/subscriptions/{jsonable_encoder(subscription_id)}/actions/{jsonable_encoder(action_id)}",
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    DeleteSubscriptionActionResponse,
                    construct_type(
                        type_=DeleteSubscriptionActionResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def change_billing_anchor_date(
        self,
        subscription_id: str,
        *,
        monthly_billing_anchor_date: typing.Optional[int] = OMIT,
        effective_date: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[ChangeBillingAnchorDateResponse]:
        """
        Changes the [billing anchor date](https://developer.squareup.com/docs/subscriptions-api/subscription-billing#billing-dates)
        for a subscription.

        Parameters
        ----------
        subscription_id : str
            The ID of the subscription to update the billing anchor date.

        monthly_billing_anchor_date : typing.Optional[int]
            The anchor day for the billing cycle.

        effective_date : typing.Optional[str]
            The `YYYY-MM-DD`-formatted date when the scheduled `BILLING_ANCHOR_CHANGE` action takes
            place on the subscription.

            When this date is unspecified or falls within the current billing cycle, the billing anchor date
            is changed immediately.

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

        Returns
        -------
        AsyncHttpResponse[ChangeBillingAnchorDateResponse]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/subscriptions/{jsonable_encoder(subscription_id)}/billing-anchor",
            method="POST",
            json={
                "monthly_billing_anchor_date": monthly_billing_anchor_date,
                "effective_date": effective_date,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    ChangeBillingAnchorDateResponse,
                    construct_type(
                        type_=ChangeBillingAnchorDateResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def cancel(
        self, subscription_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[CancelSubscriptionResponse]:
        """
        Schedules a `CANCEL` action to cancel an active subscription. This
        sets the `canceled_date` field to the end of the active billing period. After this date,
        the subscription status changes from ACTIVE to CANCELED.

        Parameters
        ----------
        subscription_id : str
            The ID of the subscription to cancel.

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

        Returns
        -------
        AsyncHttpResponse[CancelSubscriptionResponse]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/subscriptions/{jsonable_encoder(subscription_id)}/cancel",
            method="POST",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    CancelSubscriptionResponse,
                    construct_type(
                        type_=CancelSubscriptionResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def pause(
        self,
        subscription_id: str,
        *,
        pause_effective_date: typing.Optional[str] = OMIT,
        pause_cycle_duration: typing.Optional[int] = OMIT,
        resume_effective_date: typing.Optional[str] = OMIT,
        resume_change_timing: typing.Optional[ChangeTiming] = OMIT,
        pause_reason: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[PauseSubscriptionResponse]:
        """
        Schedules a `PAUSE` action to pause an active subscription.

        Parameters
        ----------
        subscription_id : str
            The ID of the subscription to pause.

        pause_effective_date : typing.Optional[str]
            The `YYYY-MM-DD`-formatted date when the scheduled `PAUSE` action takes place on the subscription.

            When this date is unspecified or falls within the current billing cycle, the subscription is paused
            on the starting date of the next billing cycle.

        pause_cycle_duration : typing.Optional[int]
            The number of billing cycles the subscription will be paused before it is reactivated.

            When this is set, a `RESUME` action is also scheduled to take place on the subscription at
            the end of the specified pause cycle duration. In this case, neither `resume_effective_date`
            nor `resume_change_timing` may be specified.

        resume_effective_date : typing.Optional[str]
            The date when the subscription is reactivated by a scheduled `RESUME` action.
            This date must be at least one billing cycle ahead of `pause_effective_date`.

        resume_change_timing : typing.Optional[ChangeTiming]
            The timing whether the subscription is reactivated immediately or at the end of the billing cycle, relative to
            `resume_effective_date`.
            See [ChangeTiming](#type-changetiming) for possible values

        pause_reason : typing.Optional[str]
            The user-provided reason to pause the subscription.

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

        Returns
        -------
        AsyncHttpResponse[PauseSubscriptionResponse]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/subscriptions/{jsonable_encoder(subscription_id)}/pause",
            method="POST",
            json={
                "pause_effective_date": pause_effective_date,
                "pause_cycle_duration": pause_cycle_duration,
                "resume_effective_date": resume_effective_date,
                "resume_change_timing": resume_change_timing,
                "pause_reason": pause_reason,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    PauseSubscriptionResponse,
                    construct_type(
                        type_=PauseSubscriptionResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def resume(
        self,
        subscription_id: str,
        *,
        resume_effective_date: typing.Optional[str] = OMIT,
        resume_change_timing: typing.Optional[ChangeTiming] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[ResumeSubscriptionResponse]:
        """
        Schedules a `RESUME` action to resume a paused or a deactivated subscription.

        Parameters
        ----------
        subscription_id : str
            The ID of the subscription to resume.

        resume_effective_date : typing.Optional[str]
            The `YYYY-MM-DD`-formatted date when the subscription reactivated.

        resume_change_timing : typing.Optional[ChangeTiming]
            The timing to resume a subscription, relative to the specified
            `resume_effective_date` attribute value.
            See [ChangeTiming](#type-changetiming) for possible values

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

        Returns
        -------
        AsyncHttpResponse[ResumeSubscriptionResponse]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/subscriptions/{jsonable_encoder(subscription_id)}/resume",
            method="POST",
            json={
                "resume_effective_date": resume_effective_date,
                "resume_change_timing": resume_change_timing,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    ResumeSubscriptionResponse,
                    construct_type(
                        type_=ResumeSubscriptionResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def swap_plan(
        self,
        subscription_id: str,
        *,
        new_plan_variation_id: typing.Optional[str] = OMIT,
        phases: typing.Optional[typing.Sequence[PhaseInputParams]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[SwapPlanResponse]:
        """
        Schedules a `SWAP_PLAN` action to swap a subscription plan variation in an existing subscription.
        For more information, see [Swap Subscription Plan Variations](https://developer.squareup.com/docs/subscriptions-api/swap-plan-variations).

        Parameters
        ----------
        subscription_id : str
            The ID of the subscription to swap the subscription plan for.

        new_plan_variation_id : typing.Optional[str]
            The ID of the new subscription plan variation.

            This field is required.

        phases : typing.Optional[typing.Sequence[PhaseInputParams]]
            A list of PhaseInputs, to pass phase-specific information used in the swap.

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

        Returns
        -------
        AsyncHttpResponse[SwapPlanResponse]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/subscriptions/{jsonable_encoder(subscription_id)}/swap-plan",
            method="POST",
            json={
                "new_plan_variation_id": new_plan_variation_id,
                "phases": convert_and_respect_annotation_metadata(
                    object_=phases, annotation=typing.Optional[typing.Sequence[PhaseInputParams]], direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    SwapPlanResponse,
                    construct_type(
                        type_=SwapPlanResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)
