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

import typing
from json.decoder import JSONDecodeError

from ..core.api_error import ApiError
from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from ..core.http_response import AsyncHttpResponse, HttpResponse
from ..core.jsonable_encoder import jsonable_encoder
from ..core.pydantic_utilities import parse_obj_as
from ..core.request_options import RequestOptions
from ..core.serialization import convert_and_respect_annotation_metadata
from ..errors.bad_request_error import BadRequestError
from ..errors.internal_server_error import InternalServerError
from ..errors.service_unavailable_error import ServiceUnavailableError
from ..errors.unauthorized_error import UnauthorizedError
from ..types.accountid import Accountid
from ..types.ach_validation import AchValidation
from ..types.bill_data import BillData
from ..types.entrypointfield import Entrypointfield
from ..types.force_customer_creation import ForceCustomerCreation
from ..types.idempotency_key import IdempotencyKey
from ..types.ip_address import IpAddress
from ..types.order_id import OrderId
from ..types.orderdescription import Orderdescription
from ..types.payabli_api_response import PayabliApiResponse
from ..types.payabli_api_response_0 import PayabliApiResponse0
from ..types.payment_detail import PaymentDetail
from ..types.payment_detail_credit import PaymentDetailCredit
from ..types.payment_method import PaymentMethod
from ..types.payor_data_request import PayorDataRequest
from ..types.refund_detail import RefundDetail
from ..types.source import Source
from ..types.subdomain import Subdomain
from ..types.subscriptionid import Subscriptionid
from ..types.transaction_query_records import TransactionQueryRecords
from .types.auth_response import AuthResponse
from .types.capture_payment_details import CapturePaymentDetails
from .types.capture_response import CaptureResponse
from .types.payabli_api_response_get_paid import PayabliApiResponseGetPaid
from .types.receipt_response import ReceiptResponse
from .types.refund_response import RefundResponse
from .types.refund_with_instructions_response import RefundWithInstructionsResponse
from .types.request_credit_payment_method import RequestCreditPaymentMethod
from .types.request_payment_validate_payment_method import RequestPaymentValidatePaymentMethod
from .types.reverse_response import ReverseResponse
from .types.validate_response import ValidateResponse
from .types.void_response import VoidResponse

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


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

    def authorize(
        self,
        *,
        payment_details: PaymentDetail,
        payment_method: PaymentMethod,
        force_customer_creation: typing.Optional[ForceCustomerCreation] = None,
        idempotency_key: typing.Optional[IdempotencyKey] = None,
        account_id: typing.Optional[Accountid] = OMIT,
        customer_data: typing.Optional[PayorDataRequest] = OMIT,
        entry_point: typing.Optional[Entrypointfield] = OMIT,
        invoice_data: typing.Optional[BillData] = OMIT,
        ipaddress: typing.Optional[IpAddress] = OMIT,
        order_description: typing.Optional[Orderdescription] = OMIT,
        order_id: typing.Optional[OrderId] = OMIT,
        source: typing.Optional[Source] = OMIT,
        subdomain: typing.Optional[Subdomain] = OMIT,
        subscription_id: typing.Optional[Subscriptionid] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[AuthResponse]:
        """
        Authorize a card transaction. This returns an authorization code and reserves funds for the merchant. Authorized transactions aren't flagged for settlement until [captured](/api-reference/moneyin/capture-an-authorized-transaction).

        **Note**: Only card transactions can be authorized. This endpoint can't be used for ACH transactions.

        Parameters
        ----------
        payment_details : PaymentDetail
            Object describing details of the payment. Required.

        payment_method : PaymentMethod
            Information about the payment method for the transaction. Required and recommended fields for each payment method type are described in each schema below.

        force_customer_creation : typing.Optional[ForceCustomerCreation]

        idempotency_key : typing.Optional[IdempotencyKey]

        account_id : typing.Optional[Accountid]

        customer_data : typing.Optional[PayorDataRequest]
            Object describing the Customer/Payor. Which fields are required depends on the paypoint's custom identifier settings.

        entry_point : typing.Optional[Entrypointfield]

        invoice_data : typing.Optional[BillData]
            Object describing an Invoice linked to the transaction.

        ipaddress : typing.Optional[IpAddress]

        order_description : typing.Optional[Orderdescription]

        order_id : typing.Optional[OrderId]

        source : typing.Optional[Source]

        subdomain : typing.Optional[Subdomain]

        subscription_id : typing.Optional[Subscriptionid]

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

        Returns
        -------
        HttpResponse[AuthResponse]
            Ok
        """
        _response = self._client_wrapper.httpx_client.request(
            "MoneyIn/authorize",
            method="POST",
            params={
                "forceCustomerCreation": force_customer_creation,
            },
            json={
                "accountId": account_id,
                "customerData": convert_and_respect_annotation_metadata(
                    object_=customer_data, annotation=PayorDataRequest, direction="write"
                ),
                "entryPoint": entry_point,
                "invoiceData": convert_and_respect_annotation_metadata(
                    object_=invoice_data, annotation=BillData, direction="write"
                ),
                "ipaddress": ipaddress,
                "orderDescription": order_description,
                "orderId": order_id,
                "paymentDetails": convert_and_respect_annotation_metadata(
                    object_=payment_details, annotation=PaymentDetail, direction="write"
                ),
                "paymentMethod": convert_and_respect_annotation_metadata(
                    object_=payment_method, annotation=PaymentMethod, direction="write"
                ),
                "source": source,
                "subdomain": subdomain,
                "subscriptionId": subscription_id,
            },
            headers={
                "content-type": "application/json",
                "idempotencyKey": str(idempotency_key) if idempotency_key is not None else None,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    AuthResponse,
                    parse_obj_as(
                        type_=AuthResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 503:
                raise ServiceUnavailableError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        PayabliApiResponse,
                        parse_obj_as(
                            type_=PayabliApiResponse,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def capture(
        self, amount: float, trans_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[CaptureResponse]:
        """
        <Warning>
          This endpoint is deprecated and will be sunset on November 24, 2025. Migrate to [POST `/capture/{transId}`](/api-reference/moneyin/capture-an-authorized-transaction)`.
        </Warning>

          Capture an [authorized
        transaction](/api-reference/moneyin/authorize-a-transaction) to complete the transaction and move funds from the customer to merchant account.

        Parameters
        ----------
        amount : float
            Amount to be captured. The amount can't be greater the original total amount of the transaction. `0` captures the total amount authorized in the transaction. Partial captures aren't supported.

        trans_id : str
            ReferenceId for the transaction (PaymentId).

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

        Returns
        -------
        HttpResponse[CaptureResponse]
            Ok
        """
        _response = self._client_wrapper.httpx_client.request(
            f"MoneyIn/capture/{jsonable_encoder(trans_id)}/{jsonable_encoder(amount)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    CaptureResponse,
                    parse_obj_as(
                        type_=CaptureResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 503:
                raise ServiceUnavailableError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        PayabliApiResponse,
                        parse_obj_as(
                            type_=PayabliApiResponse,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def capture_auth(
        self,
        trans_id: str,
        *,
        payment_details: CapturePaymentDetails,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[CaptureResponse]:
        """
        Capture an [authorized transaction](/api-reference/moneyin/authorize-a-transaction) to complete the transaction and move funds from the customer to merchant account.

        You can use this endpoint to capture both full and partial amounts of the original authorized transaction. See [Capture an authorized transaction](/developers/developer-guides/pay-in-auth-and-capture) for more information about this endpoint.

        Parameters
        ----------
        trans_id : str
            ReferenceId for the transaction (PaymentId).

        payment_details : CapturePaymentDetails

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

        Returns
        -------
        HttpResponse[CaptureResponse]
            Ok
        """
        _response = self._client_wrapper.httpx_client.request(
            f"MoneyIn/capture/{jsonable_encoder(trans_id)}",
            method="POST",
            json={
                "paymentDetails": convert_and_respect_annotation_metadata(
                    object_=payment_details, annotation=CapturePaymentDetails, direction="write"
                ),
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    CaptureResponse,
                    parse_obj_as(
                        type_=CaptureResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 503:
                raise ServiceUnavailableError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        PayabliApiResponse,
                        parse_obj_as(
                            type_=PayabliApiResponse,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def credit(
        self,
        *,
        customer_data: PayorDataRequest,
        payment_details: PaymentDetailCredit,
        payment_method: RequestCreditPaymentMethod,
        force_customer_creation: typing.Optional[ForceCustomerCreation] = None,
        idempotency_key: typing.Optional[IdempotencyKey] = None,
        account_id: typing.Optional[Accountid] = OMIT,
        entrypoint: typing.Optional[Entrypointfield] = OMIT,
        order_description: typing.Optional[Orderdescription] = OMIT,
        order_id: typing.Optional[OrderId] = OMIT,
        source: typing.Optional[Source] = OMIT,
        subdomain: typing.Optional[Subdomain] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[PayabliApiResponse0]:
        """
        Make a temporary microdeposit in a customer account to verify the customer's ownership and access to the target account. Reverse the microdeposit with `reverseCredit`.

        This feature must be enabled by Payabli on a per-merchant basis. Contact support for help.

        Parameters
        ----------
        customer_data : PayorDataRequest
            Object describing the customer/payor.

        payment_details : PaymentDetailCredit

        payment_method : RequestCreditPaymentMethod
            Object describing the ACH payment method to use for transaction.

        force_customer_creation : typing.Optional[ForceCustomerCreation]

        idempotency_key : typing.Optional[IdempotencyKey]

        account_id : typing.Optional[Accountid]

        entrypoint : typing.Optional[Entrypointfield]

        order_description : typing.Optional[Orderdescription]

        order_id : typing.Optional[OrderId]

        source : typing.Optional[Source]

        subdomain : typing.Optional[Subdomain]

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

        Returns
        -------
        HttpResponse[PayabliApiResponse0]
            Success. The `referenceId` returned in a successful response is the `transId` value you need to reverse the microdeposit.

            A "Missing Gateway Data" message can indicate that the entrypoint targeted in the request isn't set up for ACH payments.
        """
        _response = self._client_wrapper.httpx_client.request(
            "MoneyIn/makecredit",
            method="POST",
            params={
                "forceCustomerCreation": force_customer_creation,
            },
            json={
                "accountId": account_id,
                "customerData": convert_and_respect_annotation_metadata(
                    object_=customer_data, annotation=PayorDataRequest, direction="write"
                ),
                "entrypoint": entrypoint,
                "orderDescription": order_description,
                "orderId": order_id,
                "paymentDetails": convert_and_respect_annotation_metadata(
                    object_=payment_details, annotation=PaymentDetailCredit, direction="write"
                ),
                "paymentMethod": convert_and_respect_annotation_metadata(
                    object_=payment_method, annotation=RequestCreditPaymentMethod, direction="write"
                ),
                "source": source,
                "subdomain": subdomain,
            },
            headers={
                "content-type": "application/json",
                "idempotencyKey": str(idempotency_key) if idempotency_key is not None else None,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    PayabliApiResponse0,
                    parse_obj_as(
                        type_=PayabliApiResponse0,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 503:
                raise ServiceUnavailableError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        PayabliApiResponse,
                        parse_obj_as(
                            type_=PayabliApiResponse,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def details(
        self, trans_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[TransactionQueryRecords]:
        """
        Retrieve a processed transaction's details.

        Parameters
        ----------
        trans_id : str
            ReferenceId for the transaction (PaymentId).

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

        Returns
        -------
        HttpResponse[TransactionQueryRecords]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            f"MoneyIn/details/{jsonable_encoder(trans_id)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    TransactionQueryRecords,
                    parse_obj_as(
                        type_=TransactionQueryRecords,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 503:
                raise ServiceUnavailableError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        PayabliApiResponse,
                        parse_obj_as(
                            type_=PayabliApiResponse,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def getpaid(
        self,
        *,
        payment_details: PaymentDetail,
        payment_method: PaymentMethod,
        ach_validation: typing.Optional[AchValidation] = None,
        force_customer_creation: typing.Optional[ForceCustomerCreation] = None,
        idempotency_key: typing.Optional[IdempotencyKey] = None,
        validation_code: typing.Optional[str] = None,
        account_id: typing.Optional[Accountid] = OMIT,
        customer_data: typing.Optional[PayorDataRequest] = OMIT,
        entry_point: typing.Optional[Entrypointfield] = OMIT,
        invoice_data: typing.Optional[BillData] = OMIT,
        ipaddress: typing.Optional[IpAddress] = OMIT,
        order_description: typing.Optional[Orderdescription] = OMIT,
        order_id: typing.Optional[OrderId] = OMIT,
        source: typing.Optional[Source] = OMIT,
        subdomain: typing.Optional[Subdomain] = OMIT,
        subscription_id: typing.Optional[Subscriptionid] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[PayabliApiResponseGetPaid]:
        """
        Make a single transaction. This method authorizes and captures a payment in one step.

        Parameters
        ----------
        payment_details : PaymentDetail
            Object describing details of the payment. Required.

        payment_method : PaymentMethod
            Information about the payment method for the transaction. Required and recommended fields for each payment method type are described in each schema below.

        ach_validation : typing.Optional[AchValidation]

        force_customer_creation : typing.Optional[ForceCustomerCreation]

        idempotency_key : typing.Optional[IdempotencyKey]

        validation_code : typing.Optional[str]
            Value obtained from user when an API generated CAPTCHA is used in payment page

        account_id : typing.Optional[Accountid]

        customer_data : typing.Optional[PayorDataRequest]
            Object describing the Customer/Payor. Which fields are required depends on the paypoint's custom identifier settings.

        entry_point : typing.Optional[Entrypointfield]

        invoice_data : typing.Optional[BillData]
            Object describing an Invoice linked to the transaction.

        ipaddress : typing.Optional[IpAddress]

        order_description : typing.Optional[Orderdescription]

        order_id : typing.Optional[OrderId]

        source : typing.Optional[Source]

        subdomain : typing.Optional[Subdomain]

        subscription_id : typing.Optional[Subscriptionid]

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

        Returns
        -------
        HttpResponse[PayabliApiResponseGetPaid]
            Ok
        """
        _response = self._client_wrapper.httpx_client.request(
            "MoneyIn/getpaid",
            method="POST",
            params={
                "achValidation": ach_validation,
                "forceCustomerCreation": force_customer_creation,
            },
            json={
                "accountId": account_id,
                "customerData": convert_and_respect_annotation_metadata(
                    object_=customer_data, annotation=PayorDataRequest, direction="write"
                ),
                "entryPoint": entry_point,
                "invoiceData": convert_and_respect_annotation_metadata(
                    object_=invoice_data, annotation=BillData, direction="write"
                ),
                "ipaddress": ipaddress,
                "orderDescription": order_description,
                "orderId": order_id,
                "paymentDetails": convert_and_respect_annotation_metadata(
                    object_=payment_details, annotation=PaymentDetail, direction="write"
                ),
                "paymentMethod": convert_and_respect_annotation_metadata(
                    object_=payment_method, annotation=PaymentMethod, direction="write"
                ),
                "source": source,
                "subdomain": subdomain,
                "subscriptionId": subscription_id,
            },
            headers={
                "content-type": "application/json",
                "idempotencyKey": str(idempotency_key) if idempotency_key is not None else None,
                "validationCode": str(validation_code) if validation_code is not None else None,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    PayabliApiResponseGetPaid,
                    parse_obj_as(
                        type_=PayabliApiResponseGetPaid,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 503:
                raise ServiceUnavailableError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        PayabliApiResponse,
                        parse_obj_as(
                            type_=PayabliApiResponse,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def reverse(
        self, amount: float, trans_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[ReverseResponse]:
        """
        A reversal either refunds or voids a transaction independent of the transaction's settlement status. Send a reversal request for a transaction, and Payabli automatically determines whether it's a refund or void. You don't need to know whether the transaction is settled or not.

        Parameters
        ----------
        amount : float

            Amount to reverse from original transaction, minus any service fees charged on the original transaction.

            The amount provided can't be greater than the original total amount of the transaction, minus service fees. For example, if a transaction was $90 plus a $10 service fee, you can reverse up to $90.

            An amount equal to zero will refunds the total amount authorized minus any service fee.

        trans_id : str
            ReferenceId for the transaction (PaymentId).

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

        Returns
        -------
        HttpResponse[ReverseResponse]
            Ok
        """
        _response = self._client_wrapper.httpx_client.request(
            f"MoneyIn/reverse/{jsonable_encoder(trans_id)}/{jsonable_encoder(amount)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    ReverseResponse,
                    parse_obj_as(
                        type_=ReverseResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 503:
                raise ServiceUnavailableError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        PayabliApiResponse,
                        parse_obj_as(
                            type_=PayabliApiResponse,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def refund(
        self, amount: float, trans_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[RefundResponse]:
        """
        Refund a transaction that has settled and send money back to the account holder. If a transaction hasn't been settled, void it instead.

        Parameters
        ----------
        amount : float

            Amount to refund from original transaction, minus any service fees charged on the original transaction.

            The amount provided can't be greater than the original total amount of the transaction, minus service fees. For example, if a transaction was $90 plus a $10 service fee, you can refund up to $90.

            An amount equal to zero will refund the total amount authorized minus any service fee.

        trans_id : str
            ReferenceId for the transaction (PaymentId).

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

        Returns
        -------
        HttpResponse[RefundResponse]
            Ok
        """
        _response = self._client_wrapper.httpx_client.request(
            f"MoneyIn/refund/{jsonable_encoder(trans_id)}/{jsonable_encoder(amount)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    RefundResponse,
                    parse_obj_as(
                        type_=RefundResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 503:
                raise ServiceUnavailableError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        PayabliApiResponse,
                        parse_obj_as(
                            type_=PayabliApiResponse,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def refund_with_instructions(
        self,
        trans_id: str,
        *,
        idempotency_key: typing.Optional[IdempotencyKey] = None,
        amount: typing.Optional[float] = OMIT,
        ipaddress: typing.Optional[IpAddress] = OMIT,
        order_description: typing.Optional[Orderdescription] = OMIT,
        order_id: typing.Optional[OrderId] = OMIT,
        refund_details: typing.Optional[RefundDetail] = OMIT,
        source: typing.Optional[Source] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[RefundWithInstructionsResponse]:
        """
        Refunds a settled transaction with split instructions.

        Parameters
        ----------
        trans_id : str
            ReferenceId for the transaction (PaymentId).

        idempotency_key : typing.Optional[IdempotencyKey]

        amount : typing.Optional[float]

            Amount to refund from original transaction, minus any service fees charged on the original transaction.

            The amount provided can't be greater than the original total amount of the transaction, minus service fees. For example, if a transaction was $90 plus a $10 service fee, you can refund up to $90.

            An amount equal to zero will refund the total amount authorized minus any service fee.

        ipaddress : typing.Optional[IpAddress]

        order_description : typing.Optional[Orderdescription]

        order_id : typing.Optional[OrderId]

        refund_details : typing.Optional[RefundDetail]

        source : typing.Optional[Source]

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

        Returns
        -------
        HttpResponse[RefundWithInstructionsResponse]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            f"MoneyIn/refund/{jsonable_encoder(trans_id)}",
            method="POST",
            json={
                "amount": amount,
                "ipaddress": ipaddress,
                "orderDescription": order_description,
                "orderId": order_id,
                "refundDetails": convert_and_respect_annotation_metadata(
                    object_=refund_details, annotation=RefundDetail, direction="write"
                ),
                "source": source,
            },
            headers={
                "content-type": "application/json",
                "idempotencyKey": str(idempotency_key) if idempotency_key is not None else None,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    RefundWithInstructionsResponse,
                    parse_obj_as(
                        type_=RefundWithInstructionsResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 503:
                raise ServiceUnavailableError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        PayabliApiResponse,
                        parse_obj_as(
                            type_=PayabliApiResponse,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def reverse_credit(
        self, trans_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[PayabliApiResponse]:
        """
        Reverse microdeposits that are used to verify customer account ownership and access. The `transId` value is returned in the success response for the original credit transaction made with `api/MoneyIn/makecredit`.

        Parameters
        ----------
        trans_id : str
            ReferenceId for the transaction (PaymentId).

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

        Returns
        -------
        HttpResponse[PayabliApiResponse]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            f"MoneyIn/reverseCredit/{jsonable_encoder(trans_id)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    PayabliApiResponse,
                    parse_obj_as(
                        type_=PayabliApiResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 503:
                raise ServiceUnavailableError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        PayabliApiResponse,
                        parse_obj_as(
                            type_=PayabliApiResponse,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def send_receipt_2_trans(
        self,
        trans_id: str,
        *,
        email: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[ReceiptResponse]:
        """
        Send a payment receipt for a transaction.

        Parameters
        ----------
        trans_id : str
            ReferenceId for the transaction (PaymentId).

        email : typing.Optional[str]
            Email address where the payment receipt should be sent.

            If not provided, the email address on file for the user owner of the transaction is used.

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

        Returns
        -------
        HttpResponse[ReceiptResponse]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            f"MoneyIn/sendreceipt/{jsonable_encoder(trans_id)}",
            method="GET",
            params={
                "email": email,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    ReceiptResponse,
                    parse_obj_as(
                        type_=ReceiptResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 503:
                raise ServiceUnavailableError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        PayabliApiResponse,
                        parse_obj_as(
                            type_=PayabliApiResponse,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def validate(
        self,
        *,
        entry_point: Entrypointfield,
        payment_method: RequestPaymentValidatePaymentMethod,
        idempotency_key: typing.Optional[IdempotencyKey] = None,
        account_id: typing.Optional[Accountid] = OMIT,
        order_description: typing.Optional[Orderdescription] = OMIT,
        order_id: typing.Optional[OrderId] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[ValidateResponse]:
        """
        Validates a card number without running a transaction or authorizing a charge.

        Parameters
        ----------
        entry_point : Entrypointfield

        payment_method : RequestPaymentValidatePaymentMethod
            Object describing payment method to use for transaction.

        idempotency_key : typing.Optional[IdempotencyKey]

        account_id : typing.Optional[Accountid]

        order_description : typing.Optional[Orderdescription]

        order_id : typing.Optional[OrderId]

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

        Returns
        -------
        HttpResponse[ValidateResponse]
            Ok
        """
        _response = self._client_wrapper.httpx_client.request(
            "MoneyIn/validate",
            method="POST",
            json={
                "accountId": account_id,
                "entryPoint": entry_point,
                "orderDescription": order_description,
                "orderId": order_id,
                "paymentMethod": convert_and_respect_annotation_metadata(
                    object_=payment_method, annotation=RequestPaymentValidatePaymentMethod, direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
                "idempotencyKey": str(idempotency_key) if idempotency_key is not None else None,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    ValidateResponse,
                    parse_obj_as(
                        type_=ValidateResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 503:
                raise ServiceUnavailableError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        PayabliApiResponse,
                        parse_obj_as(
                            type_=PayabliApiResponse,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def void(
        self, trans_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[VoidResponse]:
        """
        Cancel a transaction that hasn't been settled yet. Voiding non-captured authorizations prevents future captures. If a transaction has been settled, refund it instead.

        Parameters
        ----------
        trans_id : str
            ReferenceId for the transaction (PaymentId).

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

        Returns
        -------
        HttpResponse[VoidResponse]
            Ok
        """
        _response = self._client_wrapper.httpx_client.request(
            f"MoneyIn/void/{jsonable_encoder(trans_id)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    VoidResponse,
                    parse_obj_as(
                        type_=VoidResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 503:
                raise ServiceUnavailableError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        PayabliApiResponse,
                        parse_obj_as(
                            type_=PayabliApiResponse,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)


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

    async def authorize(
        self,
        *,
        payment_details: PaymentDetail,
        payment_method: PaymentMethod,
        force_customer_creation: typing.Optional[ForceCustomerCreation] = None,
        idempotency_key: typing.Optional[IdempotencyKey] = None,
        account_id: typing.Optional[Accountid] = OMIT,
        customer_data: typing.Optional[PayorDataRequest] = OMIT,
        entry_point: typing.Optional[Entrypointfield] = OMIT,
        invoice_data: typing.Optional[BillData] = OMIT,
        ipaddress: typing.Optional[IpAddress] = OMIT,
        order_description: typing.Optional[Orderdescription] = OMIT,
        order_id: typing.Optional[OrderId] = OMIT,
        source: typing.Optional[Source] = OMIT,
        subdomain: typing.Optional[Subdomain] = OMIT,
        subscription_id: typing.Optional[Subscriptionid] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[AuthResponse]:
        """
        Authorize a card transaction. This returns an authorization code and reserves funds for the merchant. Authorized transactions aren't flagged for settlement until [captured](/api-reference/moneyin/capture-an-authorized-transaction).

        **Note**: Only card transactions can be authorized. This endpoint can't be used for ACH transactions.

        Parameters
        ----------
        payment_details : PaymentDetail
            Object describing details of the payment. Required.

        payment_method : PaymentMethod
            Information about the payment method for the transaction. Required and recommended fields for each payment method type are described in each schema below.

        force_customer_creation : typing.Optional[ForceCustomerCreation]

        idempotency_key : typing.Optional[IdempotencyKey]

        account_id : typing.Optional[Accountid]

        customer_data : typing.Optional[PayorDataRequest]
            Object describing the Customer/Payor. Which fields are required depends on the paypoint's custom identifier settings.

        entry_point : typing.Optional[Entrypointfield]

        invoice_data : typing.Optional[BillData]
            Object describing an Invoice linked to the transaction.

        ipaddress : typing.Optional[IpAddress]

        order_description : typing.Optional[Orderdescription]

        order_id : typing.Optional[OrderId]

        source : typing.Optional[Source]

        subdomain : typing.Optional[Subdomain]

        subscription_id : typing.Optional[Subscriptionid]

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

        Returns
        -------
        AsyncHttpResponse[AuthResponse]
            Ok
        """
        _response = await self._client_wrapper.httpx_client.request(
            "MoneyIn/authorize",
            method="POST",
            params={
                "forceCustomerCreation": force_customer_creation,
            },
            json={
                "accountId": account_id,
                "customerData": convert_and_respect_annotation_metadata(
                    object_=customer_data, annotation=PayorDataRequest, direction="write"
                ),
                "entryPoint": entry_point,
                "invoiceData": convert_and_respect_annotation_metadata(
                    object_=invoice_data, annotation=BillData, direction="write"
                ),
                "ipaddress": ipaddress,
                "orderDescription": order_description,
                "orderId": order_id,
                "paymentDetails": convert_and_respect_annotation_metadata(
                    object_=payment_details, annotation=PaymentDetail, direction="write"
                ),
                "paymentMethod": convert_and_respect_annotation_metadata(
                    object_=payment_method, annotation=PaymentMethod, direction="write"
                ),
                "source": source,
                "subdomain": subdomain,
                "subscriptionId": subscription_id,
            },
            headers={
                "content-type": "application/json",
                "idempotencyKey": str(idempotency_key) if idempotency_key is not None else None,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    AuthResponse,
                    parse_obj_as(
                        type_=AuthResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 503:
                raise ServiceUnavailableError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        PayabliApiResponse,
                        parse_obj_as(
                            type_=PayabliApiResponse,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def capture(
        self, amount: float, trans_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[CaptureResponse]:
        """
        <Warning>
          This endpoint is deprecated and will be sunset on November 24, 2025. Migrate to [POST `/capture/{transId}`](/api-reference/moneyin/capture-an-authorized-transaction)`.
        </Warning>

          Capture an [authorized
        transaction](/api-reference/moneyin/authorize-a-transaction) to complete the transaction and move funds from the customer to merchant account.

        Parameters
        ----------
        amount : float
            Amount to be captured. The amount can't be greater the original total amount of the transaction. `0` captures the total amount authorized in the transaction. Partial captures aren't supported.

        trans_id : str
            ReferenceId for the transaction (PaymentId).

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

        Returns
        -------
        AsyncHttpResponse[CaptureResponse]
            Ok
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"MoneyIn/capture/{jsonable_encoder(trans_id)}/{jsonable_encoder(amount)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    CaptureResponse,
                    parse_obj_as(
                        type_=CaptureResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 503:
                raise ServiceUnavailableError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        PayabliApiResponse,
                        parse_obj_as(
                            type_=PayabliApiResponse,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def capture_auth(
        self,
        trans_id: str,
        *,
        payment_details: CapturePaymentDetails,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[CaptureResponse]:
        """
        Capture an [authorized transaction](/api-reference/moneyin/authorize-a-transaction) to complete the transaction and move funds from the customer to merchant account.

        You can use this endpoint to capture both full and partial amounts of the original authorized transaction. See [Capture an authorized transaction](/developers/developer-guides/pay-in-auth-and-capture) for more information about this endpoint.

        Parameters
        ----------
        trans_id : str
            ReferenceId for the transaction (PaymentId).

        payment_details : CapturePaymentDetails

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

        Returns
        -------
        AsyncHttpResponse[CaptureResponse]
            Ok
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"MoneyIn/capture/{jsonable_encoder(trans_id)}",
            method="POST",
            json={
                "paymentDetails": convert_and_respect_annotation_metadata(
                    object_=payment_details, annotation=CapturePaymentDetails, direction="write"
                ),
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    CaptureResponse,
                    parse_obj_as(
                        type_=CaptureResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 503:
                raise ServiceUnavailableError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        PayabliApiResponse,
                        parse_obj_as(
                            type_=PayabliApiResponse,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def credit(
        self,
        *,
        customer_data: PayorDataRequest,
        payment_details: PaymentDetailCredit,
        payment_method: RequestCreditPaymentMethod,
        force_customer_creation: typing.Optional[ForceCustomerCreation] = None,
        idempotency_key: typing.Optional[IdempotencyKey] = None,
        account_id: typing.Optional[Accountid] = OMIT,
        entrypoint: typing.Optional[Entrypointfield] = OMIT,
        order_description: typing.Optional[Orderdescription] = OMIT,
        order_id: typing.Optional[OrderId] = OMIT,
        source: typing.Optional[Source] = OMIT,
        subdomain: typing.Optional[Subdomain] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[PayabliApiResponse0]:
        """
        Make a temporary microdeposit in a customer account to verify the customer's ownership and access to the target account. Reverse the microdeposit with `reverseCredit`.

        This feature must be enabled by Payabli on a per-merchant basis. Contact support for help.

        Parameters
        ----------
        customer_data : PayorDataRequest
            Object describing the customer/payor.

        payment_details : PaymentDetailCredit

        payment_method : RequestCreditPaymentMethod
            Object describing the ACH payment method to use for transaction.

        force_customer_creation : typing.Optional[ForceCustomerCreation]

        idempotency_key : typing.Optional[IdempotencyKey]

        account_id : typing.Optional[Accountid]

        entrypoint : typing.Optional[Entrypointfield]

        order_description : typing.Optional[Orderdescription]

        order_id : typing.Optional[OrderId]

        source : typing.Optional[Source]

        subdomain : typing.Optional[Subdomain]

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

        Returns
        -------
        AsyncHttpResponse[PayabliApiResponse0]
            Success. The `referenceId` returned in a successful response is the `transId` value you need to reverse the microdeposit.

            A "Missing Gateway Data" message can indicate that the entrypoint targeted in the request isn't set up for ACH payments.
        """
        _response = await self._client_wrapper.httpx_client.request(
            "MoneyIn/makecredit",
            method="POST",
            params={
                "forceCustomerCreation": force_customer_creation,
            },
            json={
                "accountId": account_id,
                "customerData": convert_and_respect_annotation_metadata(
                    object_=customer_data, annotation=PayorDataRequest, direction="write"
                ),
                "entrypoint": entrypoint,
                "orderDescription": order_description,
                "orderId": order_id,
                "paymentDetails": convert_and_respect_annotation_metadata(
                    object_=payment_details, annotation=PaymentDetailCredit, direction="write"
                ),
                "paymentMethod": convert_and_respect_annotation_metadata(
                    object_=payment_method, annotation=RequestCreditPaymentMethod, direction="write"
                ),
                "source": source,
                "subdomain": subdomain,
            },
            headers={
                "content-type": "application/json",
                "idempotencyKey": str(idempotency_key) if idempotency_key is not None else None,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    PayabliApiResponse0,
                    parse_obj_as(
                        type_=PayabliApiResponse0,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 503:
                raise ServiceUnavailableError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        PayabliApiResponse,
                        parse_obj_as(
                            type_=PayabliApiResponse,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def details(
        self, trans_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[TransactionQueryRecords]:
        """
        Retrieve a processed transaction's details.

        Parameters
        ----------
        trans_id : str
            ReferenceId for the transaction (PaymentId).

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

        Returns
        -------
        AsyncHttpResponse[TransactionQueryRecords]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"MoneyIn/details/{jsonable_encoder(trans_id)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    TransactionQueryRecords,
                    parse_obj_as(
                        type_=TransactionQueryRecords,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 503:
                raise ServiceUnavailableError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        PayabliApiResponse,
                        parse_obj_as(
                            type_=PayabliApiResponse,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def getpaid(
        self,
        *,
        payment_details: PaymentDetail,
        payment_method: PaymentMethod,
        ach_validation: typing.Optional[AchValidation] = None,
        force_customer_creation: typing.Optional[ForceCustomerCreation] = None,
        idempotency_key: typing.Optional[IdempotencyKey] = None,
        validation_code: typing.Optional[str] = None,
        account_id: typing.Optional[Accountid] = OMIT,
        customer_data: typing.Optional[PayorDataRequest] = OMIT,
        entry_point: typing.Optional[Entrypointfield] = OMIT,
        invoice_data: typing.Optional[BillData] = OMIT,
        ipaddress: typing.Optional[IpAddress] = OMIT,
        order_description: typing.Optional[Orderdescription] = OMIT,
        order_id: typing.Optional[OrderId] = OMIT,
        source: typing.Optional[Source] = OMIT,
        subdomain: typing.Optional[Subdomain] = OMIT,
        subscription_id: typing.Optional[Subscriptionid] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[PayabliApiResponseGetPaid]:
        """
        Make a single transaction. This method authorizes and captures a payment in one step.

        Parameters
        ----------
        payment_details : PaymentDetail
            Object describing details of the payment. Required.

        payment_method : PaymentMethod
            Information about the payment method for the transaction. Required and recommended fields for each payment method type are described in each schema below.

        ach_validation : typing.Optional[AchValidation]

        force_customer_creation : typing.Optional[ForceCustomerCreation]

        idempotency_key : typing.Optional[IdempotencyKey]

        validation_code : typing.Optional[str]
            Value obtained from user when an API generated CAPTCHA is used in payment page

        account_id : typing.Optional[Accountid]

        customer_data : typing.Optional[PayorDataRequest]
            Object describing the Customer/Payor. Which fields are required depends on the paypoint's custom identifier settings.

        entry_point : typing.Optional[Entrypointfield]

        invoice_data : typing.Optional[BillData]
            Object describing an Invoice linked to the transaction.

        ipaddress : typing.Optional[IpAddress]

        order_description : typing.Optional[Orderdescription]

        order_id : typing.Optional[OrderId]

        source : typing.Optional[Source]

        subdomain : typing.Optional[Subdomain]

        subscription_id : typing.Optional[Subscriptionid]

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

        Returns
        -------
        AsyncHttpResponse[PayabliApiResponseGetPaid]
            Ok
        """
        _response = await self._client_wrapper.httpx_client.request(
            "MoneyIn/getpaid",
            method="POST",
            params={
                "achValidation": ach_validation,
                "forceCustomerCreation": force_customer_creation,
            },
            json={
                "accountId": account_id,
                "customerData": convert_and_respect_annotation_metadata(
                    object_=customer_data, annotation=PayorDataRequest, direction="write"
                ),
                "entryPoint": entry_point,
                "invoiceData": convert_and_respect_annotation_metadata(
                    object_=invoice_data, annotation=BillData, direction="write"
                ),
                "ipaddress": ipaddress,
                "orderDescription": order_description,
                "orderId": order_id,
                "paymentDetails": convert_and_respect_annotation_metadata(
                    object_=payment_details, annotation=PaymentDetail, direction="write"
                ),
                "paymentMethod": convert_and_respect_annotation_metadata(
                    object_=payment_method, annotation=PaymentMethod, direction="write"
                ),
                "source": source,
                "subdomain": subdomain,
                "subscriptionId": subscription_id,
            },
            headers={
                "content-type": "application/json",
                "idempotencyKey": str(idempotency_key) if idempotency_key is not None else None,
                "validationCode": str(validation_code) if validation_code is not None else None,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    PayabliApiResponseGetPaid,
                    parse_obj_as(
                        type_=PayabliApiResponseGetPaid,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 503:
                raise ServiceUnavailableError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        PayabliApiResponse,
                        parse_obj_as(
                            type_=PayabliApiResponse,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def reverse(
        self, amount: float, trans_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[ReverseResponse]:
        """
        A reversal either refunds or voids a transaction independent of the transaction's settlement status. Send a reversal request for a transaction, and Payabli automatically determines whether it's a refund or void. You don't need to know whether the transaction is settled or not.

        Parameters
        ----------
        amount : float

            Amount to reverse from original transaction, minus any service fees charged on the original transaction.

            The amount provided can't be greater than the original total amount of the transaction, minus service fees. For example, if a transaction was $90 plus a $10 service fee, you can reverse up to $90.

            An amount equal to zero will refunds the total amount authorized minus any service fee.

        trans_id : str
            ReferenceId for the transaction (PaymentId).

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

        Returns
        -------
        AsyncHttpResponse[ReverseResponse]
            Ok
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"MoneyIn/reverse/{jsonable_encoder(trans_id)}/{jsonable_encoder(amount)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    ReverseResponse,
                    parse_obj_as(
                        type_=ReverseResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 503:
                raise ServiceUnavailableError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        PayabliApiResponse,
                        parse_obj_as(
                            type_=PayabliApiResponse,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def refund(
        self, amount: float, trans_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[RefundResponse]:
        """
        Refund a transaction that has settled and send money back to the account holder. If a transaction hasn't been settled, void it instead.

        Parameters
        ----------
        amount : float

            Amount to refund from original transaction, minus any service fees charged on the original transaction.

            The amount provided can't be greater than the original total amount of the transaction, minus service fees. For example, if a transaction was $90 plus a $10 service fee, you can refund up to $90.

            An amount equal to zero will refund the total amount authorized minus any service fee.

        trans_id : str
            ReferenceId for the transaction (PaymentId).

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

        Returns
        -------
        AsyncHttpResponse[RefundResponse]
            Ok
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"MoneyIn/refund/{jsonable_encoder(trans_id)}/{jsonable_encoder(amount)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    RefundResponse,
                    parse_obj_as(
                        type_=RefundResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 503:
                raise ServiceUnavailableError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        PayabliApiResponse,
                        parse_obj_as(
                            type_=PayabliApiResponse,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def refund_with_instructions(
        self,
        trans_id: str,
        *,
        idempotency_key: typing.Optional[IdempotencyKey] = None,
        amount: typing.Optional[float] = OMIT,
        ipaddress: typing.Optional[IpAddress] = OMIT,
        order_description: typing.Optional[Orderdescription] = OMIT,
        order_id: typing.Optional[OrderId] = OMIT,
        refund_details: typing.Optional[RefundDetail] = OMIT,
        source: typing.Optional[Source] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[RefundWithInstructionsResponse]:
        """
        Refunds a settled transaction with split instructions.

        Parameters
        ----------
        trans_id : str
            ReferenceId for the transaction (PaymentId).

        idempotency_key : typing.Optional[IdempotencyKey]

        amount : typing.Optional[float]

            Amount to refund from original transaction, minus any service fees charged on the original transaction.

            The amount provided can't be greater than the original total amount of the transaction, minus service fees. For example, if a transaction was $90 plus a $10 service fee, you can refund up to $90.

            An amount equal to zero will refund the total amount authorized minus any service fee.

        ipaddress : typing.Optional[IpAddress]

        order_description : typing.Optional[Orderdescription]

        order_id : typing.Optional[OrderId]

        refund_details : typing.Optional[RefundDetail]

        source : typing.Optional[Source]

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

        Returns
        -------
        AsyncHttpResponse[RefundWithInstructionsResponse]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"MoneyIn/refund/{jsonable_encoder(trans_id)}",
            method="POST",
            json={
                "amount": amount,
                "ipaddress": ipaddress,
                "orderDescription": order_description,
                "orderId": order_id,
                "refundDetails": convert_and_respect_annotation_metadata(
                    object_=refund_details, annotation=RefundDetail, direction="write"
                ),
                "source": source,
            },
            headers={
                "content-type": "application/json",
                "idempotencyKey": str(idempotency_key) if idempotency_key is not None else None,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    RefundWithInstructionsResponse,
                    parse_obj_as(
                        type_=RefundWithInstructionsResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 503:
                raise ServiceUnavailableError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        PayabliApiResponse,
                        parse_obj_as(
                            type_=PayabliApiResponse,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def reverse_credit(
        self, trans_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[PayabliApiResponse]:
        """
        Reverse microdeposits that are used to verify customer account ownership and access. The `transId` value is returned in the success response for the original credit transaction made with `api/MoneyIn/makecredit`.

        Parameters
        ----------
        trans_id : str
            ReferenceId for the transaction (PaymentId).

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

        Returns
        -------
        AsyncHttpResponse[PayabliApiResponse]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"MoneyIn/reverseCredit/{jsonable_encoder(trans_id)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    PayabliApiResponse,
                    parse_obj_as(
                        type_=PayabliApiResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 503:
                raise ServiceUnavailableError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        PayabliApiResponse,
                        parse_obj_as(
                            type_=PayabliApiResponse,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def send_receipt_2_trans(
        self,
        trans_id: str,
        *,
        email: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[ReceiptResponse]:
        """
        Send a payment receipt for a transaction.

        Parameters
        ----------
        trans_id : str
            ReferenceId for the transaction (PaymentId).

        email : typing.Optional[str]
            Email address where the payment receipt should be sent.

            If not provided, the email address on file for the user owner of the transaction is used.

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

        Returns
        -------
        AsyncHttpResponse[ReceiptResponse]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"MoneyIn/sendreceipt/{jsonable_encoder(trans_id)}",
            method="GET",
            params={
                "email": email,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    ReceiptResponse,
                    parse_obj_as(
                        type_=ReceiptResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 503:
                raise ServiceUnavailableError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        PayabliApiResponse,
                        parse_obj_as(
                            type_=PayabliApiResponse,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def validate(
        self,
        *,
        entry_point: Entrypointfield,
        payment_method: RequestPaymentValidatePaymentMethod,
        idempotency_key: typing.Optional[IdempotencyKey] = None,
        account_id: typing.Optional[Accountid] = OMIT,
        order_description: typing.Optional[Orderdescription] = OMIT,
        order_id: typing.Optional[OrderId] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[ValidateResponse]:
        """
        Validates a card number without running a transaction or authorizing a charge.

        Parameters
        ----------
        entry_point : Entrypointfield

        payment_method : RequestPaymentValidatePaymentMethod
            Object describing payment method to use for transaction.

        idempotency_key : typing.Optional[IdempotencyKey]

        account_id : typing.Optional[Accountid]

        order_description : typing.Optional[Orderdescription]

        order_id : typing.Optional[OrderId]

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

        Returns
        -------
        AsyncHttpResponse[ValidateResponse]
            Ok
        """
        _response = await self._client_wrapper.httpx_client.request(
            "MoneyIn/validate",
            method="POST",
            json={
                "accountId": account_id,
                "entryPoint": entry_point,
                "orderDescription": order_description,
                "orderId": order_id,
                "paymentMethod": convert_and_respect_annotation_metadata(
                    object_=payment_method, annotation=RequestPaymentValidatePaymentMethod, direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
                "idempotencyKey": str(idempotency_key) if idempotency_key is not None else None,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    ValidateResponse,
                    parse_obj_as(
                        type_=ValidateResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 503:
                raise ServiceUnavailableError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        PayabliApiResponse,
                        parse_obj_as(
                            type_=PayabliApiResponse,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def void(
        self, trans_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[VoidResponse]:
        """
        Cancel a transaction that hasn't been settled yet. Voiding non-captured authorizations prevents future captures. If a transaction has been settled, refund it instead.

        Parameters
        ----------
        trans_id : str
            ReferenceId for the transaction (PaymentId).

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

        Returns
        -------
        AsyncHttpResponse[VoidResponse]
            Ok
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"MoneyIn/void/{jsonable_encoder(trans_id)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    VoidResponse,
                    parse_obj_as(
                        type_=VoidResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 503:
                raise ServiceUnavailableError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        PayabliApiResponse,
                        parse_obj_as(
                            type_=PayabliApiResponse,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
