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

from __future__ import annotations

import typing

import httpx
from .core.api_error import ApiError
from .core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from .core.oauth_token_provider import AsyncOAuthTokenProvider, OAuthTokenProvider
from .environment import CandidApiClientEnvironment

if typing.TYPE_CHECKING:
    from .resources.auth.client import AsyncAuthClient, AuthClient
    from .resources.billing_notes.client import AsyncBillingNotesClient, BillingNotesClient
    from .resources.charge_capture.client import AsyncChargeCaptureClient, ChargeCaptureClient
    from .resources.charge_capture_bundles.client import AsyncChargeCaptureBundlesClient, ChargeCaptureBundlesClient
    from .resources.contracts.client import AsyncContractsClient, ContractsClient
    from .resources.credentialing.client import AsyncCredentialingClient, CredentialingClient
    from .resources.custom_schemas.client import AsyncCustomSchemasClient, CustomSchemasClient
    from .resources.diagnoses.client import AsyncDiagnosesClient, DiagnosesClient
    from .resources.eligibility.client import AsyncEligibilityClient, EligibilityClient
    from .resources.encounter_attachments.client import AsyncEncounterAttachmentsClient, EncounterAttachmentsClient
    from .resources.encounter_providers.client import AsyncEncounterProvidersClient, EncounterProvidersClient
    from .resources.encounter_supplemental_information.client import (
        AsyncEncounterSupplementalInformationClient,
        EncounterSupplementalInformationClient,
    )
    from .resources.encounters.client import AsyncEncountersClient, EncountersClient
    from .resources.events.client import AsyncEventsClient, EventsClient
    from .resources.exports.client import AsyncExportsClient, ExportsClient
    from .resources.external_payment_account_config.client import (
        AsyncExternalPaymentAccountConfigClient,
        ExternalPaymentAccountConfigClient,
    )
    from .resources.fee_schedules.client import AsyncFeeSchedulesClient, FeeSchedulesClient
    from .resources.guarantor.client import AsyncGuarantorClient, GuarantorClient
    from .resources.health_care_code_information.client import (
        AsyncHealthCareCodeInformationClient,
        HealthCareCodeInformationClient,
    )
    from .resources.import_invoice.client import AsyncImportInvoiceClient, ImportInvoiceClient
    from .resources.insurance_adjudications.client import (
        AsyncInsuranceAdjudicationsClient,
        InsuranceAdjudicationsClient,
    )
    from .resources.insurance_refunds.client import AsyncInsuranceRefundsClient, InsuranceRefundsClient
    from .resources.medication_dispense.client import AsyncMedicationDispenseClient, MedicationDispenseClient
    from .resources.non_insurance_payer_payments.client import (
        AsyncNonInsurancePayerPaymentsClient,
        NonInsurancePayerPaymentsClient,
    )
    from .resources.non_insurance_payer_refunds.client import (
        AsyncNonInsurancePayerRefundsClient,
        NonInsurancePayerRefundsClient,
    )
    from .resources.non_insurance_payers.client import AsyncNonInsurancePayersClient, NonInsurancePayersClient
    from .resources.organization_providers.client import AsyncOrganizationProvidersClient, OrganizationProvidersClient
    from .resources.organization_service_facilities.client import (
        AsyncOrganizationServiceFacilitiesClient,
        OrganizationServiceFacilitiesClient,
    )
    from .resources.patient_ar.client import AsyncPatientArClient, PatientArClient
    from .resources.patient_payments.client import AsyncPatientPaymentsClient, PatientPaymentsClient
    from .resources.patient_refunds.client import AsyncPatientRefundsClient, PatientRefundsClient
    from .resources.payer_plan_groups.client import AsyncPayerPlanGroupsClient, PayerPlanGroupsClient
    from .resources.payers.client import AsyncPayersClient, PayersClient
    from .resources.pre_encounter.client import AsyncPreEncounterClient, PreEncounterClient
    from .resources.service_lines.client import AsyncServiceLinesClient, ServiceLinesClient
    from .resources.superbills.client import AsyncSuperbillsClient, SuperbillsClient
    from .resources.tasks.client import AsyncTasksClient, TasksClient
    from .resources.write_offs.client import AsyncWriteOffsClient, WriteOffsClient


class CandidApiClient:
    """
    Use this class to access the different functions within the SDK. You can instantiate any number of clients with different configuration that will propagate to these functions.

    Parameters
    ----------

    client_id : str
        The client identifier used for authentication.

    client_secret : str
        The client secret used for authentication.

    timeout : typing.Optional[float]
        The timeout to be used, in seconds, for requests. By default the timeout is 60 seconds, unless a custom httpx client is used, in which case this default is not enforced.

    follow_redirects : typing.Optional[bool]
        Whether the default httpx client follows redirects or not, this is irrelevant if a custom httpx client is passed in.

    httpx_client : typing.Optional[httpx.Client]
        The httpx client to use for making requests, a preconfigured client is used by default, however this is useful should you want to pass in any custom httpx configuration.

    # or ...

    token : typing.Callable[[], str]
        Authenticate by providing a callable that returns a pre-generated bearer token. In this mode, OAuth client credentials are not required.

    timeout : typing.Optional[float]
        The timeout to be used, in seconds, for requests. By default the timeout is 60 seconds, unless a custom httpx client is used, in which case this default is not enforced.

    follow_redirects : typing.Optional[bool]
        Whether the default httpx client follows redirects or not, this is irrelevant if a custom httpx client is passed in.

    httpx_client : typing.Optional[httpx.Client]
        The httpx client to use for making requests, a preconfigured client is used by default, however this is useful should you want to pass in any custom httpx configuration.

    Examples
    --------
    from candid import CandidApiClient

    client = CandidApiClient(
        client_id="YOUR_CLIENT_ID",
        client_secret="YOUR_CLIENT_SECRET",
    )

    # or ...

    from candid import CandidApiClient

    client = CandidApiClient(
        base_url="https://yourhost.com/path/to/api",
        token="YOUR_BEARER_TOKEN",
    )
    """

    @typing.overload
    def __init__(
        self,
        *,
        environment: CandidApiClientEnvironment = CandidApiClientEnvironment.PRODUCTION,
        timeout: typing.Optional[float] = None,
        follow_redirects: typing.Optional[bool] = True,
        httpx_client: typing.Optional[httpx.Client] = None,
        client_id: str,
        client_secret: str,
    ): ...
    @typing.overload
    def __init__(
        self,
        *,
        environment: CandidApiClientEnvironment = CandidApiClientEnvironment.PRODUCTION,
        timeout: typing.Optional[float] = None,
        follow_redirects: typing.Optional[bool] = True,
        httpx_client: typing.Optional[httpx.Client] = None,
        token: typing.Callable[[], str],
    ): ...
    def __init__(
        self,
        *,
        environment: CandidApiClientEnvironment = CandidApiClientEnvironment.PRODUCTION,
        client_id: typing.Optional[str] = None,
        client_secret: typing.Optional[str] = None,
        token: typing.Optional[typing.Callable[[], str]] = None,
        _token_getter_override: typing.Optional[typing.Callable[[], str]] = None,
        timeout: typing.Optional[float] = None,
        follow_redirects: typing.Optional[bool] = True,
        httpx_client: typing.Optional[httpx.Client] = None,
    ):
        _defaulted_timeout = (
            timeout if timeout is not None else 60 if httpx_client is None else httpx_client.timeout.read
        )
        if token is not None:
            self._client_wrapper = SyncClientWrapper(
                environment=environment,
                httpx_client=httpx_client
                if httpx_client is not None
                else httpx.Client(timeout=_defaulted_timeout, follow_redirects=follow_redirects)
                if follow_redirects is not None
                else httpx.Client(timeout=_defaulted_timeout),
                timeout=_defaulted_timeout,
                token=_token_getter_override if _token_getter_override is not None else token,
            )
        elif client_id is not None and client_secret is not None:
            oauth_token_provider = OAuthTokenProvider(
                client_id=client_id,
                client_secret=client_secret,
                client_wrapper=SyncClientWrapper(
                    environment=environment,
                    httpx_client=httpx.Client(timeout=_defaulted_timeout, follow_redirects=follow_redirects)
                    if follow_redirects is not None
                    else httpx.Client(timeout=_defaulted_timeout),
                    timeout=_defaulted_timeout,
                ),
            )
            self._client_wrapper = SyncClientWrapper(
                environment=environment,
                token=_token_getter_override if _token_getter_override is not None else oauth_token_provider.get_token,
                httpx_client=httpx_client
                if httpx_client is not None
                else httpx.Client(timeout=_defaulted_timeout, follow_redirects=follow_redirects)
                if follow_redirects is not None
                else httpx.Client(timeout=_defaulted_timeout),
                timeout=_defaulted_timeout,
            )
        else:
            raise ApiError(
                body="The client must be instantiated with either 'token' or both 'client_id' and 'client_secret'"
            )
        self._auth: typing.Optional[AuthClient] = None
        self._billing_notes: typing.Optional[BillingNotesClient] = None
        self._charge_capture_bundles: typing.Optional[ChargeCaptureBundlesClient] = None
        self._charge_capture: typing.Optional[ChargeCaptureClient] = None
        self._contracts: typing.Optional[ContractsClient] = None
        self._credentialing: typing.Optional[CredentialingClient] = None
        self._custom_schemas: typing.Optional[CustomSchemasClient] = None
        self._eligibility: typing.Optional[EligibilityClient] = None
        self._encounter_attachments: typing.Optional[EncounterAttachmentsClient] = None
        self._encounter_providers: typing.Optional[EncounterProvidersClient] = None
        self._encounter_supplemental_information: typing.Optional[EncounterSupplementalInformationClient] = None
        self._encounters: typing.Optional[EncountersClient] = None
        self._events: typing.Optional[EventsClient] = None
        self._exports: typing.Optional[ExportsClient] = None
        self._external_payment_account_config: typing.Optional[ExternalPaymentAccountConfigClient] = None
        self._fee_schedules: typing.Optional[FeeSchedulesClient] = None
        self._guarantor: typing.Optional[GuarantorClient] = None
        self._health_care_code_information: typing.Optional[HealthCareCodeInformationClient] = None
        self._import_invoice: typing.Optional[ImportInvoiceClient] = None
        self._insurance_adjudications: typing.Optional[InsuranceAdjudicationsClient] = None
        self._insurance_refunds: typing.Optional[InsuranceRefundsClient] = None
        self._medication_dispense: typing.Optional[MedicationDispenseClient] = None
        self._non_insurance_payer_payments: typing.Optional[NonInsurancePayerPaymentsClient] = None
        self._non_insurance_payer_refunds: typing.Optional[NonInsurancePayerRefundsClient] = None
        self._non_insurance_payers: typing.Optional[NonInsurancePayersClient] = None
        self._organization_providers: typing.Optional[OrganizationProvidersClient] = None
        self._organization_service_facilities: typing.Optional[OrganizationServiceFacilitiesClient] = None
        self._patient_ar: typing.Optional[PatientArClient] = None
        self._patient_payments: typing.Optional[PatientPaymentsClient] = None
        self._patient_refunds: typing.Optional[PatientRefundsClient] = None
        self._payer_plan_groups: typing.Optional[PayerPlanGroupsClient] = None
        self._payers: typing.Optional[PayersClient] = None
        self._service_lines: typing.Optional[ServiceLinesClient] = None
        self._superbills: typing.Optional[SuperbillsClient] = None
        self._tasks: typing.Optional[TasksClient] = None
        self._write_offs: typing.Optional[WriteOffsClient] = None
        self._pre_encounter: typing.Optional[PreEncounterClient] = None
        self._diagnoses: typing.Optional[DiagnosesClient] = None

    @property
    def auth(self):
        if self._auth is None:
            from .resources.auth.client import AuthClient  # noqa: E402

            self._auth = AuthClient(client_wrapper=self._client_wrapper)
        return self._auth

    @property
    def billing_notes(self):
        if self._billing_notes is None:
            from .resources.billing_notes.client import BillingNotesClient  # noqa: E402

            self._billing_notes = BillingNotesClient(client_wrapper=self._client_wrapper)
        return self._billing_notes

    @property
    def charge_capture_bundles(self):
        if self._charge_capture_bundles is None:
            from .resources.charge_capture_bundles.client import ChargeCaptureBundlesClient  # noqa: E402

            self._charge_capture_bundles = ChargeCaptureBundlesClient(client_wrapper=self._client_wrapper)
        return self._charge_capture_bundles

    @property
    def charge_capture(self):
        if self._charge_capture is None:
            from .resources.charge_capture.client import ChargeCaptureClient  # noqa: E402

            self._charge_capture = ChargeCaptureClient(client_wrapper=self._client_wrapper)
        return self._charge_capture

    @property
    def contracts(self):
        if self._contracts is None:
            from .resources.contracts.client import ContractsClient  # noqa: E402

            self._contracts = ContractsClient(client_wrapper=self._client_wrapper)
        return self._contracts

    @property
    def credentialing(self):
        if self._credentialing is None:
            from .resources.credentialing.client import CredentialingClient  # noqa: E402

            self._credentialing = CredentialingClient(client_wrapper=self._client_wrapper)
        return self._credentialing

    @property
    def custom_schemas(self):
        if self._custom_schemas is None:
            from .resources.custom_schemas.client import CustomSchemasClient  # noqa: E402

            self._custom_schemas = CustomSchemasClient(client_wrapper=self._client_wrapper)
        return self._custom_schemas

    @property
    def eligibility(self):
        if self._eligibility is None:
            from .resources.eligibility.client import EligibilityClient  # noqa: E402

            self._eligibility = EligibilityClient(client_wrapper=self._client_wrapper)
        return self._eligibility

    @property
    def encounter_attachments(self):
        if self._encounter_attachments is None:
            from .resources.encounter_attachments.client import EncounterAttachmentsClient  # noqa: E402

            self._encounter_attachments = EncounterAttachmentsClient(client_wrapper=self._client_wrapper)
        return self._encounter_attachments

    @property
    def encounter_providers(self):
        if self._encounter_providers is None:
            from .resources.encounter_providers.client import EncounterProvidersClient  # noqa: E402

            self._encounter_providers = EncounterProvidersClient(client_wrapper=self._client_wrapper)
        return self._encounter_providers

    @property
    def encounter_supplemental_information(self):
        if self._encounter_supplemental_information is None:
            from .resources.encounter_supplemental_information.client import (
                EncounterSupplementalInformationClient,  # noqa: E402
            )

            self._encounter_supplemental_information = EncounterSupplementalInformationClient(
                client_wrapper=self._client_wrapper
            )
        return self._encounter_supplemental_information

    @property
    def encounters(self):
        if self._encounters is None:
            from .resources.encounters.client import EncountersClient  # noqa: E402

            self._encounters = EncountersClient(client_wrapper=self._client_wrapper)
        return self._encounters

    @property
    def events(self):
        if self._events is None:
            from .resources.events.client import EventsClient  # noqa: E402

            self._events = EventsClient(client_wrapper=self._client_wrapper)
        return self._events

    @property
    def exports(self):
        if self._exports is None:
            from .resources.exports.client import ExportsClient  # noqa: E402

            self._exports = ExportsClient(client_wrapper=self._client_wrapper)
        return self._exports

    @property
    def external_payment_account_config(self):
        if self._external_payment_account_config is None:
            from .resources.external_payment_account_config.client import (
                ExternalPaymentAccountConfigClient,  # noqa: E402
            )

            self._external_payment_account_config = ExternalPaymentAccountConfigClient(
                client_wrapper=self._client_wrapper
            )
        return self._external_payment_account_config

    @property
    def fee_schedules(self):
        if self._fee_schedules is None:
            from .resources.fee_schedules.client import FeeSchedulesClient  # noqa: E402

            self._fee_schedules = FeeSchedulesClient(client_wrapper=self._client_wrapper)
        return self._fee_schedules

    @property
    def guarantor(self):
        if self._guarantor is None:
            from .resources.guarantor.client import GuarantorClient  # noqa: E402

            self._guarantor = GuarantorClient(client_wrapper=self._client_wrapper)
        return self._guarantor

    @property
    def health_care_code_information(self):
        if self._health_care_code_information is None:
            from .resources.health_care_code_information.client import HealthCareCodeInformationClient  # noqa: E402

            self._health_care_code_information = HealthCareCodeInformationClient(client_wrapper=self._client_wrapper)
        return self._health_care_code_information

    @property
    def import_invoice(self):
        if self._import_invoice is None:
            from .resources.import_invoice.client import ImportInvoiceClient  # noqa: E402

            self._import_invoice = ImportInvoiceClient(client_wrapper=self._client_wrapper)
        return self._import_invoice

    @property
    def insurance_adjudications(self):
        if self._insurance_adjudications is None:
            from .resources.insurance_adjudications.client import InsuranceAdjudicationsClient  # noqa: E402

            self._insurance_adjudications = InsuranceAdjudicationsClient(client_wrapper=self._client_wrapper)
        return self._insurance_adjudications

    @property
    def insurance_refunds(self):
        if self._insurance_refunds is None:
            from .resources.insurance_refunds.client import InsuranceRefundsClient  # noqa: E402

            self._insurance_refunds = InsuranceRefundsClient(client_wrapper=self._client_wrapper)
        return self._insurance_refunds

    @property
    def medication_dispense(self):
        if self._medication_dispense is None:
            from .resources.medication_dispense.client import MedicationDispenseClient  # noqa: E402

            self._medication_dispense = MedicationDispenseClient(client_wrapper=self._client_wrapper)
        return self._medication_dispense

    @property
    def non_insurance_payer_payments(self):
        if self._non_insurance_payer_payments is None:
            from .resources.non_insurance_payer_payments.client import NonInsurancePayerPaymentsClient  # noqa: E402

            self._non_insurance_payer_payments = NonInsurancePayerPaymentsClient(client_wrapper=self._client_wrapper)
        return self._non_insurance_payer_payments

    @property
    def non_insurance_payer_refunds(self):
        if self._non_insurance_payer_refunds is None:
            from .resources.non_insurance_payer_refunds.client import NonInsurancePayerRefundsClient  # noqa: E402

            self._non_insurance_payer_refunds = NonInsurancePayerRefundsClient(client_wrapper=self._client_wrapper)
        return self._non_insurance_payer_refunds

    @property
    def non_insurance_payers(self):
        if self._non_insurance_payers is None:
            from .resources.non_insurance_payers.client import NonInsurancePayersClient  # noqa: E402

            self._non_insurance_payers = NonInsurancePayersClient(client_wrapper=self._client_wrapper)
        return self._non_insurance_payers

    @property
    def organization_providers(self):
        if self._organization_providers is None:
            from .resources.organization_providers.client import OrganizationProvidersClient  # noqa: E402

            self._organization_providers = OrganizationProvidersClient(client_wrapper=self._client_wrapper)
        return self._organization_providers

    @property
    def organization_service_facilities(self):
        if self._organization_service_facilities is None:
            from .resources.organization_service_facilities.client import (
                OrganizationServiceFacilitiesClient,  # noqa: E402
            )

            self._organization_service_facilities = OrganizationServiceFacilitiesClient(
                client_wrapper=self._client_wrapper
            )
        return self._organization_service_facilities

    @property
    def patient_ar(self):
        if self._patient_ar is None:
            from .resources.patient_ar.client import PatientArClient  # noqa: E402

            self._patient_ar = PatientArClient(client_wrapper=self._client_wrapper)
        return self._patient_ar

    @property
    def patient_payments(self):
        if self._patient_payments is None:
            from .resources.patient_payments.client import PatientPaymentsClient  # noqa: E402

            self._patient_payments = PatientPaymentsClient(client_wrapper=self._client_wrapper)
        return self._patient_payments

    @property
    def patient_refunds(self):
        if self._patient_refunds is None:
            from .resources.patient_refunds.client import PatientRefundsClient  # noqa: E402

            self._patient_refunds = PatientRefundsClient(client_wrapper=self._client_wrapper)
        return self._patient_refunds

    @property
    def payer_plan_groups(self):
        if self._payer_plan_groups is None:
            from .resources.payer_plan_groups.client import PayerPlanGroupsClient  # noqa: E402

            self._payer_plan_groups = PayerPlanGroupsClient(client_wrapper=self._client_wrapper)
        return self._payer_plan_groups

    @property
    def payers(self):
        if self._payers is None:
            from .resources.payers.client import PayersClient  # noqa: E402

            self._payers = PayersClient(client_wrapper=self._client_wrapper)
        return self._payers

    @property
    def service_lines(self):
        if self._service_lines is None:
            from .resources.service_lines.client import ServiceLinesClient  # noqa: E402

            self._service_lines = ServiceLinesClient(client_wrapper=self._client_wrapper)
        return self._service_lines

    @property
    def superbills(self):
        if self._superbills is None:
            from .resources.superbills.client import SuperbillsClient  # noqa: E402

            self._superbills = SuperbillsClient(client_wrapper=self._client_wrapper)
        return self._superbills

    @property
    def tasks(self):
        if self._tasks is None:
            from .resources.tasks.client import TasksClient  # noqa: E402

            self._tasks = TasksClient(client_wrapper=self._client_wrapper)
        return self._tasks

    @property
    def write_offs(self):
        if self._write_offs is None:
            from .resources.write_offs.client import WriteOffsClient  # noqa: E402

            self._write_offs = WriteOffsClient(client_wrapper=self._client_wrapper)
        return self._write_offs

    @property
    def pre_encounter(self):
        if self._pre_encounter is None:
            from .resources.pre_encounter.client import PreEncounterClient  # noqa: E402

            self._pre_encounter = PreEncounterClient(client_wrapper=self._client_wrapper)
        return self._pre_encounter

    @property
    def diagnoses(self):
        if self._diagnoses is None:
            from .resources.diagnoses.client import DiagnosesClient  # noqa: E402

            self._diagnoses = DiagnosesClient(client_wrapper=self._client_wrapper)
        return self._diagnoses


class AsyncCandidApiClient:
    """
    Use this class to access the different functions within the SDK. You can instantiate any number of clients with different configuration that will propagate to these functions.

    Parameters
    ----------

    client_id : str
        The client identifier used for authentication.

    client_secret : str
        The client secret used for authentication.

    timeout : typing.Optional[float]
        The timeout to be used, in seconds, for requests. By default the timeout is 60 seconds, unless a custom httpx client is used, in which case this default is not enforced.

    follow_redirects : typing.Optional[bool]
        Whether the default httpx client follows redirects or not, this is irrelevant if a custom httpx client is passed in.

    httpx_client : typing.Optional[httpx.AsyncClient]
        The httpx client to use for making requests, a preconfigured client is used by default, however this is useful should you want to pass in any custom httpx configuration.

    # or ...

    token : typing.Callable[[], str]
        Authenticate by providing a callable that returns a pre-generated bearer token. In this mode, OAuth client credentials are not required.

    timeout : typing.Optional[float]
        The timeout to be used, in seconds, for requests. By default the timeout is 60 seconds, unless a custom httpx client is used, in which case this default is not enforced.

    follow_redirects : typing.Optional[bool]
        Whether the default httpx client follows redirects or not, this is irrelevant if a custom httpx client is passed in.

    httpx_client : typing.Optional[httpx.AsyncClient]
        The httpx client to use for making requests, a preconfigured client is used by default, however this is useful should you want to pass in any custom httpx configuration.

    Examples
    --------
    from candid import AsyncCandidApiClient

    client = AsyncCandidApiClient(
        client_id="YOUR_CLIENT_ID",
        client_secret="YOUR_CLIENT_SECRET",
    )

    # or ...

    from candid import AsyncCandidApiClient

    client = AsyncCandidApiClient(
        base_url="https://yourhost.com/path/to/api",
        token="YOUR_BEARER_TOKEN",
    )
    """

    @typing.overload
    def __init__(
        self,
        *,
        environment: CandidApiClientEnvironment = CandidApiClientEnvironment.PRODUCTION,
        timeout: typing.Optional[float] = None,
        follow_redirects: typing.Optional[bool] = True,
        httpx_client: typing.Optional[httpx.AsyncClient] = None,
        client_id: str,
        client_secret: str,
    ): ...
    @typing.overload
    def __init__(
        self,
        *,
        environment: CandidApiClientEnvironment = CandidApiClientEnvironment.PRODUCTION,
        timeout: typing.Optional[float] = None,
        follow_redirects: typing.Optional[bool] = True,
        httpx_client: typing.Optional[httpx.AsyncClient] = None,
        token: typing.Callable[[], str],
    ): ...
    def __init__(
        self,
        *,
        environment: CandidApiClientEnvironment = CandidApiClientEnvironment.PRODUCTION,
        client_id: typing.Optional[str] = None,
        client_secret: typing.Optional[str] = None,
        token: typing.Optional[typing.Callable[[], str]] = None,
        _token_getter_override: typing.Optional[typing.Callable[[], str]] = None,
        timeout: typing.Optional[float] = None,
        follow_redirects: typing.Optional[bool] = True,
        httpx_client: typing.Optional[httpx.AsyncClient] = None,
    ):
        _defaulted_timeout = (
            timeout if timeout is not None else 60 if httpx_client is None else httpx_client.timeout.read
        )
        if token is not None:
            self._client_wrapper = AsyncClientWrapper(
                environment=environment,
                httpx_client=httpx_client
                if httpx_client is not None
                else httpx.AsyncClient(timeout=_defaulted_timeout, follow_redirects=follow_redirects)
                if follow_redirects is not None
                else httpx.AsyncClient(timeout=_defaulted_timeout),
                timeout=_defaulted_timeout,
                token=_token_getter_override if _token_getter_override is not None else token,
            )
        elif client_id is not None and client_secret is not None:
            oauth_token_provider = AsyncOAuthTokenProvider(
                client_id=client_id,
                client_secret=client_secret,
                client_wrapper=AsyncClientWrapper(
                    environment=environment,
                    httpx_client=httpx.AsyncClient(timeout=_defaulted_timeout, follow_redirects=follow_redirects)
                    if follow_redirects is not None
                    else httpx.AsyncClient(timeout=_defaulted_timeout),
                    timeout=_defaulted_timeout,
                ),
            )
            self._client_wrapper = AsyncClientWrapper(
                environment=environment,
                token=_token_getter_override,
                async_token=oauth_token_provider.get_token,
                httpx_client=httpx_client
                if httpx_client is not None
                else httpx.AsyncClient(timeout=_defaulted_timeout, follow_redirects=follow_redirects)
                if follow_redirects is not None
                else httpx.AsyncClient(timeout=_defaulted_timeout),
                timeout=_defaulted_timeout,
            )
        else:
            raise ApiError(
                body="The client must be instantiated with either 'token' or both 'client_id' and 'client_secret'"
            )
        self._auth: typing.Optional[AsyncAuthClient] = None
        self._billing_notes: typing.Optional[AsyncBillingNotesClient] = None
        self._charge_capture_bundles: typing.Optional[AsyncChargeCaptureBundlesClient] = None
        self._charge_capture: typing.Optional[AsyncChargeCaptureClient] = None
        self._contracts: typing.Optional[AsyncContractsClient] = None
        self._credentialing: typing.Optional[AsyncCredentialingClient] = None
        self._custom_schemas: typing.Optional[AsyncCustomSchemasClient] = None
        self._eligibility: typing.Optional[AsyncEligibilityClient] = None
        self._encounter_attachments: typing.Optional[AsyncEncounterAttachmentsClient] = None
        self._encounter_providers: typing.Optional[AsyncEncounterProvidersClient] = None
        self._encounter_supplemental_information: typing.Optional[AsyncEncounterSupplementalInformationClient] = None
        self._encounters: typing.Optional[AsyncEncountersClient] = None
        self._events: typing.Optional[AsyncEventsClient] = None
        self._exports: typing.Optional[AsyncExportsClient] = None
        self._external_payment_account_config: typing.Optional[AsyncExternalPaymentAccountConfigClient] = None
        self._fee_schedules: typing.Optional[AsyncFeeSchedulesClient] = None
        self._guarantor: typing.Optional[AsyncGuarantorClient] = None
        self._health_care_code_information: typing.Optional[AsyncHealthCareCodeInformationClient] = None
        self._import_invoice: typing.Optional[AsyncImportInvoiceClient] = None
        self._insurance_adjudications: typing.Optional[AsyncInsuranceAdjudicationsClient] = None
        self._insurance_refunds: typing.Optional[AsyncInsuranceRefundsClient] = None
        self._medication_dispense: typing.Optional[AsyncMedicationDispenseClient] = None
        self._non_insurance_payer_payments: typing.Optional[AsyncNonInsurancePayerPaymentsClient] = None
        self._non_insurance_payer_refunds: typing.Optional[AsyncNonInsurancePayerRefundsClient] = None
        self._non_insurance_payers: typing.Optional[AsyncNonInsurancePayersClient] = None
        self._organization_providers: typing.Optional[AsyncOrganizationProvidersClient] = None
        self._organization_service_facilities: typing.Optional[AsyncOrganizationServiceFacilitiesClient] = None
        self._patient_ar: typing.Optional[AsyncPatientArClient] = None
        self._patient_payments: typing.Optional[AsyncPatientPaymentsClient] = None
        self._patient_refunds: typing.Optional[AsyncPatientRefundsClient] = None
        self._payer_plan_groups: typing.Optional[AsyncPayerPlanGroupsClient] = None
        self._payers: typing.Optional[AsyncPayersClient] = None
        self._service_lines: typing.Optional[AsyncServiceLinesClient] = None
        self._superbills: typing.Optional[AsyncSuperbillsClient] = None
        self._tasks: typing.Optional[AsyncTasksClient] = None
        self._write_offs: typing.Optional[AsyncWriteOffsClient] = None
        self._pre_encounter: typing.Optional[AsyncPreEncounterClient] = None
        self._diagnoses: typing.Optional[AsyncDiagnosesClient] = None

    @property
    def auth(self):
        if self._auth is None:
            from .resources.auth.client import AsyncAuthClient  # noqa: E402

            self._auth = AsyncAuthClient(client_wrapper=self._client_wrapper)
        return self._auth

    @property
    def billing_notes(self):
        if self._billing_notes is None:
            from .resources.billing_notes.client import AsyncBillingNotesClient  # noqa: E402

            self._billing_notes = AsyncBillingNotesClient(client_wrapper=self._client_wrapper)
        return self._billing_notes

    @property
    def charge_capture_bundles(self):
        if self._charge_capture_bundles is None:
            from .resources.charge_capture_bundles.client import AsyncChargeCaptureBundlesClient  # noqa: E402

            self._charge_capture_bundles = AsyncChargeCaptureBundlesClient(client_wrapper=self._client_wrapper)
        return self._charge_capture_bundles

    @property
    def charge_capture(self):
        if self._charge_capture is None:
            from .resources.charge_capture.client import AsyncChargeCaptureClient  # noqa: E402

            self._charge_capture = AsyncChargeCaptureClient(client_wrapper=self._client_wrapper)
        return self._charge_capture

    @property
    def contracts(self):
        if self._contracts is None:
            from .resources.contracts.client import AsyncContractsClient  # noqa: E402

            self._contracts = AsyncContractsClient(client_wrapper=self._client_wrapper)
        return self._contracts

    @property
    def credentialing(self):
        if self._credentialing is None:
            from .resources.credentialing.client import AsyncCredentialingClient  # noqa: E402

            self._credentialing = AsyncCredentialingClient(client_wrapper=self._client_wrapper)
        return self._credentialing

    @property
    def custom_schemas(self):
        if self._custom_schemas is None:
            from .resources.custom_schemas.client import AsyncCustomSchemasClient  # noqa: E402

            self._custom_schemas = AsyncCustomSchemasClient(client_wrapper=self._client_wrapper)
        return self._custom_schemas

    @property
    def eligibility(self):
        if self._eligibility is None:
            from .resources.eligibility.client import AsyncEligibilityClient  # noqa: E402

            self._eligibility = AsyncEligibilityClient(client_wrapper=self._client_wrapper)
        return self._eligibility

    @property
    def encounter_attachments(self):
        if self._encounter_attachments is None:
            from .resources.encounter_attachments.client import AsyncEncounterAttachmentsClient  # noqa: E402

            self._encounter_attachments = AsyncEncounterAttachmentsClient(client_wrapper=self._client_wrapper)
        return self._encounter_attachments

    @property
    def encounter_providers(self):
        if self._encounter_providers is None:
            from .resources.encounter_providers.client import AsyncEncounterProvidersClient  # noqa: E402

            self._encounter_providers = AsyncEncounterProvidersClient(client_wrapper=self._client_wrapper)
        return self._encounter_providers

    @property
    def encounter_supplemental_information(self):
        if self._encounter_supplemental_information is None:
            from .resources.encounter_supplemental_information.client import (
                AsyncEncounterSupplementalInformationClient,  # noqa: E402
            )

            self._encounter_supplemental_information = AsyncEncounterSupplementalInformationClient(
                client_wrapper=self._client_wrapper
            )
        return self._encounter_supplemental_information

    @property
    def encounters(self):
        if self._encounters is None:
            from .resources.encounters.client import AsyncEncountersClient  # noqa: E402

            self._encounters = AsyncEncountersClient(client_wrapper=self._client_wrapper)
        return self._encounters

    @property
    def events(self):
        if self._events is None:
            from .resources.events.client import AsyncEventsClient  # noqa: E402

            self._events = AsyncEventsClient(client_wrapper=self._client_wrapper)
        return self._events

    @property
    def exports(self):
        if self._exports is None:
            from .resources.exports.client import AsyncExportsClient  # noqa: E402

            self._exports = AsyncExportsClient(client_wrapper=self._client_wrapper)
        return self._exports

    @property
    def external_payment_account_config(self):
        if self._external_payment_account_config is None:
            from .resources.external_payment_account_config.client import (
                AsyncExternalPaymentAccountConfigClient,  # noqa: E402
            )

            self._external_payment_account_config = AsyncExternalPaymentAccountConfigClient(
                client_wrapper=self._client_wrapper
            )
        return self._external_payment_account_config

    @property
    def fee_schedules(self):
        if self._fee_schedules is None:
            from .resources.fee_schedules.client import AsyncFeeSchedulesClient  # noqa: E402

            self._fee_schedules = AsyncFeeSchedulesClient(client_wrapper=self._client_wrapper)
        return self._fee_schedules

    @property
    def guarantor(self):
        if self._guarantor is None:
            from .resources.guarantor.client import AsyncGuarantorClient  # noqa: E402

            self._guarantor = AsyncGuarantorClient(client_wrapper=self._client_wrapper)
        return self._guarantor

    @property
    def health_care_code_information(self):
        if self._health_care_code_information is None:
            from .resources.health_care_code_information.client import (
                AsyncHealthCareCodeInformationClient,  # noqa: E402
            )

            self._health_care_code_information = AsyncHealthCareCodeInformationClient(
                client_wrapper=self._client_wrapper
            )
        return self._health_care_code_information

    @property
    def import_invoice(self):
        if self._import_invoice is None:
            from .resources.import_invoice.client import AsyncImportInvoiceClient  # noqa: E402

            self._import_invoice = AsyncImportInvoiceClient(client_wrapper=self._client_wrapper)
        return self._import_invoice

    @property
    def insurance_adjudications(self):
        if self._insurance_adjudications is None:
            from .resources.insurance_adjudications.client import AsyncInsuranceAdjudicationsClient  # noqa: E402

            self._insurance_adjudications = AsyncInsuranceAdjudicationsClient(client_wrapper=self._client_wrapper)
        return self._insurance_adjudications

    @property
    def insurance_refunds(self):
        if self._insurance_refunds is None:
            from .resources.insurance_refunds.client import AsyncInsuranceRefundsClient  # noqa: E402

            self._insurance_refunds = AsyncInsuranceRefundsClient(client_wrapper=self._client_wrapper)
        return self._insurance_refunds

    @property
    def medication_dispense(self):
        if self._medication_dispense is None:
            from .resources.medication_dispense.client import AsyncMedicationDispenseClient  # noqa: E402

            self._medication_dispense = AsyncMedicationDispenseClient(client_wrapper=self._client_wrapper)
        return self._medication_dispense

    @property
    def non_insurance_payer_payments(self):
        if self._non_insurance_payer_payments is None:
            from .resources.non_insurance_payer_payments.client import (
                AsyncNonInsurancePayerPaymentsClient,  # noqa: E402
            )

            self._non_insurance_payer_payments = AsyncNonInsurancePayerPaymentsClient(
                client_wrapper=self._client_wrapper
            )
        return self._non_insurance_payer_payments

    @property
    def non_insurance_payer_refunds(self):
        if self._non_insurance_payer_refunds is None:
            from .resources.non_insurance_payer_refunds.client import AsyncNonInsurancePayerRefundsClient  # noqa: E402

            self._non_insurance_payer_refunds = AsyncNonInsurancePayerRefundsClient(client_wrapper=self._client_wrapper)
        return self._non_insurance_payer_refunds

    @property
    def non_insurance_payers(self):
        if self._non_insurance_payers is None:
            from .resources.non_insurance_payers.client import AsyncNonInsurancePayersClient  # noqa: E402

            self._non_insurance_payers = AsyncNonInsurancePayersClient(client_wrapper=self._client_wrapper)
        return self._non_insurance_payers

    @property
    def organization_providers(self):
        if self._organization_providers is None:
            from .resources.organization_providers.client import AsyncOrganizationProvidersClient  # noqa: E402

            self._organization_providers = AsyncOrganizationProvidersClient(client_wrapper=self._client_wrapper)
        return self._organization_providers

    @property
    def organization_service_facilities(self):
        if self._organization_service_facilities is None:
            from .resources.organization_service_facilities.client import (
                AsyncOrganizationServiceFacilitiesClient,  # noqa: E402
            )

            self._organization_service_facilities = AsyncOrganizationServiceFacilitiesClient(
                client_wrapper=self._client_wrapper
            )
        return self._organization_service_facilities

    @property
    def patient_ar(self):
        if self._patient_ar is None:
            from .resources.patient_ar.client import AsyncPatientArClient  # noqa: E402

            self._patient_ar = AsyncPatientArClient(client_wrapper=self._client_wrapper)
        return self._patient_ar

    @property
    def patient_payments(self):
        if self._patient_payments is None:
            from .resources.patient_payments.client import AsyncPatientPaymentsClient  # noqa: E402

            self._patient_payments = AsyncPatientPaymentsClient(client_wrapper=self._client_wrapper)
        return self._patient_payments

    @property
    def patient_refunds(self):
        if self._patient_refunds is None:
            from .resources.patient_refunds.client import AsyncPatientRefundsClient  # noqa: E402

            self._patient_refunds = AsyncPatientRefundsClient(client_wrapper=self._client_wrapper)
        return self._patient_refunds

    @property
    def payer_plan_groups(self):
        if self._payer_plan_groups is None:
            from .resources.payer_plan_groups.client import AsyncPayerPlanGroupsClient  # noqa: E402

            self._payer_plan_groups = AsyncPayerPlanGroupsClient(client_wrapper=self._client_wrapper)
        return self._payer_plan_groups

    @property
    def payers(self):
        if self._payers is None:
            from .resources.payers.client import AsyncPayersClient  # noqa: E402

            self._payers = AsyncPayersClient(client_wrapper=self._client_wrapper)
        return self._payers

    @property
    def service_lines(self):
        if self._service_lines is None:
            from .resources.service_lines.client import AsyncServiceLinesClient  # noqa: E402

            self._service_lines = AsyncServiceLinesClient(client_wrapper=self._client_wrapper)
        return self._service_lines

    @property
    def superbills(self):
        if self._superbills is None:
            from .resources.superbills.client import AsyncSuperbillsClient  # noqa: E402

            self._superbills = AsyncSuperbillsClient(client_wrapper=self._client_wrapper)
        return self._superbills

    @property
    def tasks(self):
        if self._tasks is None:
            from .resources.tasks.client import AsyncTasksClient  # noqa: E402

            self._tasks = AsyncTasksClient(client_wrapper=self._client_wrapper)
        return self._tasks

    @property
    def write_offs(self):
        if self._write_offs is None:
            from .resources.write_offs.client import AsyncWriteOffsClient  # noqa: E402

            self._write_offs = AsyncWriteOffsClient(client_wrapper=self._client_wrapper)
        return self._write_offs

    @property
    def pre_encounter(self):
        if self._pre_encounter is None:
            from .resources.pre_encounter.client import AsyncPreEncounterClient  # noqa: E402

            self._pre_encounter = AsyncPreEncounterClient(client_wrapper=self._client_wrapper)
        return self._pre_encounter

    @property
    def diagnoses(self):
        if self._diagnoses is None:
            from .resources.diagnoses.client import AsyncDiagnosesClient  # noqa: E402

            self._diagnoses = AsyncDiagnosesClient(client_wrapper=self._client_wrapper)
        return self._diagnoses
