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

import typing
from json.decoder import JSONDecodeError

from ...core.api_error import ApiError
from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from ...core.http_response import AsyncHttpResponse, HttpResponse
from ...core.jsonable_encoder import jsonable_encoder
from ...core.pydantic_utilities import parse_obj_as
from ...core.request_options import RequestOptions
from ...core.serialization import convert_and_respect_annotation_metadata
from ...errors.bad_request_error import BadRequestError
from ...errors.internal_server_error import InternalServerError
from ...errors.not_found_error import NotFoundError
from ...errors.payment_required_error import PaymentRequiredError
from ...errors.unauthorized_error import UnauthorizedError
from ...types.campaign_submission_result import CampaignSubmissionResult
from ...types.campaign_validation_result import CampaignValidationResult
from ...types.error import Error
from ...types.extended_rcs_campaign import ExtendedRcsCampaign
from ...types.rcs_messaging_type_enum import RcsMessagingTypeEnum
from .types.rcs_agent import RcsAgent
from .types.rcs_autofill_response import RcsAutofillResponse
from .types.rcs_campaign_keywords import RcsCampaignKeywords
from .types.rcs_campaign_traffic import RcsCampaignTraffic
from .types.rcs_links import RcsLinks
from .types.rcs_use_case import RcsUseCase

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


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

    def autofill(
        self,
        *,
        additional_info: typing.Optional[str] = OMIT,
        campaign_id: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[RcsAutofillResponse]:
        """
        Generate campaign details based off existing campaign and the brand it's connected to.

        Parameters
        ----------
        additional_info : typing.Optional[str]
            Any additional information you want to provide.

        campaign_id : typing.Optional[str]
            Unique identifier for the campaign.
            - When autofilling 10DLC campaigns, it must begin with the prefix `dlc_` (e.g., `dlc_1234567890`)
            - When autofilling Toll-Free campaigns, it must begin with the prefix `tf_` (e.g., `tf_1234567890`)
            - When autofilling RCS campaigns, it must begin with the prefix `rcs_` (e.g., `rcs_1234567890`)

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

        Returns
        -------
        HttpResponse[RcsAutofillResponse]
            Returns autofilled RCS information.
        """
        _response = self._client_wrapper.httpx_client.request(
            "campaigns/rcs/autofill",
            method="POST",
            json={
                "additionalInfo": additional_info,
                "campaignId": campaign_id,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    RcsAutofillResponse,
                    parse_obj_as(
                        type_=RcsAutofillResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def get(
        self, campaign_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[ExtendedRcsCampaign]:
        """
        Retrieve RCS campaign.

        Parameters
        ----------
        campaign_id : str
            Unique identifier of the RCS campaign. Must begin with the prefix `rcs_`.

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

        Returns
        -------
        HttpResponse[ExtendedRcsCampaign]
            Successfully retrieved.
        """
        _response = self._client_wrapper.httpx_client.request(
            f"campaigns/rcs/{jsonable_encoder(campaign_id)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    ExtendedRcsCampaign,
                    parse_obj_as(
                        type_=ExtendedRcsCampaign,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def submit(
        self, campaign_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[CampaignSubmissionResult]:
        """
        Submit your RCS campaign for approval and activation with carriers.

        Parameters
        ----------
        campaign_id : str
            Unique identifier of the RCS campaign to retrieve. Must begin with the prefix `rcs_`.

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

        Returns
        -------
        HttpResponse[CampaignSubmissionResult]
            Successfully submitted RCS campaign for approval.
        """
        _response = self._client_wrapper.httpx_client.request(
            f"campaigns/rcs/submit/{jsonable_encoder(campaign_id)}",
            method="POST",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    CampaignSubmissionResult,
                    parse_obj_as(
                        type_=CampaignSubmissionResult,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 402:
                raise PaymentRequiredError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def upsert(
        self,
        *,
        agent: typing.Optional[RcsAgent] = OMIT,
        brand: typing.Optional[str] = OMIT,
        campaign_id: typing.Optional[str] = OMIT,
        expected_agent_responses: typing.Optional[typing.Sequence[str]] = OMIT,
        links: typing.Optional[RcsLinks] = OMIT,
        use_case: typing.Optional[RcsUseCase] = OMIT,
        opt_in_terms_and_conditions: typing.Optional[str] = OMIT,
        messaging_type: typing.Optional[RcsMessagingTypeEnum] = OMIT,
        carrier_description: typing.Optional[str] = OMIT,
        keywords: typing.Optional[RcsCampaignKeywords] = OMIT,
        traffic: typing.Optional[RcsCampaignTraffic] = OMIT,
        agent_triggers: typing.Optional[str] = OMIT,
        interaction_description: typing.Optional[str] = OMIT,
        is_conversational: typing.Optional[bool] = OMIT,
        cta_language: typing.Optional[str] = OMIT,
        demo_trigger: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[ExtendedRcsCampaign]:
        """
        Create a new RCS campaign or update an existing one.

        <Note>
        **To create a new campaign:** Omit `campaignId` — one will be generated automatically.

        **Before you start:** Create a [brand](/api-reference/brands/upsert) first — you'll need its `id` for the [`brand`](#request.body.brand) field.

        All fields are **required** unless specified otherwise, and will be validated when [submitted](/api-reference/campaigns/rcs/submit).
        </Note>

        Parameters
        ----------
        agent : typing.Optional[RcsAgent]
            Create an agent for the campaign.

        brand : typing.Optional[str]
            Unique identifier for the brand.

        campaign_id : typing.Optional[str]
            Unique identifier for the campaign.

        expected_agent_responses : typing.Optional[typing.Sequence[str]]
            List of what the agent might say to users. See the [Expected Agent Responses](/guides/campaigns/rcs-compliance#expected-agent-responses) section for requirements. <br><br>
            **Limit:** 1 to 5

        links : typing.Optional[RcsLinks]
            Legal documentation links.

        use_case : typing.Optional[RcsUseCase]
            Use case classification for the campaign.

        opt_in_terms_and_conditions : typing.Optional[str]
            Details on how opt-in is acquired. If it is done through a website or app, provide the link. See the [Opt-In Terms and Conditions](/guides/campaigns/rcs-compliance#opt-in-terms-and-conditions) section for requirements.

        messaging_type : typing.Optional[RcsMessagingTypeEnum]

        carrier_description : typing.Optional[str]
            Description of the agent's purpose, shown to carriers for approval. See the [Carrier Description](/guides/campaigns/rcs-compliance#carrier-description) section for requirements.

        keywords : typing.Optional[RcsCampaignKeywords]

        traffic : typing.Optional[RcsCampaignTraffic]

        agent_triggers : typing.Optional[str]
            Explanation of how the agent is triggered. This includes how the first message is delivered, whether messages follow a schedule or triggered by user actions, and any external triggers. See the [Agent Triggers](/guides/campaigns/rcs-compliance#agent-triggers) section for requirements.

        interaction_description : typing.Optional[str]
            Description of all agent interactions, including primary and secondary use cases. See the [Interaction Description](/guides/campaigns/rcs-compliance#interaction-description) section for requirements.

        is_conversational : typing.Optional[bool]
            Whether the agent supports conversational flows or respond to P2A messages from the users. Set to false for one-way messages from agent to user.

        cta_language : typing.Optional[str]
            Required text that appears next to the opt-in checkbox for your opt-in form. This checkbox has to be unchecked by default. See the [CTA Language](/guides/campaigns/rcs-compliance#cta-language-opt-in-disclosure) section for requirements.

        demo_trigger : typing.Optional[str]
            Instructions on how an external reviewer can trigger messages and an example flow from the agent. This is usually an inbound text message to the agent that will start a flow of messages between the agent and the user. See the [Demo Trigger](/guides/campaigns/rcs-compliance#demo-trigger) section for requirements.

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

        Returns
        -------
        HttpResponse[ExtendedRcsCampaign]
            Successfully created or updated RCS campaign.
        """
        _response = self._client_wrapper.httpx_client.request(
            "campaigns/rcs",
            method="POST",
            json={
                "agent": convert_and_respect_annotation_metadata(object_=agent, annotation=RcsAgent, direction="write"),
                "brand": brand,
                "campaignId": campaign_id,
                "expectedAgentResponses": expected_agent_responses,
                "links": convert_and_respect_annotation_metadata(object_=links, annotation=RcsLinks, direction="write"),
                "useCase": convert_and_respect_annotation_metadata(
                    object_=use_case, annotation=RcsUseCase, direction="write"
                ),
                "optInTermsAndConditions": opt_in_terms_and_conditions,
                "messagingType": messaging_type,
                "carrierDescription": carrier_description,
                "keywords": convert_and_respect_annotation_metadata(
                    object_=keywords, annotation=RcsCampaignKeywords, direction="write"
                ),
                "traffic": convert_and_respect_annotation_metadata(
                    object_=traffic, annotation=RcsCampaignTraffic, direction="write"
                ),
                "agentTriggers": agent_triggers,
                "interactionDescription": interaction_description,
                "isConversational": is_conversational,
                "ctaLanguage": cta_language,
                "demoTrigger": demo_trigger,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    ExtendedRcsCampaign,
                    parse_obj_as(
                        type_=ExtendedRcsCampaign,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def validate(
        self,
        *,
        campaign_id: str,
        additional_info: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[CampaignValidationResult]:
        """
        Validate your RCS campaign configuration against carrier requirements and compliance rules.

        Parameters
        ----------
        campaign_id : str
            Unique identifier for the campaign.
            - When validating 10DLC campaigns, it must begin with the prefix `dlc_` (e.g., `dlc_1234567890`)
            - When validating toll-free campaigns, it must begin with the prefix `tf_` (e.g., `tf_1234567890`)
            - When validating RCS campaigns, it must begin with the prefix `rcs_` (e.g., `rcs_1234567890`)

        additional_info : typing.Optional[str]
            Any additional information you want to provide.

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

        Returns
        -------
        HttpResponse[CampaignValidationResult]
            Returns validation results.
        """
        _response = self._client_wrapper.httpx_client.request(
            "campaigns/rcs/validate",
            method="POST",
            json={
                "additionalInfo": additional_info,
                "campaignId": campaign_id,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    CampaignValidationResult,
                    parse_obj_as(
                        type_=CampaignValidationResult,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)


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

    async def autofill(
        self,
        *,
        additional_info: typing.Optional[str] = OMIT,
        campaign_id: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[RcsAutofillResponse]:
        """
        Generate campaign details based off existing campaign and the brand it's connected to.

        Parameters
        ----------
        additional_info : typing.Optional[str]
            Any additional information you want to provide.

        campaign_id : typing.Optional[str]
            Unique identifier for the campaign.
            - When autofilling 10DLC campaigns, it must begin with the prefix `dlc_` (e.g., `dlc_1234567890`)
            - When autofilling Toll-Free campaigns, it must begin with the prefix `tf_` (e.g., `tf_1234567890`)
            - When autofilling RCS campaigns, it must begin with the prefix `rcs_` (e.g., `rcs_1234567890`)

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

        Returns
        -------
        AsyncHttpResponse[RcsAutofillResponse]
            Returns autofilled RCS information.
        """
        _response = await self._client_wrapper.httpx_client.request(
            "campaigns/rcs/autofill",
            method="POST",
            json={
                "additionalInfo": additional_info,
                "campaignId": campaign_id,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    RcsAutofillResponse,
                    parse_obj_as(
                        type_=RcsAutofillResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def get(
        self, campaign_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[ExtendedRcsCampaign]:
        """
        Retrieve RCS campaign.

        Parameters
        ----------
        campaign_id : str
            Unique identifier of the RCS campaign. Must begin with the prefix `rcs_`.

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

        Returns
        -------
        AsyncHttpResponse[ExtendedRcsCampaign]
            Successfully retrieved.
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"campaigns/rcs/{jsonable_encoder(campaign_id)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    ExtendedRcsCampaign,
                    parse_obj_as(
                        type_=ExtendedRcsCampaign,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def submit(
        self, campaign_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[CampaignSubmissionResult]:
        """
        Submit your RCS campaign for approval and activation with carriers.

        Parameters
        ----------
        campaign_id : str
            Unique identifier of the RCS campaign to retrieve. Must begin with the prefix `rcs_`.

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

        Returns
        -------
        AsyncHttpResponse[CampaignSubmissionResult]
            Successfully submitted RCS campaign for approval.
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"campaigns/rcs/submit/{jsonable_encoder(campaign_id)}",
            method="POST",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    CampaignSubmissionResult,
                    parse_obj_as(
                        type_=CampaignSubmissionResult,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 402:
                raise PaymentRequiredError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def upsert(
        self,
        *,
        agent: typing.Optional[RcsAgent] = OMIT,
        brand: typing.Optional[str] = OMIT,
        campaign_id: typing.Optional[str] = OMIT,
        expected_agent_responses: typing.Optional[typing.Sequence[str]] = OMIT,
        links: typing.Optional[RcsLinks] = OMIT,
        use_case: typing.Optional[RcsUseCase] = OMIT,
        opt_in_terms_and_conditions: typing.Optional[str] = OMIT,
        messaging_type: typing.Optional[RcsMessagingTypeEnum] = OMIT,
        carrier_description: typing.Optional[str] = OMIT,
        keywords: typing.Optional[RcsCampaignKeywords] = OMIT,
        traffic: typing.Optional[RcsCampaignTraffic] = OMIT,
        agent_triggers: typing.Optional[str] = OMIT,
        interaction_description: typing.Optional[str] = OMIT,
        is_conversational: typing.Optional[bool] = OMIT,
        cta_language: typing.Optional[str] = OMIT,
        demo_trigger: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[ExtendedRcsCampaign]:
        """
        Create a new RCS campaign or update an existing one.

        <Note>
        **To create a new campaign:** Omit `campaignId` — one will be generated automatically.

        **Before you start:** Create a [brand](/api-reference/brands/upsert) first — you'll need its `id` for the [`brand`](#request.body.brand) field.

        All fields are **required** unless specified otherwise, and will be validated when [submitted](/api-reference/campaigns/rcs/submit).
        </Note>

        Parameters
        ----------
        agent : typing.Optional[RcsAgent]
            Create an agent for the campaign.

        brand : typing.Optional[str]
            Unique identifier for the brand.

        campaign_id : typing.Optional[str]
            Unique identifier for the campaign.

        expected_agent_responses : typing.Optional[typing.Sequence[str]]
            List of what the agent might say to users. See the [Expected Agent Responses](/guides/campaigns/rcs-compliance#expected-agent-responses) section for requirements. <br><br>
            **Limit:** 1 to 5

        links : typing.Optional[RcsLinks]
            Legal documentation links.

        use_case : typing.Optional[RcsUseCase]
            Use case classification for the campaign.

        opt_in_terms_and_conditions : typing.Optional[str]
            Details on how opt-in is acquired. If it is done through a website or app, provide the link. See the [Opt-In Terms and Conditions](/guides/campaigns/rcs-compliance#opt-in-terms-and-conditions) section for requirements.

        messaging_type : typing.Optional[RcsMessagingTypeEnum]

        carrier_description : typing.Optional[str]
            Description of the agent's purpose, shown to carriers for approval. See the [Carrier Description](/guides/campaigns/rcs-compliance#carrier-description) section for requirements.

        keywords : typing.Optional[RcsCampaignKeywords]

        traffic : typing.Optional[RcsCampaignTraffic]

        agent_triggers : typing.Optional[str]
            Explanation of how the agent is triggered. This includes how the first message is delivered, whether messages follow a schedule or triggered by user actions, and any external triggers. See the [Agent Triggers](/guides/campaigns/rcs-compliance#agent-triggers) section for requirements.

        interaction_description : typing.Optional[str]
            Description of all agent interactions, including primary and secondary use cases. See the [Interaction Description](/guides/campaigns/rcs-compliance#interaction-description) section for requirements.

        is_conversational : typing.Optional[bool]
            Whether the agent supports conversational flows or respond to P2A messages from the users. Set to false for one-way messages from agent to user.

        cta_language : typing.Optional[str]
            Required text that appears next to the opt-in checkbox for your opt-in form. This checkbox has to be unchecked by default. See the [CTA Language](/guides/campaigns/rcs-compliance#cta-language-opt-in-disclosure) section for requirements.

        demo_trigger : typing.Optional[str]
            Instructions on how an external reviewer can trigger messages and an example flow from the agent. This is usually an inbound text message to the agent that will start a flow of messages between the agent and the user. See the [Demo Trigger](/guides/campaigns/rcs-compliance#demo-trigger) section for requirements.

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

        Returns
        -------
        AsyncHttpResponse[ExtendedRcsCampaign]
            Successfully created or updated RCS campaign.
        """
        _response = await self._client_wrapper.httpx_client.request(
            "campaigns/rcs",
            method="POST",
            json={
                "agent": convert_and_respect_annotation_metadata(object_=agent, annotation=RcsAgent, direction="write"),
                "brand": brand,
                "campaignId": campaign_id,
                "expectedAgentResponses": expected_agent_responses,
                "links": convert_and_respect_annotation_metadata(object_=links, annotation=RcsLinks, direction="write"),
                "useCase": convert_and_respect_annotation_metadata(
                    object_=use_case, annotation=RcsUseCase, direction="write"
                ),
                "optInTermsAndConditions": opt_in_terms_and_conditions,
                "messagingType": messaging_type,
                "carrierDescription": carrier_description,
                "keywords": convert_and_respect_annotation_metadata(
                    object_=keywords, annotation=RcsCampaignKeywords, direction="write"
                ),
                "traffic": convert_and_respect_annotation_metadata(
                    object_=traffic, annotation=RcsCampaignTraffic, direction="write"
                ),
                "agentTriggers": agent_triggers,
                "interactionDescription": interaction_description,
                "isConversational": is_conversational,
                "ctaLanguage": cta_language,
                "demoTrigger": demo_trigger,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    ExtendedRcsCampaign,
                    parse_obj_as(
                        type_=ExtendedRcsCampaign,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def validate(
        self,
        *,
        campaign_id: str,
        additional_info: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[CampaignValidationResult]:
        """
        Validate your RCS campaign configuration against carrier requirements and compliance rules.

        Parameters
        ----------
        campaign_id : str
            Unique identifier for the campaign.
            - When validating 10DLC campaigns, it must begin with the prefix `dlc_` (e.g., `dlc_1234567890`)
            - When validating toll-free campaigns, it must begin with the prefix `tf_` (e.g., `tf_1234567890`)
            - When validating RCS campaigns, it must begin with the prefix `rcs_` (e.g., `rcs_1234567890`)

        additional_info : typing.Optional[str]
            Any additional information you want to provide.

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

        Returns
        -------
        AsyncHttpResponse[CampaignValidationResult]
            Returns validation results.
        """
        _response = await self._client_wrapper.httpx_client.request(
            "campaigns/rcs/validate",
            method="POST",
            json={
                "additionalInfo": additional_info,
                "campaignId": campaign_id,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    CampaignValidationResult,
                    parse_obj_as(
                        type_=CampaignValidationResult,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
