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

import typing
import urllib.parse
from json.decoder import JSONDecodeError

from ..commons.errors.server_error import ServerError
from ..commons.errors.unauthorized_error import UnauthorizedError
from ..commons.types.error_body import ErrorBody
from ..commons.types.phone_number import PhoneNumber
from ..commons.types.webhook import Webhook
from ..core.api_error import ApiError
from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from ..core.jsonable_encoder import jsonable_encoder
from ..core.pydantic_utilities import pydantic_v1
from ..core.remove_none_from_dict import remove_none_from_dict
from ..core.request_options import RequestOptions
from .types.check_status_response import CheckStatusResponse
from .types.get_messages_response import GetMessagesResponse
from .types.legal_structure_enum import LegalStructureEnum
from .types.register_response import RegisterResponse
from .types.toggle_reply_response import ToggleReplyResponse
from .types.trusted_user import TrustedUser
from .types.update_prompt_response import UpdatePromptResponse
from .types.update_webhook_response import UpdateWebhookResponse
from .types.vertical_enum import VerticalEnum

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


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

    def register(
        self,
        *,
        business_name: str,
        ein: str,
        vertical: VerticalEnum,
        address: str,
        city: str,
        state: str,
        postal_code: str,
        country: str,
        email: str,
        type: LegalStructureEnum,
        website: str,
        opt_in_info: str,
        message_samples: typing.Sequence[str],
        trusted_user: TrustedUser,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> RegisterResponse:
        """
        This documentation provides detailed information on how to register an Application-to-Person (A2P) brand by making a POST request to our API. The process involves submitting your brand's details for registration and verification purposes.

        A2P Registration is required _for_ all businesses who wish to send SMS. There can be signifcant fines for any non compliant messages. A2P Registration can take 2 days -> 2 Weeks.

        Parameters
        ----------
        business_name : str
            The legal name of your business.

        ein : str
            Your Employer Identification Number.

        vertical : VerticalEnum
            The industry vertical of your business.

        address : str
            The business address.

        city : str
            The city of your business.

        state : str
            The state of your business. Must be a valid US state code.

        postal_code : str
            The postal code of your business.

        country : str
            The country of your business.

        email : str
            The email address for your business.

        type : LegalStructureEnum
            Legal structure of the business.

        website : str
            Your business's website URL.

        opt_in_info : str
            Information regarding opt-in procedures for your messaging service.

            EX: “Customers must explicitly consent on our website and during the phone call.”

        message_samples : typing.Sequence[str]
            An array of three strings, each a sample message you plan to use.

        trusted_user : TrustedUser
            An object containing details about the trusted user registering the brand.

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

        Returns
        -------
        RegisterResponse
            A successful request returns a `200 OK` status code with a JSON body containing a message indicating the registration was successful and any relevant data or identifiers related to the A2P brand registration.

            **Important:** The Brand Registration can take several attempts and days to weeks to complete. This success only indicates we submitted the registration correctly.


        Examples
        --------
        from bland import TrustedUser
        from bland.client import BlandAI

        client = BlandAI(
            api_key="YOUR_API_KEY",
        )
        client.sms.register(
            business_name="string",
            ein="string",
            vertical="AUTOMOTIVE",
            address="string",
            city="string",
            state="string",
            postal_code="string",
            country="string",
            email="string",
            type="Partnership",
            website="string",
            opt_in_info="string",
            message_samples=["string"],
            trusted_user=TrustedUser(),
        )
        """
        _request: typing.Dict[str, typing.Any] = {
            "businessName": business_name,
            "ein": ein,
            "vertical": vertical,
            "address": address,
            "city": city,
            "state": state,
            "postalCode": postal_code,
            "country": country,
            "email": email,
            "type": type,
            "website": website,
            "opt_in_info": opt_in_info,
            "messageSamples": message_samples,
            "trusted_user": trusted_user,
        }
        _response = self._client_wrapper.httpx_client.request(
            method="POST",
            url=urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "v1/sms/register"),
            params=jsonable_encoder(
                request_options.get("additional_query_parameters") if request_options is not None else None
            ),
            json=jsonable_encoder(_request)
            if request_options is None or request_options.get("additional_body_parameters") is None
            else {
                **jsonable_encoder(_request),
                **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))),
            },
            headers=jsonable_encoder(
                remove_none_from_dict(
                    {
                        **self._client_wrapper.get_headers(),
                        **(request_options.get("additional_headers", {}) if request_options is not None else {}),
                    }
                )
            ),
            timeout=request_options.get("timeout_in_seconds")
            if request_options is not None and request_options.get("timeout_in_seconds") is not None
            else self._client_wrapper.get_timeout(),
            retries=0,
            max_retries=request_options.get("max_retries") if request_options is not None else 0,  # type: ignore
        )
        if 200 <= _response.status_code < 300:
            return pydantic_v1.parse_obj_as(RegisterResponse, _response.json())  # type: ignore
        if _response.status_code == 500:
            raise ServerError(pydantic_v1.parse_obj_as(ErrorBody, _response.json()))  # type: ignore
        if _response.status_code == 401:
            raise UnauthorizedError(pydantic_v1.parse_obj_as(ErrorBody, _response.json()))  # type: ignore
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def check(
        self, *, registration_id: str, request_options: typing.Optional[RequestOptions] = None
    ) -> CheckStatusResponse:
        """
        Check the status of an A2P registration.

        Parameters
        ----------
        registration_id : str
            The registration_id for the a2p registration.

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

        Returns
        -------
        CheckStatusResponse

        Examples
        --------
        from bland.client import BlandAI

        client = BlandAI(
            api_key="YOUR_API_KEY",
        )
        client.sms.check(
            registration_id="string",
        )
        """
        _request: typing.Dict[str, typing.Any] = {"registration_id": registration_id}
        _response = self._client_wrapper.httpx_client.request(
            method="POST",
            url=urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "v1/sms/register/status"),
            params=jsonable_encoder(
                request_options.get("additional_query_parameters") if request_options is not None else None
            ),
            json=jsonable_encoder(_request)
            if request_options is None or request_options.get("additional_body_parameters") is None
            else {
                **jsonable_encoder(_request),
                **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))),
            },
            headers=jsonable_encoder(
                remove_none_from_dict(
                    {
                        **self._client_wrapper.get_headers(),
                        **(request_options.get("additional_headers", {}) if request_options is not None else {}),
                    }
                )
            ),
            timeout=request_options.get("timeout_in_seconds")
            if request_options is not None and request_options.get("timeout_in_seconds") is not None
            else self._client_wrapper.get_timeout(),
            retries=0,
            max_retries=request_options.get("max_retries") if request_options is not None else 0,  # type: ignore
        )
        if 200 <= _response.status_code < 300:
            return pydantic_v1.parse_obj_as(CheckStatusResponse, _response.json())  # type: ignore
        if _response.status_code == 500:
            raise ServerError(pydantic_v1.parse_obj_as(ErrorBody, _response.json()))  # type: ignore
        if _response.status_code == 401:
            raise UnauthorizedError(pydantic_v1.parse_obj_as(ErrorBody, _response.json()))  # type: ignore
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def get(
        self,
        *,
        phone_number: typing.Optional[PhoneNumber] = OMIT,
        to: typing.Optional[PhoneNumber] = OMIT,
        from_: typing.Optional[PhoneNumber] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> GetMessagesResponse:
        """
        Get the list of SMS messages for a given conversation.

        Parameters
        ----------
        phone_number : typing.Optional[PhoneNumber]
            The phone number to get messages for.

        to : typing.Optional[PhoneNumber]
            The to number in the conversation. This is the number you _do not_ own.

        from_ : typing.Optional[PhoneNumber]
            The from number in the conversation. This is the number you _do_ own.

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

        Returns
        -------
        GetMessagesResponse

        Examples
        --------
        from bland.client import BlandAI

        client = BlandAI(
            api_key="YOUR_API_KEY",
        )
        client.sms.get(
            phone_number="+18582814611",
            to="+18582814611",
            from_="+18582814611",
        )
        """
        _request: typing.Dict[str, typing.Any] = {}
        if phone_number is not OMIT:
            _request["phone_number"] = phone_number
        if to is not OMIT:
            _request["to"] = to
        if from_ is not OMIT:
            _request["from"] = from_
        _response = self._client_wrapper.httpx_client.request(
            method="POST",
            url=urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "v1/sms/messages/get"),
            params=jsonable_encoder(
                request_options.get("additional_query_parameters") if request_options is not None else None
            ),
            json=jsonable_encoder(_request)
            if request_options is None or request_options.get("additional_body_parameters") is None
            else {
                **jsonable_encoder(_request),
                **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))),
            },
            headers=jsonable_encoder(
                remove_none_from_dict(
                    {
                        **self._client_wrapper.get_headers(),
                        **(request_options.get("additional_headers", {}) if request_options is not None else {}),
                    }
                )
            ),
            timeout=request_options.get("timeout_in_seconds")
            if request_options is not None and request_options.get("timeout_in_seconds") is not None
            else self._client_wrapper.get_timeout(),
            retries=0,
            max_retries=request_options.get("max_retries") if request_options is not None else 0,  # type: ignore
        )
        if 200 <= _response.status_code < 300:
            return pydantic_v1.parse_obj_as(GetMessagesResponse, _response.json())  # type: ignore
        if _response.status_code == 500:
            raise ServerError(pydantic_v1.parse_obj_as(ErrorBody, _response.json()))  # type: ignore
        if _response.status_code == 401:
            raise UnauthorizedError(pydantic_v1.parse_obj_as(ErrorBody, _response.json()))  # type: ignore
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def toggle(
        self,
        *,
        phone_number: typing.Optional[PhoneNumber] = OMIT,
        on: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ToggleReplyResponse:
        """
        Turn on or off the AI replying for a given phone number.

        Parameters
        ----------
        phone_number : typing.Optional[PhoneNumber]
            The phone number to update.

        on : typing.Optional[bool]
            Turn human mode on or off.

            `true` means that the AI will not reply. `false` means the AI will reply.

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

        Returns
        -------
        ToggleReplyResponse

        Examples
        --------
        from bland.client import BlandAI

        client = BlandAI(
            api_key="YOUR_API_KEY",
        )
        client.sms.toggle(
            phone_number="+18582814611",
            on=True,
        )
        """
        _request: typing.Dict[str, typing.Any] = {}
        if phone_number is not OMIT:
            _request["phone_number"] = phone_number
        if on is not OMIT:
            _request["on"] = on
        _response = self._client_wrapper.httpx_client.request(
            method="POST",
            url=urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "v1/sms/toggle"),
            params=jsonable_encoder(
                request_options.get("additional_query_parameters") if request_options is not None else None
            ),
            json=jsonable_encoder(_request)
            if request_options is None or request_options.get("additional_body_parameters") is None
            else {
                **jsonable_encoder(_request),
                **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))),
            },
            headers=jsonable_encoder(
                remove_none_from_dict(
                    {
                        **self._client_wrapper.get_headers(),
                        **(request_options.get("additional_headers", {}) if request_options is not None else {}),
                    }
                )
            ),
            timeout=request_options.get("timeout_in_seconds")
            if request_options is not None and request_options.get("timeout_in_seconds") is not None
            else self._client_wrapper.get_timeout(),
            retries=0,
            max_retries=request_options.get("max_retries") if request_options is not None else 0,  # type: ignore
        )
        if 200 <= _response.status_code < 300:
            return pydantic_v1.parse_obj_as(ToggleReplyResponse, _response.json())  # type: ignore
        if _response.status_code == 500:
            raise ServerError(pydantic_v1.parse_obj_as(ErrorBody, _response.json()))  # type: ignore
        if _response.status_code == 401:
            raise UnauthorizedError(pydantic_v1.parse_obj_as(ErrorBody, _response.json()))  # type: ignore
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def update_prompt(
        self,
        *,
        phone_number: typing.Optional[PhoneNumber] = OMIT,
        prompt: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> UpdatePromptResponse:
        """
        Purchase and configure a new inbound phone number. ($15/mo. subscription using your stored payment method).

        Parameters
        ----------
        phone_number : typing.Optional[PhoneNumber]
            The phone number to update.

        prompt : typing.Optional[str]
            The prompt for the AI to use when replying.

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

        Returns
        -------
        UpdatePromptResponse

        Examples
        --------
        from bland.client import BlandAI

        client = BlandAI(
            api_key="YOUR_API_KEY",
        )
        client.sms.update_prompt(
            phone_number="+18582814611",
            prompt="string",
        )
        """
        _request: typing.Dict[str, typing.Any] = {}
        if phone_number is not OMIT:
            _request["phone_number"] = phone_number
        if prompt is not OMIT:
            _request["prompt"] = prompt
        _response = self._client_wrapper.httpx_client.request(
            method="POST",
            url=urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "v1/sms/prompt/update"),
            params=jsonable_encoder(
                request_options.get("additional_query_parameters") if request_options is not None else None
            ),
            json=jsonable_encoder(_request)
            if request_options is None or request_options.get("additional_body_parameters") is None
            else {
                **jsonable_encoder(_request),
                **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))),
            },
            headers=jsonable_encoder(
                remove_none_from_dict(
                    {
                        **self._client_wrapper.get_headers(),
                        **(request_options.get("additional_headers", {}) if request_options is not None else {}),
                    }
                )
            ),
            timeout=request_options.get("timeout_in_seconds")
            if request_options is not None and request_options.get("timeout_in_seconds") is not None
            else self._client_wrapper.get_timeout(),
            retries=0,
            max_retries=request_options.get("max_retries") if request_options is not None else 0,  # type: ignore
        )
        if 200 <= _response.status_code < 300:
            return pydantic_v1.parse_obj_as(UpdatePromptResponse, _response.json())  # type: ignore
        if _response.status_code == 500:
            raise ServerError(pydantic_v1.parse_obj_as(ErrorBody, _response.json()))  # type: ignore
        if _response.status_code == 401:
            raise UnauthorizedError(pydantic_v1.parse_obj_as(ErrorBody, _response.json()))  # type: ignore
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def update_webhook(
        self,
        *,
        phone_number: typing.Optional[PhoneNumber] = OMIT,
        webhook: typing.Optional[Webhook] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> UpdateWebhookResponse:
        """
        Update the webhook for a given phone number.

        Parameters
        ----------
        phone_number : typing.Optional[PhoneNumber]
            The phone number to update.

        webhook : typing.Optional[Webhook]
            The webhook to fire when an SMS is received.

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

        Returns
        -------
        UpdateWebhookResponse

        Examples
        --------
        from bland.client import BlandAI

        client = BlandAI(
            api_key="YOUR_API_KEY",
        )
        client.sms.update_webhook(
            phone_number="+18582814611",
            webhook="string",
        )
        """
        _request: typing.Dict[str, typing.Any] = {}
        if phone_number is not OMIT:
            _request["phone_number"] = phone_number
        if webhook is not OMIT:
            _request["webhook"] = webhook
        _response = self._client_wrapper.httpx_client.request(
            method="POST",
            url=urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "v1/sms/webhook/update"),
            params=jsonable_encoder(
                request_options.get("additional_query_parameters") if request_options is not None else None
            ),
            json=jsonable_encoder(_request)
            if request_options is None or request_options.get("additional_body_parameters") is None
            else {
                **jsonable_encoder(_request),
                **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))),
            },
            headers=jsonable_encoder(
                remove_none_from_dict(
                    {
                        **self._client_wrapper.get_headers(),
                        **(request_options.get("additional_headers", {}) if request_options is not None else {}),
                    }
                )
            ),
            timeout=request_options.get("timeout_in_seconds")
            if request_options is not None and request_options.get("timeout_in_seconds") is not None
            else self._client_wrapper.get_timeout(),
            retries=0,
            max_retries=request_options.get("max_retries") if request_options is not None else 0,  # type: ignore
        )
        if 200 <= _response.status_code < 300:
            return pydantic_v1.parse_obj_as(UpdateWebhookResponse, _response.json())  # type: ignore
        if _response.status_code == 500:
            raise ServerError(pydantic_v1.parse_obj_as(ErrorBody, _response.json()))  # type: ignore
        if _response.status_code == 401:
            raise UnauthorizedError(pydantic_v1.parse_obj_as(ErrorBody, _response.json()))  # type: ignore
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)


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

    async def register(
        self,
        *,
        business_name: str,
        ein: str,
        vertical: VerticalEnum,
        address: str,
        city: str,
        state: str,
        postal_code: str,
        country: str,
        email: str,
        type: LegalStructureEnum,
        website: str,
        opt_in_info: str,
        message_samples: typing.Sequence[str],
        trusted_user: TrustedUser,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> RegisterResponse:
        """
        This documentation provides detailed information on how to register an Application-to-Person (A2P) brand by making a POST request to our API. The process involves submitting your brand's details for registration and verification purposes.

        A2P Registration is required _for_ all businesses who wish to send SMS. There can be signifcant fines for any non compliant messages. A2P Registration can take 2 days -> 2 Weeks.

        Parameters
        ----------
        business_name : str
            The legal name of your business.

        ein : str
            Your Employer Identification Number.

        vertical : VerticalEnum
            The industry vertical of your business.

        address : str
            The business address.

        city : str
            The city of your business.

        state : str
            The state of your business. Must be a valid US state code.

        postal_code : str
            The postal code of your business.

        country : str
            The country of your business.

        email : str
            The email address for your business.

        type : LegalStructureEnum
            Legal structure of the business.

        website : str
            Your business's website URL.

        opt_in_info : str
            Information regarding opt-in procedures for your messaging service.

            EX: “Customers must explicitly consent on our website and during the phone call.”

        message_samples : typing.Sequence[str]
            An array of three strings, each a sample message you plan to use.

        trusted_user : TrustedUser
            An object containing details about the trusted user registering the brand.

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

        Returns
        -------
        RegisterResponse
            A successful request returns a `200 OK` status code with a JSON body containing a message indicating the registration was successful and any relevant data or identifiers related to the A2P brand registration.

            **Important:** The Brand Registration can take several attempts and days to weeks to complete. This success only indicates we submitted the registration correctly.


        Examples
        --------
        from bland import TrustedUser
        from bland.client import AsyncBlandAI

        client = AsyncBlandAI(
            api_key="YOUR_API_KEY",
        )
        await client.sms.register(
            business_name="string",
            ein="string",
            vertical="AUTOMOTIVE",
            address="string",
            city="string",
            state="string",
            postal_code="string",
            country="string",
            email="string",
            type="Partnership",
            website="string",
            opt_in_info="string",
            message_samples=["string"],
            trusted_user=TrustedUser(),
        )
        """
        _request: typing.Dict[str, typing.Any] = {
            "businessName": business_name,
            "ein": ein,
            "vertical": vertical,
            "address": address,
            "city": city,
            "state": state,
            "postalCode": postal_code,
            "country": country,
            "email": email,
            "type": type,
            "website": website,
            "opt_in_info": opt_in_info,
            "messageSamples": message_samples,
            "trusted_user": trusted_user,
        }
        _response = await self._client_wrapper.httpx_client.request(
            method="POST",
            url=urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "v1/sms/register"),
            params=jsonable_encoder(
                request_options.get("additional_query_parameters") if request_options is not None else None
            ),
            json=jsonable_encoder(_request)
            if request_options is None or request_options.get("additional_body_parameters") is None
            else {
                **jsonable_encoder(_request),
                **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))),
            },
            headers=jsonable_encoder(
                remove_none_from_dict(
                    {
                        **self._client_wrapper.get_headers(),
                        **(request_options.get("additional_headers", {}) if request_options is not None else {}),
                    }
                )
            ),
            timeout=request_options.get("timeout_in_seconds")
            if request_options is not None and request_options.get("timeout_in_seconds") is not None
            else self._client_wrapper.get_timeout(),
            retries=0,
            max_retries=request_options.get("max_retries") if request_options is not None else 0,  # type: ignore
        )
        if 200 <= _response.status_code < 300:
            return pydantic_v1.parse_obj_as(RegisterResponse, _response.json())  # type: ignore
        if _response.status_code == 500:
            raise ServerError(pydantic_v1.parse_obj_as(ErrorBody, _response.json()))  # type: ignore
        if _response.status_code == 401:
            raise UnauthorizedError(pydantic_v1.parse_obj_as(ErrorBody, _response.json()))  # type: ignore
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def check(
        self, *, registration_id: str, request_options: typing.Optional[RequestOptions] = None
    ) -> CheckStatusResponse:
        """
        Check the status of an A2P registration.

        Parameters
        ----------
        registration_id : str
            The registration_id for the a2p registration.

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

        Returns
        -------
        CheckStatusResponse

        Examples
        --------
        from bland.client import AsyncBlandAI

        client = AsyncBlandAI(
            api_key="YOUR_API_KEY",
        )
        await client.sms.check(
            registration_id="string",
        )
        """
        _request: typing.Dict[str, typing.Any] = {"registration_id": registration_id}
        _response = await self._client_wrapper.httpx_client.request(
            method="POST",
            url=urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "v1/sms/register/status"),
            params=jsonable_encoder(
                request_options.get("additional_query_parameters") if request_options is not None else None
            ),
            json=jsonable_encoder(_request)
            if request_options is None or request_options.get("additional_body_parameters") is None
            else {
                **jsonable_encoder(_request),
                **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))),
            },
            headers=jsonable_encoder(
                remove_none_from_dict(
                    {
                        **self._client_wrapper.get_headers(),
                        **(request_options.get("additional_headers", {}) if request_options is not None else {}),
                    }
                )
            ),
            timeout=request_options.get("timeout_in_seconds")
            if request_options is not None and request_options.get("timeout_in_seconds") is not None
            else self._client_wrapper.get_timeout(),
            retries=0,
            max_retries=request_options.get("max_retries") if request_options is not None else 0,  # type: ignore
        )
        if 200 <= _response.status_code < 300:
            return pydantic_v1.parse_obj_as(CheckStatusResponse, _response.json())  # type: ignore
        if _response.status_code == 500:
            raise ServerError(pydantic_v1.parse_obj_as(ErrorBody, _response.json()))  # type: ignore
        if _response.status_code == 401:
            raise UnauthorizedError(pydantic_v1.parse_obj_as(ErrorBody, _response.json()))  # type: ignore
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def get(
        self,
        *,
        phone_number: typing.Optional[PhoneNumber] = OMIT,
        to: typing.Optional[PhoneNumber] = OMIT,
        from_: typing.Optional[PhoneNumber] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> GetMessagesResponse:
        """
        Get the list of SMS messages for a given conversation.

        Parameters
        ----------
        phone_number : typing.Optional[PhoneNumber]
            The phone number to get messages for.

        to : typing.Optional[PhoneNumber]
            The to number in the conversation. This is the number you _do not_ own.

        from_ : typing.Optional[PhoneNumber]
            The from number in the conversation. This is the number you _do_ own.

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

        Returns
        -------
        GetMessagesResponse

        Examples
        --------
        from bland.client import AsyncBlandAI

        client = AsyncBlandAI(
            api_key="YOUR_API_KEY",
        )
        await client.sms.get(
            phone_number="+18582814611",
            to="+18582814611",
            from_="+18582814611",
        )
        """
        _request: typing.Dict[str, typing.Any] = {}
        if phone_number is not OMIT:
            _request["phone_number"] = phone_number
        if to is not OMIT:
            _request["to"] = to
        if from_ is not OMIT:
            _request["from"] = from_
        _response = await self._client_wrapper.httpx_client.request(
            method="POST",
            url=urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "v1/sms/messages/get"),
            params=jsonable_encoder(
                request_options.get("additional_query_parameters") if request_options is not None else None
            ),
            json=jsonable_encoder(_request)
            if request_options is None or request_options.get("additional_body_parameters") is None
            else {
                **jsonable_encoder(_request),
                **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))),
            },
            headers=jsonable_encoder(
                remove_none_from_dict(
                    {
                        **self._client_wrapper.get_headers(),
                        **(request_options.get("additional_headers", {}) if request_options is not None else {}),
                    }
                )
            ),
            timeout=request_options.get("timeout_in_seconds")
            if request_options is not None and request_options.get("timeout_in_seconds") is not None
            else self._client_wrapper.get_timeout(),
            retries=0,
            max_retries=request_options.get("max_retries") if request_options is not None else 0,  # type: ignore
        )
        if 200 <= _response.status_code < 300:
            return pydantic_v1.parse_obj_as(GetMessagesResponse, _response.json())  # type: ignore
        if _response.status_code == 500:
            raise ServerError(pydantic_v1.parse_obj_as(ErrorBody, _response.json()))  # type: ignore
        if _response.status_code == 401:
            raise UnauthorizedError(pydantic_v1.parse_obj_as(ErrorBody, _response.json()))  # type: ignore
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def toggle(
        self,
        *,
        phone_number: typing.Optional[PhoneNumber] = OMIT,
        on: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ToggleReplyResponse:
        """
        Turn on or off the AI replying for a given phone number.

        Parameters
        ----------
        phone_number : typing.Optional[PhoneNumber]
            The phone number to update.

        on : typing.Optional[bool]
            Turn human mode on or off.

            `true` means that the AI will not reply. `false` means the AI will reply.

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

        Returns
        -------
        ToggleReplyResponse

        Examples
        --------
        from bland.client import AsyncBlandAI

        client = AsyncBlandAI(
            api_key="YOUR_API_KEY",
        )
        await client.sms.toggle(
            phone_number="+18582814611",
            on=True,
        )
        """
        _request: typing.Dict[str, typing.Any] = {}
        if phone_number is not OMIT:
            _request["phone_number"] = phone_number
        if on is not OMIT:
            _request["on"] = on
        _response = await self._client_wrapper.httpx_client.request(
            method="POST",
            url=urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "v1/sms/toggle"),
            params=jsonable_encoder(
                request_options.get("additional_query_parameters") if request_options is not None else None
            ),
            json=jsonable_encoder(_request)
            if request_options is None or request_options.get("additional_body_parameters") is None
            else {
                **jsonable_encoder(_request),
                **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))),
            },
            headers=jsonable_encoder(
                remove_none_from_dict(
                    {
                        **self._client_wrapper.get_headers(),
                        **(request_options.get("additional_headers", {}) if request_options is not None else {}),
                    }
                )
            ),
            timeout=request_options.get("timeout_in_seconds")
            if request_options is not None and request_options.get("timeout_in_seconds") is not None
            else self._client_wrapper.get_timeout(),
            retries=0,
            max_retries=request_options.get("max_retries") if request_options is not None else 0,  # type: ignore
        )
        if 200 <= _response.status_code < 300:
            return pydantic_v1.parse_obj_as(ToggleReplyResponse, _response.json())  # type: ignore
        if _response.status_code == 500:
            raise ServerError(pydantic_v1.parse_obj_as(ErrorBody, _response.json()))  # type: ignore
        if _response.status_code == 401:
            raise UnauthorizedError(pydantic_v1.parse_obj_as(ErrorBody, _response.json()))  # type: ignore
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def update_prompt(
        self,
        *,
        phone_number: typing.Optional[PhoneNumber] = OMIT,
        prompt: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> UpdatePromptResponse:
        """
        Purchase and configure a new inbound phone number. ($15/mo. subscription using your stored payment method).

        Parameters
        ----------
        phone_number : typing.Optional[PhoneNumber]
            The phone number to update.

        prompt : typing.Optional[str]
            The prompt for the AI to use when replying.

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

        Returns
        -------
        UpdatePromptResponse

        Examples
        --------
        from bland.client import AsyncBlandAI

        client = AsyncBlandAI(
            api_key="YOUR_API_KEY",
        )
        await client.sms.update_prompt(
            phone_number="+18582814611",
            prompt="string",
        )
        """
        _request: typing.Dict[str, typing.Any] = {}
        if phone_number is not OMIT:
            _request["phone_number"] = phone_number
        if prompt is not OMIT:
            _request["prompt"] = prompt
        _response = await self._client_wrapper.httpx_client.request(
            method="POST",
            url=urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "v1/sms/prompt/update"),
            params=jsonable_encoder(
                request_options.get("additional_query_parameters") if request_options is not None else None
            ),
            json=jsonable_encoder(_request)
            if request_options is None or request_options.get("additional_body_parameters") is None
            else {
                **jsonable_encoder(_request),
                **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))),
            },
            headers=jsonable_encoder(
                remove_none_from_dict(
                    {
                        **self._client_wrapper.get_headers(),
                        **(request_options.get("additional_headers", {}) if request_options is not None else {}),
                    }
                )
            ),
            timeout=request_options.get("timeout_in_seconds")
            if request_options is not None and request_options.get("timeout_in_seconds") is not None
            else self._client_wrapper.get_timeout(),
            retries=0,
            max_retries=request_options.get("max_retries") if request_options is not None else 0,  # type: ignore
        )
        if 200 <= _response.status_code < 300:
            return pydantic_v1.parse_obj_as(UpdatePromptResponse, _response.json())  # type: ignore
        if _response.status_code == 500:
            raise ServerError(pydantic_v1.parse_obj_as(ErrorBody, _response.json()))  # type: ignore
        if _response.status_code == 401:
            raise UnauthorizedError(pydantic_v1.parse_obj_as(ErrorBody, _response.json()))  # type: ignore
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def update_webhook(
        self,
        *,
        phone_number: typing.Optional[PhoneNumber] = OMIT,
        webhook: typing.Optional[Webhook] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> UpdateWebhookResponse:
        """
        Update the webhook for a given phone number.

        Parameters
        ----------
        phone_number : typing.Optional[PhoneNumber]
            The phone number to update.

        webhook : typing.Optional[Webhook]
            The webhook to fire when an SMS is received.

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

        Returns
        -------
        UpdateWebhookResponse

        Examples
        --------
        from bland.client import AsyncBlandAI

        client = AsyncBlandAI(
            api_key="YOUR_API_KEY",
        )
        await client.sms.update_webhook(
            phone_number="+18582814611",
            webhook="string",
        )
        """
        _request: typing.Dict[str, typing.Any] = {}
        if phone_number is not OMIT:
            _request["phone_number"] = phone_number
        if webhook is not OMIT:
            _request["webhook"] = webhook
        _response = await self._client_wrapper.httpx_client.request(
            method="POST",
            url=urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "v1/sms/webhook/update"),
            params=jsonable_encoder(
                request_options.get("additional_query_parameters") if request_options is not None else None
            ),
            json=jsonable_encoder(_request)
            if request_options is None or request_options.get("additional_body_parameters") is None
            else {
                **jsonable_encoder(_request),
                **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))),
            },
            headers=jsonable_encoder(
                remove_none_from_dict(
                    {
                        **self._client_wrapper.get_headers(),
                        **(request_options.get("additional_headers", {}) if request_options is not None else {}),
                    }
                )
            ),
            timeout=request_options.get("timeout_in_seconds")
            if request_options is not None and request_options.get("timeout_in_seconds") is not None
            else self._client_wrapper.get_timeout(),
            retries=0,
            max_retries=request_options.get("max_retries") if request_options is not None else 0,  # type: ignore
        )
        if 200 <= _response.status_code < 300:
            return pydantic_v1.parse_obj_as(UpdateWebhookResponse, _response.json())  # type: ignore
        if _response.status_code == 500:
            raise ServerError(pydantic_v1.parse_obj_as(ErrorBody, _response.json()))  # type: ignore
        if _response.status_code == 401:
            raise UnauthorizedError(pydantic_v1.parse_obj_as(ErrorBody, _response.json()))  # type: ignore
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)
