"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
# @generated-id: 528cc19ae879

from .basesdk import BaseSDK
from jsonpath import JSONPath
from mollie import models, utils
from mollie._hooks import HookContext
from mollie.types import OptionalNullable, UNSET
from mollie.utils import get_security_from_env
from mollie.utils.unmarshal_json_response import unmarshal_json_response
from typing import Any, Awaitable, Dict, List, Mapping, Optional, Union


class Balances(BaseSDK):
    def list(
        self,
        *,
        currency: OptionalNullable[str] = UNSET,
        from_: OptionalNullable[str] = UNSET,
        limit: OptionalNullable[int] = UNSET,
        testmode: Optional[bool] = None,
        idempotency_key: Optional[str] = None,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        url_override: Optional[str] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> Optional[models.ListBalancesResponse]:
        r"""List balances

        Retrieve a list of the organization's balances, including the primary balance.

        The results are paginated.

        :param currency: Optionally only return balances with the given currency. For example: `EUR`.
        :param from_: Provide an ID to start the result set from the item with the given ID and onwards. This allows you to paginate the
            result set.
        :param limit: The maximum number of items to return. Defaults to 50 items.
        :param testmode: You can enable test mode by setting the `testmode` query parameter to `true`.

            Test entities cannot be retrieved when the endpoint is set to live mode, and vice versa.
        :param idempotency_key: A unique key to ensure idempotent requests. This key should be a UUID v4 string.
        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = models.ListBalancesRequest(
            currency=currency,
            from_=from_,
            limit=limit,
            testmode=testmode,
            idempotency_key=idempotency_key,
        )

        req = self._build_request(
            method="GET",
            path="/balances",
            base_url=base_url,
            url_variables=url_variables,
            url_override=url_override,
            request=request,
            request_body_required=False,
            request_has_path_params=False,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/hal+json",
            http_headers=http_headers,
            _globals=models.ListBalancesGlobals(
                testmode=self.sdk_configuration.globals.testmode,
            ),
            security=self.sdk_configuration.security,
            allow_empty_value=None,
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config
            else:
                retries = utils.RetryConfig(
                    "backoff", utils.BackoffStrategy(500, 5000, 2, 7500), True
                )

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["5xx"])

        http_res = self.do_request(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="list-balances",
                oauth2_scopes=None,
                security_source=get_security_from_env(
                    self.sdk_configuration.security, models.Security
                ),
            ),
            request=req,
            error_status_codes=["400", "404", "4XX", "5XX"],
            retry_config=retry_config,
        )

        def next_func() -> Optional[models.ListBalancesResponse]:
            body = utils.unmarshal_json(http_res.text, Union[Dict[Any, Any], List[Any]])

            next_url_match = JSONPath("$._links.next.href").parse(body)
            if len(next_url_match) == 0:
                return None

            next_url = next_url_match[0]
            if not next_url:
                return None

            if next_url[0] == "/":
                url = self._get_url(base_url, url_variables)
                next_url = url + next_url

            return self.list(
                currency=currency,
                from_=from_,
                limit=limit,
                testmode=testmode,
                idempotency_key=idempotency_key,
                retries=retries,
                url_override=next_url,
            )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/hal+json"):
            return models.ListBalancesResponse(
                result=unmarshal_json_response(
                    models.ListBalancesResponseBody, http_res
                ),
                next=next_func,
            )
        if utils.match_response(http_res, ["400", "404"], "application/hal+json"):
            response_data = unmarshal_json_response(models.ErrorResponseData, http_res)
            raise models.ErrorResponse(response_data, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise models.APIError("API error occurred", http_res, http_res_text)
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise models.APIError("API error occurred", http_res, http_res_text)

        raise models.APIError("Unexpected response received", http_res)

    async def list_async(
        self,
        *,
        currency: OptionalNullable[str] = UNSET,
        from_: OptionalNullable[str] = UNSET,
        limit: OptionalNullable[int] = UNSET,
        testmode: Optional[bool] = None,
        idempotency_key: Optional[str] = None,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        url_override: Optional[str] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> Optional[models.ListBalancesResponse]:
        r"""List balances

        Retrieve a list of the organization's balances, including the primary balance.

        The results are paginated.

        :param currency: Optionally only return balances with the given currency. For example: `EUR`.
        :param from_: Provide an ID to start the result set from the item with the given ID and onwards. This allows you to paginate the
            result set.
        :param limit: The maximum number of items to return. Defaults to 50 items.
        :param testmode: You can enable test mode by setting the `testmode` query parameter to `true`.

            Test entities cannot be retrieved when the endpoint is set to live mode, and vice versa.
        :param idempotency_key: A unique key to ensure idempotent requests. This key should be a UUID v4 string.
        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = models.ListBalancesRequest(
            currency=currency,
            from_=from_,
            limit=limit,
            testmode=testmode,
            idempotency_key=idempotency_key,
        )

        req = self._build_request_async(
            method="GET",
            path="/balances",
            base_url=base_url,
            url_variables=url_variables,
            url_override=url_override,
            request=request,
            request_body_required=False,
            request_has_path_params=False,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/hal+json",
            http_headers=http_headers,
            _globals=models.ListBalancesGlobals(
                testmode=self.sdk_configuration.globals.testmode,
            ),
            security=self.sdk_configuration.security,
            allow_empty_value=None,
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config
            else:
                retries = utils.RetryConfig(
                    "backoff", utils.BackoffStrategy(500, 5000, 2, 7500), True
                )

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["5xx"])

        http_res = await self.do_request_async(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="list-balances",
                oauth2_scopes=None,
                security_source=get_security_from_env(
                    self.sdk_configuration.security, models.Security
                ),
            ),
            request=req,
            error_status_codes=["400", "404", "4XX", "5XX"],
            retry_config=retry_config,
        )

        def next_func() -> Awaitable[Optional[models.ListBalancesResponse]]:
            body = utils.unmarshal_json(http_res.text, Union[Dict[Any, Any], List[Any]])

            async def empty_result():
                return None

            next_url_match = JSONPath("$._links.next.href").parse(body)
            if len(next_url_match) == 0:
                return empty_result()

            next_url = next_url_match[0]
            if not next_url:
                return empty_result()

            if next_url[0] == "/":
                url = self._get_url(base_url, url_variables)
                next_url = url + next_url

            return self.list_async(
                currency=currency,
                from_=from_,
                limit=limit,
                testmode=testmode,
                idempotency_key=idempotency_key,
                retries=retries,
                url_override=next_url,
            )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/hal+json"):
            return models.ListBalancesResponse(
                result=unmarshal_json_response(
                    models.ListBalancesResponseBody, http_res
                ),
                next=next_func,
            )
        if utils.match_response(http_res, ["400", "404"], "application/hal+json"):
            response_data = unmarshal_json_response(models.ErrorResponseData, http_res)
            raise models.ErrorResponse(response_data, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise models.APIError("API error occurred", http_res, http_res_text)
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise models.APIError("API error occurred", http_res, http_res_text)

        raise models.APIError("Unexpected response received", http_res)

    def get(
        self,
        *,
        balance_id: str,
        testmode: Optional[bool] = None,
        idempotency_key: Optional[str] = None,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> models.EntityBalance:
        r"""Get balance

        When processing payments with Mollie, we put all pending funds — usually
        minus Mollie fees — on a balance. Once you have linked a bank account to your Mollie account, we can pay out your
        balance towards this bank account.

        With the Balances API you can retrieve your current balance. The response
        includes two amounts:

        * The *pending amount*. These are payments that have been marked as `paid`,
        but are not yet available on your balance.
        * The *available amount*. This is the amount that you can get paid out to
        your bank account, or use for refunds.

        With instant payment methods like iDEAL, payments are moved to the available
        balance instantly. With slower payment methods, like credit card for example, it can take a few days before the
        funds are available on your balance. These funds will be shown under the *pending amount* in the meanwhile.

        :param balance_id: Provide the ID of the related balance.
        :param testmode: You can enable test mode by setting the `testmode` query parameter to `true`.

            Test entities cannot be retrieved when the endpoint is set to live mode, and vice versa.
        :param idempotency_key: A unique key to ensure idempotent requests. This key should be a UUID v4 string.
        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = models.GetBalanceRequest(
            balance_id=balance_id,
            testmode=testmode,
            idempotency_key=idempotency_key,
        )

        req = self._build_request(
            method="GET",
            path="/balances/{balanceId}",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=False,
            request_has_path_params=True,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/hal+json",
            http_headers=http_headers,
            _globals=models.GetBalanceGlobals(
                testmode=self.sdk_configuration.globals.testmode,
            ),
            security=self.sdk_configuration.security,
            allow_empty_value=None,
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config
            else:
                retries = utils.RetryConfig(
                    "backoff", utils.BackoffStrategy(500, 5000, 2, 7500), True
                )

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["5xx"])

        http_res = self.do_request(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="get-balance",
                oauth2_scopes=None,
                security_source=get_security_from_env(
                    self.sdk_configuration.security, models.Security
                ),
            ),
            request=req,
            error_status_codes=["404", "4XX", "5XX"],
            retry_config=retry_config,
        )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/hal+json"):
            return unmarshal_json_response(models.EntityBalance, http_res)
        if utils.match_response(http_res, "404", "application/hal+json"):
            response_data = unmarshal_json_response(models.ErrorResponseData, http_res)
            raise models.ErrorResponse(response_data, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise models.APIError("API error occurred", http_res, http_res_text)
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise models.APIError("API error occurred", http_res, http_res_text)

        raise models.APIError("Unexpected response received", http_res)

    async def get_async(
        self,
        *,
        balance_id: str,
        testmode: Optional[bool] = None,
        idempotency_key: Optional[str] = None,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> models.EntityBalance:
        r"""Get balance

        When processing payments with Mollie, we put all pending funds — usually
        minus Mollie fees — on a balance. Once you have linked a bank account to your Mollie account, we can pay out your
        balance towards this bank account.

        With the Balances API you can retrieve your current balance. The response
        includes two amounts:

        * The *pending amount*. These are payments that have been marked as `paid`,
        but are not yet available on your balance.
        * The *available amount*. This is the amount that you can get paid out to
        your bank account, or use for refunds.

        With instant payment methods like iDEAL, payments are moved to the available
        balance instantly. With slower payment methods, like credit card for example, it can take a few days before the
        funds are available on your balance. These funds will be shown under the *pending amount* in the meanwhile.

        :param balance_id: Provide the ID of the related balance.
        :param testmode: You can enable test mode by setting the `testmode` query parameter to `true`.

            Test entities cannot be retrieved when the endpoint is set to live mode, and vice versa.
        :param idempotency_key: A unique key to ensure idempotent requests. This key should be a UUID v4 string.
        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = models.GetBalanceRequest(
            balance_id=balance_id,
            testmode=testmode,
            idempotency_key=idempotency_key,
        )

        req = self._build_request_async(
            method="GET",
            path="/balances/{balanceId}",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=False,
            request_has_path_params=True,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/hal+json",
            http_headers=http_headers,
            _globals=models.GetBalanceGlobals(
                testmode=self.sdk_configuration.globals.testmode,
            ),
            security=self.sdk_configuration.security,
            allow_empty_value=None,
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config
            else:
                retries = utils.RetryConfig(
                    "backoff", utils.BackoffStrategy(500, 5000, 2, 7500), True
                )

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["5xx"])

        http_res = await self.do_request_async(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="get-balance",
                oauth2_scopes=None,
                security_source=get_security_from_env(
                    self.sdk_configuration.security, models.Security
                ),
            ),
            request=req,
            error_status_codes=["404", "4XX", "5XX"],
            retry_config=retry_config,
        )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/hal+json"):
            return unmarshal_json_response(models.EntityBalance, http_res)
        if utils.match_response(http_res, "404", "application/hal+json"):
            response_data = unmarshal_json_response(models.ErrorResponseData, http_res)
            raise models.ErrorResponse(response_data, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise models.APIError("API error occurred", http_res, http_res_text)
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise models.APIError("API error occurred", http_res, http_res_text)

        raise models.APIError("Unexpected response received", http_res)

    def get_primary(
        self,
        *,
        idempotency_key: Optional[str] = None,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> models.EntityBalance:
        r"""Get primary balance

        Retrieve the primary balance. This is the balance of your account's primary
        currency, where all payments are settled to by default.

        This endpoint is a convenient alias of the [Get balance](get-balance)
        endpoint.

        :param idempotency_key: A unique key to ensure idempotent requests. This key should be a UUID v4 string.
        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = models.GetPrimaryBalanceRequest(
            idempotency_key=idempotency_key,
        )

        req = self._build_request(
            method="GET",
            path="/balances/primary",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=False,
            request_has_path_params=False,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/hal+json",
            http_headers=http_headers,
            security=self.sdk_configuration.security,
            allow_empty_value=None,
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config
            else:
                retries = utils.RetryConfig(
                    "backoff", utils.BackoffStrategy(500, 5000, 2, 7500), True
                )

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["5xx"])

        http_res = self.do_request(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="get-primary-balance",
                oauth2_scopes=None,
                security_source=get_security_from_env(
                    self.sdk_configuration.security, models.Security
                ),
            ),
            request=req,
            error_status_codes=["4XX", "5XX"],
            retry_config=retry_config,
        )

        if utils.match_response(http_res, "200", "application/hal+json"):
            return unmarshal_json_response(models.EntityBalance, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise models.APIError("API error occurred", http_res, http_res_text)
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise models.APIError("API error occurred", http_res, http_res_text)

        raise models.APIError("Unexpected response received", http_res)

    async def get_primary_async(
        self,
        *,
        idempotency_key: Optional[str] = None,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> models.EntityBalance:
        r"""Get primary balance

        Retrieve the primary balance. This is the balance of your account's primary
        currency, where all payments are settled to by default.

        This endpoint is a convenient alias of the [Get balance](get-balance)
        endpoint.

        :param idempotency_key: A unique key to ensure idempotent requests. This key should be a UUID v4 string.
        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = models.GetPrimaryBalanceRequest(
            idempotency_key=idempotency_key,
        )

        req = self._build_request_async(
            method="GET",
            path="/balances/primary",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=False,
            request_has_path_params=False,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/hal+json",
            http_headers=http_headers,
            security=self.sdk_configuration.security,
            allow_empty_value=None,
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config
            else:
                retries = utils.RetryConfig(
                    "backoff", utils.BackoffStrategy(500, 5000, 2, 7500), True
                )

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["5xx"])

        http_res = await self.do_request_async(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="get-primary-balance",
                oauth2_scopes=None,
                security_source=get_security_from_env(
                    self.sdk_configuration.security, models.Security
                ),
            ),
            request=req,
            error_status_codes=["4XX", "5XX"],
            retry_config=retry_config,
        )

        if utils.match_response(http_res, "200", "application/hal+json"):
            return unmarshal_json_response(models.EntityBalance, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise models.APIError("API error occurred", http_res, http_res_text)
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise models.APIError("API error occurred", http_res, http_res_text)

        raise models.APIError("Unexpected response received", http_res)

    def get_report(
        self,
        *,
        balance_id: str,
        from_: str,
        until: str,
        grouping: Optional[models.BalanceReportGrouping] = None,
        testmode: Optional[bool] = None,
        idempotency_key: Optional[str] = None,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> models.EntityBalanceReport:
        r"""Get balance report

        Retrieve a summarized report for all transactions on a given balance within a given timeframe.

        The API also provides a detailed report on all 'prepayments' for Mollie fees that were deducted from your balance
        during the reported period, ahead of your Mollie invoice.

        The alias `primary` can be used instead of the balance ID to refer to the
        organization's primary balance.

        :param balance_id: Provide the ID of the related balance.
        :param from_: The start date of the report, in `YYYY-MM-DD` format. The from date is
            'inclusive', and in Central European Time. This means a report with for example `from=2024-01-01` will
            include transactions from 2024-01-01 0:00:00 CET and onwards.
        :param until: The end date of the report, in `YYYY-MM-DD` format. The until date is 'exclusive', and in Central European Time.
            This means a report with for example `until=2024-02-01` will include transactions up until
            2024-01-31 23:59:59 CET.
        :param grouping: You can retrieve reports in two different formats. With the `status-balances` format, transactions are grouped
            by status (e.g. `pending`, `available`), then by transaction type, and then by other sub-groupings where
            available (e.g. payment method).

            With the `transaction-categories` format, transactions are grouped by
            transaction type, then by status, and then again by other sub-groupings where available.
        :param testmode: You can enable test mode by setting the `testmode` query parameter to `true`.

            Test entities cannot be retrieved when the endpoint is set to live mode, and vice versa.
        :param idempotency_key: A unique key to ensure idempotent requests. This key should be a UUID v4 string.
        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = models.GetBalanceReportRequest(
            balance_id=balance_id,
            from_=from_,
            until=until,
            grouping=grouping,
            testmode=testmode,
            idempotency_key=idempotency_key,
        )

        req = self._build_request(
            method="GET",
            path="/balances/{balanceId}/report",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=False,
            request_has_path_params=True,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/hal+json",
            http_headers=http_headers,
            _globals=models.GetBalanceReportGlobals(
                testmode=self.sdk_configuration.globals.testmode,
            ),
            security=self.sdk_configuration.security,
            allow_empty_value=None,
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config
            else:
                retries = utils.RetryConfig(
                    "backoff", utils.BackoffStrategy(500, 5000, 2, 7500), True
                )

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["5xx"])

        http_res = self.do_request(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="get-balance-report",
                oauth2_scopes=None,
                security_source=get_security_from_env(
                    self.sdk_configuration.security, models.Security
                ),
            ),
            request=req,
            error_status_codes=["404", "422", "4XX", "5XX"],
            retry_config=retry_config,
        )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/hal+json"):
            return unmarshal_json_response(models.EntityBalanceReport, http_res)
        if utils.match_response(http_res, ["404", "422"], "application/hal+json"):
            response_data = unmarshal_json_response(models.ErrorResponseData, http_res)
            raise models.ErrorResponse(response_data, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise models.APIError("API error occurred", http_res, http_res_text)
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise models.APIError("API error occurred", http_res, http_res_text)

        raise models.APIError("Unexpected response received", http_res)

    async def get_report_async(
        self,
        *,
        balance_id: str,
        from_: str,
        until: str,
        grouping: Optional[models.BalanceReportGrouping] = None,
        testmode: Optional[bool] = None,
        idempotency_key: Optional[str] = None,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> models.EntityBalanceReport:
        r"""Get balance report

        Retrieve a summarized report for all transactions on a given balance within a given timeframe.

        The API also provides a detailed report on all 'prepayments' for Mollie fees that were deducted from your balance
        during the reported period, ahead of your Mollie invoice.

        The alias `primary` can be used instead of the balance ID to refer to the
        organization's primary balance.

        :param balance_id: Provide the ID of the related balance.
        :param from_: The start date of the report, in `YYYY-MM-DD` format. The from date is
            'inclusive', and in Central European Time. This means a report with for example `from=2024-01-01` will
            include transactions from 2024-01-01 0:00:00 CET and onwards.
        :param until: The end date of the report, in `YYYY-MM-DD` format. The until date is 'exclusive', and in Central European Time.
            This means a report with for example `until=2024-02-01` will include transactions up until
            2024-01-31 23:59:59 CET.
        :param grouping: You can retrieve reports in two different formats. With the `status-balances` format, transactions are grouped
            by status (e.g. `pending`, `available`), then by transaction type, and then by other sub-groupings where
            available (e.g. payment method).

            With the `transaction-categories` format, transactions are grouped by
            transaction type, then by status, and then again by other sub-groupings where available.
        :param testmode: You can enable test mode by setting the `testmode` query parameter to `true`.

            Test entities cannot be retrieved when the endpoint is set to live mode, and vice versa.
        :param idempotency_key: A unique key to ensure idempotent requests. This key should be a UUID v4 string.
        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = models.GetBalanceReportRequest(
            balance_id=balance_id,
            from_=from_,
            until=until,
            grouping=grouping,
            testmode=testmode,
            idempotency_key=idempotency_key,
        )

        req = self._build_request_async(
            method="GET",
            path="/balances/{balanceId}/report",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=False,
            request_has_path_params=True,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/hal+json",
            http_headers=http_headers,
            _globals=models.GetBalanceReportGlobals(
                testmode=self.sdk_configuration.globals.testmode,
            ),
            security=self.sdk_configuration.security,
            allow_empty_value=None,
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config
            else:
                retries = utils.RetryConfig(
                    "backoff", utils.BackoffStrategy(500, 5000, 2, 7500), True
                )

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["5xx"])

        http_res = await self.do_request_async(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="get-balance-report",
                oauth2_scopes=None,
                security_source=get_security_from_env(
                    self.sdk_configuration.security, models.Security
                ),
            ),
            request=req,
            error_status_codes=["404", "422", "4XX", "5XX"],
            retry_config=retry_config,
        )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/hal+json"):
            return unmarshal_json_response(models.EntityBalanceReport, http_res)
        if utils.match_response(http_res, ["404", "422"], "application/hal+json"):
            response_data = unmarshal_json_response(models.ErrorResponseData, http_res)
            raise models.ErrorResponse(response_data, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise models.APIError("API error occurred", http_res, http_res_text)
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise models.APIError("API error occurred", http_res, http_res_text)

        raise models.APIError("Unexpected response received", http_res)

    def list_transactions(
        self,
        *,
        balance_id: str,
        from_: OptionalNullable[str] = UNSET,
        limit: OptionalNullable[int] = UNSET,
        testmode: Optional[bool] = None,
        idempotency_key: Optional[str] = None,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        url_override: Optional[str] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> Optional[models.ListBalanceTransactionsResponse]:
        r"""List balance transactions

        Retrieve a list of all balance transactions. Transactions include for
        example payments, refunds, chargebacks, and settlements.

        For an aggregated report of these balance transactions, refer to the [Get
        balance report](get-balance-report) endpoint.

        The alias `primary` can be used instead of the balance ID to refer to the
        organization's primary balance.

        The results are paginated.

        :param balance_id: Provide the ID of the related balance.
        :param from_: Provide an ID to start the result set from the item with the given ID and onwards. This allows you to paginate the
            result set.
        :param limit: The maximum number of items to return. Defaults to 50 items.
        :param testmode: You can enable test mode by setting the `testmode` query parameter to `true`.

            Test entities cannot be retrieved when the endpoint is set to live mode, and vice versa.
        :param idempotency_key: A unique key to ensure idempotent requests. This key should be a UUID v4 string.
        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = models.ListBalanceTransactionsRequest(
            balance_id=balance_id,
            from_=from_,
            limit=limit,
            testmode=testmode,
            idempotency_key=idempotency_key,
        )

        req = self._build_request(
            method="GET",
            path="/balances/{balanceId}/transactions",
            base_url=base_url,
            url_variables=url_variables,
            url_override=url_override,
            request=request,
            request_body_required=False,
            request_has_path_params=True,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/hal+json",
            http_headers=http_headers,
            _globals=models.ListBalanceTransactionsGlobals(
                testmode=self.sdk_configuration.globals.testmode,
            ),
            security=self.sdk_configuration.security,
            allow_empty_value=None,
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config
            else:
                retries = utils.RetryConfig(
                    "backoff", utils.BackoffStrategy(500, 5000, 2, 7500), True
                )

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["5xx"])

        http_res = self.do_request(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="list-balance-transactions",
                oauth2_scopes=None,
                security_source=get_security_from_env(
                    self.sdk_configuration.security, models.Security
                ),
            ),
            request=req,
            error_status_codes=["400", "404", "429", "4XX", "5XX"],
            retry_config=retry_config,
        )

        def next_func() -> Optional[models.ListBalanceTransactionsResponse]:
            body = utils.unmarshal_json(http_res.text, Union[Dict[Any, Any], List[Any]])

            next_url_match = JSONPath("$._links.next.href").parse(body)
            if len(next_url_match) == 0:
                return None

            next_url = next_url_match[0]
            if not next_url:
                return None

            if next_url[0] == "/":
                url = self._get_url(base_url, url_variables)
                next_url = url + next_url

            return self.list_transactions(
                balance_id=balance_id,
                from_=from_,
                limit=limit,
                testmode=testmode,
                idempotency_key=idempotency_key,
                retries=retries,
                url_override=next_url,
            )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/hal+json"):
            return models.ListBalanceTransactionsResponse(
                result=unmarshal_json_response(
                    models.ListBalanceTransactionsResponseBody, http_res
                ),
                next=next_func,
            )
        if utils.match_response(
            http_res, ["400", "404", "429"], "application/hal+json"
        ):
            response_data = unmarshal_json_response(models.ErrorResponseData, http_res)
            raise models.ErrorResponse(response_data, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise models.APIError("API error occurred", http_res, http_res_text)
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise models.APIError("API error occurred", http_res, http_res_text)

        raise models.APIError("Unexpected response received", http_res)

    async def list_transactions_async(
        self,
        *,
        balance_id: str,
        from_: OptionalNullable[str] = UNSET,
        limit: OptionalNullable[int] = UNSET,
        testmode: Optional[bool] = None,
        idempotency_key: Optional[str] = None,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        url_override: Optional[str] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> Optional[models.ListBalanceTransactionsResponse]:
        r"""List balance transactions

        Retrieve a list of all balance transactions. Transactions include for
        example payments, refunds, chargebacks, and settlements.

        For an aggregated report of these balance transactions, refer to the [Get
        balance report](get-balance-report) endpoint.

        The alias `primary` can be used instead of the balance ID to refer to the
        organization's primary balance.

        The results are paginated.

        :param balance_id: Provide the ID of the related balance.
        :param from_: Provide an ID to start the result set from the item with the given ID and onwards. This allows you to paginate the
            result set.
        :param limit: The maximum number of items to return. Defaults to 50 items.
        :param testmode: You can enable test mode by setting the `testmode` query parameter to `true`.

            Test entities cannot be retrieved when the endpoint is set to live mode, and vice versa.
        :param idempotency_key: A unique key to ensure idempotent requests. This key should be a UUID v4 string.
        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = models.ListBalanceTransactionsRequest(
            balance_id=balance_id,
            from_=from_,
            limit=limit,
            testmode=testmode,
            idempotency_key=idempotency_key,
        )

        req = self._build_request_async(
            method="GET",
            path="/balances/{balanceId}/transactions",
            base_url=base_url,
            url_variables=url_variables,
            url_override=url_override,
            request=request,
            request_body_required=False,
            request_has_path_params=True,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/hal+json",
            http_headers=http_headers,
            _globals=models.ListBalanceTransactionsGlobals(
                testmode=self.sdk_configuration.globals.testmode,
            ),
            security=self.sdk_configuration.security,
            allow_empty_value=None,
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config
            else:
                retries = utils.RetryConfig(
                    "backoff", utils.BackoffStrategy(500, 5000, 2, 7500), True
                )

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["5xx"])

        http_res = await self.do_request_async(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="list-balance-transactions",
                oauth2_scopes=None,
                security_source=get_security_from_env(
                    self.sdk_configuration.security, models.Security
                ),
            ),
            request=req,
            error_status_codes=["400", "404", "429", "4XX", "5XX"],
            retry_config=retry_config,
        )

        def next_func() -> Awaitable[Optional[models.ListBalanceTransactionsResponse]]:
            body = utils.unmarshal_json(http_res.text, Union[Dict[Any, Any], List[Any]])

            async def empty_result():
                return None

            next_url_match = JSONPath("$._links.next.href").parse(body)
            if len(next_url_match) == 0:
                return empty_result()

            next_url = next_url_match[0]
            if not next_url:
                return empty_result()

            if next_url[0] == "/":
                url = self._get_url(base_url, url_variables)
                next_url = url + next_url

            return self.list_transactions_async(
                balance_id=balance_id,
                from_=from_,
                limit=limit,
                testmode=testmode,
                idempotency_key=idempotency_key,
                retries=retries,
                url_override=next_url,
            )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/hal+json"):
            return models.ListBalanceTransactionsResponse(
                result=unmarshal_json_response(
                    models.ListBalanceTransactionsResponseBody, http_res
                ),
                next=next_func,
            )
        if utils.match_response(
            http_res, ["400", "404", "429"], "application/hal+json"
        ):
            response_data = unmarshal_json_response(models.ErrorResponseData, http_res)
            raise models.ErrorResponse(response_data, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise models.APIError("API error occurred", http_res, http_res_text)
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise models.APIError("API error occurred", http_res, http_res_text)

        raise models.APIError("Unexpected response received", http_res)
