diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 6eb00725..dd939620 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -3,7 +3,7 @@ FROM mcr.microsoft.com/vscode/devcontainers/python:0-${VARIANT} USER vscode -RUN curl -sSf https://rye-up.com/get | RYE_VERSION="0.15.2" RYE_INSTALL_OPTION="--yes" bash +RUN curl -sSf https://rye-up.com/get | RYE_VERSION="0.24.0" RYE_INSTALL_OPTION="--yes" bash ENV PATH=/home/vscode/.rye/shims:$PATH RUN echo "[[ -d .venv ]] && source .venv/bin/activate" >> /home/vscode/.bashrc diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6ff0071b..a8ceec3c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: curl -sSf https://rye-up.com/get | bash echo "$HOME/.rye/shims" >> $GITHUB_PATH env: - RYE_VERSION: 0.15.2 + RYE_VERSION: 0.24.0 RYE_INSTALL_OPTION: "--yes" - name: Install dependencies diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml index 4cf6265e..6a3f9363 100644 --- a/.github/workflows/publish-pypi.yml +++ b/.github/workflows/publish-pypi.yml @@ -21,7 +21,7 @@ jobs: curl -sSf https://rye-up.com/get | bash echo "$HOME/.rye/shims" >> $GITHUB_PATH env: - RYE_VERSION: 0.15.2 + RYE_VERSION: 0.24.0 RYE_INSTALL_OPTION: "--yes" - name: Publish to PyPI diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 157f0355..51acdaa4 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.36.0" + ".": "0.37.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 703116df..7662c60d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1 +1 @@ -configured_endpoints: 108 +configured_endpoints: 110 diff --git a/CHANGELOG.md b/CHANGELOG.md index aee2b930..5a4eece9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## 0.37.0 (2024-02-21) + +Full Changelog: [v0.36.0...v0.37.0](https://github.com/lithic-com/lithic-python/compare/v0.36.0...v0.37.0) + +### Features + +* **api:** create financial account and retry microdeposits endpoints ([#366](https://github.com/lithic-com/lithic-python/issues/366)) ([4cc06ec](https://github.com/lithic-com/lithic-python/commit/4cc06eca313e87524174d9b6af615e36c8f5c8dd)) + + +### Chores + +* **internal:** bump rye to v0.24.0 ([#364](https://github.com/lithic-com/lithic-python/issues/364)) ([ef3b396](https://github.com/lithic-com/lithic-python/commit/ef3b396cfb9f58894506514e889d78168a246489)) + ## 0.36.0 (2024-02-19) Full Changelog: [v0.35.0...v0.36.0](https://github.com/lithic-com/lithic-python/compare/v0.35.0...v0.36.0) diff --git a/api.md b/api.md index 47207417..49fc4d95 100644 --- a/api.md +++ b/api.md @@ -268,6 +268,7 @@ from lithic.types import FinancialAccount, FinancialTransaction Methods: +- client.financial_accounts.create(\*\*params) -> FinancialAccount - client.financial_accounts.retrieve(financial_account_token) -> FinancialAccount - client.financial_accounts.update(financial_account_token, \*\*params) -> FinancialAccount - client.financial_accounts.list(\*\*params) -> SyncSinglePage[FinancialAccount] @@ -373,6 +374,7 @@ from lithic.types import ( ExternalBankAccountRetrieveResponse, ExternalBankAccountUpdateResponse, ExternalBankAccountListResponse, + ExternalBankAccountRetryMicroDepositsResponse, ) ``` @@ -382,6 +384,7 @@ Methods: - client.external_bank_accounts.retrieve(external_bank_account_token) -> ExternalBankAccountRetrieveResponse - client.external_bank_accounts.update(external_bank_account_token, \*\*params) -> ExternalBankAccountUpdateResponse - client.external_bank_accounts.list(\*\*params) -> SyncCursorPage[ExternalBankAccountListResponse] +- client.external_bank_accounts.retry_micro_deposits(external_bank_account_token) -> ExternalBankAccountRetryMicroDepositsResponse ## MicroDeposits diff --git a/pyproject.toml b/pyproject.toml index dce8043d..69593513 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "lithic" -version = "0.36.0" +version = "0.37.0" description = "The official Python library for the lithic API" readme = "README.md" license = "Apache-2.0" diff --git a/requirements-dev.lock b/requirements-dev.lock index a0134d65..ae6a7797 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -5,48 +5,92 @@ # pre: false # features: [] # all-features: true +# with-sources: false -e file:. annotated-types==0.6.0 + # via pydantic anyio==4.1.0 + # via httpx + # via lithic argcomplete==3.1.2 + # via nox attrs==23.1.0 + # via pytest certifi==2023.7.22 + # via httpcore + # via httpx colorlog==6.7.0 + # via nox dirty-equals==0.6.0 distlib==0.3.7 + # via virtualenv distro==1.8.0 + # via lithic exceptiongroup==1.1.3 + # via anyio filelock==3.12.4 + # via virtualenv h11==0.14.0 + # via httpcore httpcore==1.0.2 + # via httpx httpx==0.25.2 + # via lithic + # via respx idna==3.4 + # via anyio + # via httpx importlib-metadata==7.0.0 iniconfig==2.0.0 + # via pytest mypy==1.7.1 mypy-extensions==1.0.0 + # via mypy nodeenv==1.8.0 + # via pyright nox==2023.4.22 packaging==23.2 + # via nox + # via pytest platformdirs==3.11.0 + # via virtualenv pluggy==1.3.0 + # via pytest py==1.11.0 + # via pytest pydantic==2.4.2 + # via lithic pydantic-core==2.10.1 + # via pydantic pyright==1.1.332 pytest==7.1.1 + # via pytest-asyncio pytest-asyncio==0.21.1 python-dateutil==2.8.2 + # via time-machine pytz==2023.3.post1 + # via dirty-equals respx==0.20.2 ruff==0.1.9 +setuptools==68.2.2 + # via nodeenv six==1.16.0 + # via python-dateutil sniffio==1.3.0 + # via anyio + # via httpx + # via lithic time-machine==2.9.0 tomli==2.0.1 + # via mypy + # via pytest typing-extensions==4.8.0 + # via lithic + # via mypy + # via pydantic + # via pydantic-core virtualenv==20.24.5 + # via nox zipp==3.17.0 -# The following packages are considered to be unsafe in a requirements file: -setuptools==68.2.2 + # via importlib-metadata diff --git a/requirements.lock b/requirements.lock index 2022a5c5..7fbcaa73 100644 --- a/requirements.lock +++ b/requirements.lock @@ -5,18 +5,39 @@ # pre: false # features: [] # all-features: true +# with-sources: false -e file:. annotated-types==0.6.0 + # via pydantic anyio==4.1.0 + # via httpx + # via lithic certifi==2023.7.22 + # via httpcore + # via httpx distro==1.8.0 + # via lithic exceptiongroup==1.1.3 + # via anyio h11==0.14.0 + # via httpcore httpcore==1.0.2 + # via httpx httpx==0.25.2 + # via lithic idna==3.4 + # via anyio + # via httpx pydantic==2.4.2 + # via lithic pydantic-core==2.10.1 + # via pydantic sniffio==1.3.0 + # via anyio + # via httpx + # via lithic typing-extensions==4.8.0 + # via lithic + # via pydantic + # via pydantic-core diff --git a/src/lithic/_version.py b/src/lithic/_version.py index 2f118537..863fa494 100644 --- a/src/lithic/_version.py +++ b/src/lithic/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. __title__ = "lithic" -__version__ = "0.36.0" # x-release-please-version +__version__ = "0.37.0" # x-release-please-version diff --git a/src/lithic/resources/external_bank_accounts/external_bank_accounts.py b/src/lithic/resources/external_bank_accounts/external_bank_accounts.py index 4f365bfb..aa2580a3 100644 --- a/src/lithic/resources/external_bank_accounts/external_bank_accounts.py +++ b/src/lithic/resources/external_bank_accounts/external_bank_accounts.py @@ -17,6 +17,7 @@ ExternalBankAccountCreateResponse, ExternalBankAccountUpdateResponse, ExternalBankAccountRetrieveResponse, + ExternalBankAccountRetryMicroDepositsResponse, external_bank_account_list_params, external_bank_account_create_params, external_bank_account_update_params, @@ -320,7 +321,8 @@ def list( page_size: int | NotGiven = NOT_GIVEN, starting_after: str | NotGiven = NOT_GIVEN, states: List[Literal["CLOSED", "ENABLED", "PAUSED"]] | NotGiven = NOT_GIVEN, - verification_states: List[Literal["ENABLED", "FAILED_VERIFICATION", "PENDING"]] | NotGiven = NOT_GIVEN, + verification_states: List[Literal["ENABLED", "FAILED_VERIFICATION", "INSUFFICIENT_FUNDS", "PENDING"]] + | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -374,6 +376,41 @@ def list( model=ExternalBankAccountListResponse, ) + def retry_micro_deposits( + self, + external_bank_account_token: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> ExternalBankAccountRetryMicroDepositsResponse: + """ + Retry external bank account micro deposit verification. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not external_bank_account_token: + raise ValueError( + f"Expected a non-empty value for `external_bank_account_token` but received {external_bank_account_token!r}" + ) + return self._post( + f"/external_bank_accounts/{external_bank_account_token}/retry_micro_deposits", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ExternalBankAccountRetryMicroDepositsResponse, + ) + class AsyncExternalBankAccounts(AsyncAPIResource): @cached_property @@ -652,7 +689,8 @@ def list( page_size: int | NotGiven = NOT_GIVEN, starting_after: str | NotGiven = NOT_GIVEN, states: List[Literal["CLOSED", "ENABLED", "PAUSED"]] | NotGiven = NOT_GIVEN, - verification_states: List[Literal["ENABLED", "FAILED_VERIFICATION", "PENDING"]] | NotGiven = NOT_GIVEN, + verification_states: List[Literal["ENABLED", "FAILED_VERIFICATION", "INSUFFICIENT_FUNDS", "PENDING"]] + | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -706,6 +744,41 @@ def list( model=ExternalBankAccountListResponse, ) + async def retry_micro_deposits( + self, + external_bank_account_token: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> ExternalBankAccountRetryMicroDepositsResponse: + """ + Retry external bank account micro deposit verification. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not external_bank_account_token: + raise ValueError( + f"Expected a non-empty value for `external_bank_account_token` but received {external_bank_account_token!r}" + ) + return await self._post( + f"/external_bank_accounts/{external_bank_account_token}/retry_micro_deposits", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ExternalBankAccountRetryMicroDepositsResponse, + ) + class ExternalBankAccountsWithRawResponse: def __init__(self, external_bank_accounts: ExternalBankAccounts) -> None: @@ -723,6 +796,9 @@ def __init__(self, external_bank_accounts: ExternalBankAccounts) -> None: self.list = _legacy_response.to_raw_response_wrapper( external_bank_accounts.list, ) + self.retry_micro_deposits = _legacy_response.to_raw_response_wrapper( + external_bank_accounts.retry_micro_deposits, + ) @cached_property def micro_deposits(self) -> MicroDepositsWithRawResponse: @@ -745,6 +821,9 @@ def __init__(self, external_bank_accounts: AsyncExternalBankAccounts) -> None: self.list = _legacy_response.async_to_raw_response_wrapper( external_bank_accounts.list, ) + self.retry_micro_deposits = _legacy_response.async_to_raw_response_wrapper( + external_bank_accounts.retry_micro_deposits, + ) @cached_property def micro_deposits(self) -> AsyncMicroDepositsWithRawResponse: @@ -767,6 +846,9 @@ def __init__(self, external_bank_accounts: ExternalBankAccounts) -> None: self.list = to_streamed_response_wrapper( external_bank_accounts.list, ) + self.retry_micro_deposits = to_streamed_response_wrapper( + external_bank_accounts.retry_micro_deposits, + ) @cached_property def micro_deposits(self) -> MicroDepositsWithStreamingResponse: @@ -789,6 +871,9 @@ def __init__(self, external_bank_accounts: AsyncExternalBankAccounts) -> None: self.list = async_to_streamed_response_wrapper( external_bank_accounts.list, ) + self.retry_micro_deposits = async_to_streamed_response_wrapper( + external_bank_accounts.retry_micro_deposits, + ) @cached_property def micro_deposits(self) -> AsyncMicroDepositsWithStreamingResponse: diff --git a/src/lithic/resources/financial_accounts/financial_accounts.py b/src/lithic/resources/financial_accounts/financial_accounts.py index 3b0d35af..6d29a6f9 100644 --- a/src/lithic/resources/financial_accounts/financial_accounts.py +++ b/src/lithic/resources/financial_accounts/financial_accounts.py @@ -7,7 +7,12 @@ import httpx from ... import _legacy_response -from ...types import FinancialAccount, financial_account_list_params, financial_account_update_params +from ...types import ( + FinancialAccount, + financial_account_list_params, + financial_account_create_params, + financial_account_update_params, +) from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven from ..._utils import maybe_transform from .balances import ( @@ -68,6 +73,47 @@ def with_raw_response(self) -> FinancialAccountsWithRawResponse: def with_streaming_response(self) -> FinancialAccountsWithStreamingResponse: return FinancialAccountsWithStreamingResponse(self) + def create( + self, + *, + nickname: str, + type: Literal["OPERATING"], + account_token: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> FinancialAccount: + """ + Create a new financial account + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._post( + "/financial_accounts", + body=maybe_transform( + { + "nickname": nickname, + "type": type, + "account_token": account_token, + }, + financial_account_create_params.FinancialAccountCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=FinancialAccount, + ) + def retrieve( self, financial_account_token: str, @@ -214,6 +260,47 @@ def with_raw_response(self) -> AsyncFinancialAccountsWithRawResponse: def with_streaming_response(self) -> AsyncFinancialAccountsWithStreamingResponse: return AsyncFinancialAccountsWithStreamingResponse(self) + async def create( + self, + *, + nickname: str, + type: Literal["OPERATING"], + account_token: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> FinancialAccount: + """ + Create a new financial account + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._post( + "/financial_accounts", + body=maybe_transform( + { + "nickname": nickname, + "type": type, + "account_token": account_token, + }, + financial_account_create_params.FinancialAccountCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=FinancialAccount, + ) + async def retrieve( self, financial_account_token: str, @@ -343,6 +430,9 @@ class FinancialAccountsWithRawResponse: def __init__(self, financial_accounts: FinancialAccounts) -> None: self._financial_accounts = financial_accounts + self.create = _legacy_response.to_raw_response_wrapper( + financial_accounts.create, + ) self.retrieve = _legacy_response.to_raw_response_wrapper( financial_accounts.retrieve, ) @@ -370,6 +460,9 @@ class AsyncFinancialAccountsWithRawResponse: def __init__(self, financial_accounts: AsyncFinancialAccounts) -> None: self._financial_accounts = financial_accounts + self.create = _legacy_response.async_to_raw_response_wrapper( + financial_accounts.create, + ) self.retrieve = _legacy_response.async_to_raw_response_wrapper( financial_accounts.retrieve, ) @@ -397,6 +490,9 @@ class FinancialAccountsWithStreamingResponse: def __init__(self, financial_accounts: FinancialAccounts) -> None: self._financial_accounts = financial_accounts + self.create = to_streamed_response_wrapper( + financial_accounts.create, + ) self.retrieve = to_streamed_response_wrapper( financial_accounts.retrieve, ) @@ -424,6 +520,9 @@ class AsyncFinancialAccountsWithStreamingResponse: def __init__(self, financial_accounts: AsyncFinancialAccounts) -> None: self._financial_accounts = financial_accounts + self.create = async_to_streamed_response_wrapper( + financial_accounts.create, + ) self.retrieve = async_to_streamed_response_wrapper( financial_accounts.retrieve, ) diff --git a/src/lithic/types/__init__.py b/src/lithic/types/__init__.py index 32a2ed2f..28712475 100644 --- a/src/lithic/types/__init__.py +++ b/src/lithic/types/__init__.py @@ -83,6 +83,7 @@ from .account_holder_update_response import AccountHolderUpdateResponse as AccountHolderUpdateResponse from .payment_simulate_return_params import PaymentSimulateReturnParams as PaymentSimulateReturnParams from .tokenization_simulate_response import TokenizationSimulateResponse as TokenizationSimulateResponse +from .financial_account_create_params import FinancialAccountCreateParams as FinancialAccountCreateParams from .financial_account_update_params import FinancialAccountUpdateParams as FinancialAccountUpdateParams from .payment_simulate_release_params import PaymentSimulateReleaseParams as PaymentSimulateReleaseParams from .payment_simulate_return_response import PaymentSimulateReturnResponse as PaymentSimulateReturnResponse @@ -152,3 +153,6 @@ from .transaction_simulate_credit_authorization_response import ( TransactionSimulateCreditAuthorizationResponse as TransactionSimulateCreditAuthorizationResponse, ) +from .external_bank_account_retry_micro_deposits_response import ( + ExternalBankAccountRetryMicroDepositsResponse as ExternalBankAccountRetryMicroDepositsResponse, +) diff --git a/src/lithic/types/external_bank_account_create_response.py b/src/lithic/types/external_bank_account_create_response.py index 17109878..593fd169 100644 --- a/src/lithic/types/external_bank_account_create_response.py +++ b/src/lithic/types/external_bank_account_create_response.py @@ -57,9 +57,9 @@ class ExternalBankAccountCreateResponse(BaseModel): verification_attempts: int """The number of attempts at verification""" - verification_method: Literal["MANUAL", "MICRO_DEPOSIT", "PLAID"] + verification_method: Literal["MANUAL", "MICRO_DEPOSIT", "PLAID", "PRENOTE"] - verification_state: Literal["ENABLED", "FAILED_VERIFICATION", "PENDING"] + verification_state: Literal["ENABLED", "FAILED_VERIFICATION", "INSUFFICIENT_FUNDS", "PENDING"] account_token: Optional[str] = None """Indicates which Lithic account the external account is associated with. diff --git a/src/lithic/types/external_bank_account_list_params.py b/src/lithic/types/external_bank_account_list_params.py index a35d981c..561b6808 100644 --- a/src/lithic/types/external_bank_account_list_params.py +++ b/src/lithic/types/external_bank_account_list_params.py @@ -37,4 +37,4 @@ class ExternalBankAccountListParams(TypedDict, total=False): states: List[Literal["CLOSED", "ENABLED", "PAUSED"]] - verification_states: List[Literal["ENABLED", "FAILED_VERIFICATION", "PENDING"]] + verification_states: List[Literal["ENABLED", "FAILED_VERIFICATION", "INSUFFICIENT_FUNDS", "PENDING"]] diff --git a/src/lithic/types/external_bank_account_list_response.py b/src/lithic/types/external_bank_account_list_response.py index 2958f785..867b7937 100644 --- a/src/lithic/types/external_bank_account_list_response.py +++ b/src/lithic/types/external_bank_account_list_response.py @@ -57,9 +57,9 @@ class ExternalBankAccountListResponse(BaseModel): verification_attempts: int """The number of attempts at verification""" - verification_method: Literal["MANUAL", "MICRO_DEPOSIT", "PLAID"] + verification_method: Literal["MANUAL", "MICRO_DEPOSIT", "PLAID", "PRENOTE"] - verification_state: Literal["ENABLED", "FAILED_VERIFICATION", "PENDING"] + verification_state: Literal["ENABLED", "FAILED_VERIFICATION", "INSUFFICIENT_FUNDS", "PENDING"] account_token: Optional[str] = None """Indicates which Lithic account the external account is associated with. diff --git a/src/lithic/types/external_bank_account_retrieve_response.py b/src/lithic/types/external_bank_account_retrieve_response.py index 0ee274f3..7bb09881 100644 --- a/src/lithic/types/external_bank_account_retrieve_response.py +++ b/src/lithic/types/external_bank_account_retrieve_response.py @@ -57,9 +57,9 @@ class ExternalBankAccountRetrieveResponse(BaseModel): verification_attempts: int """The number of attempts at verification""" - verification_method: Literal["MANUAL", "MICRO_DEPOSIT", "PLAID"] + verification_method: Literal["MANUAL", "MICRO_DEPOSIT", "PLAID", "PRENOTE"] - verification_state: Literal["ENABLED", "FAILED_VERIFICATION", "PENDING"] + verification_state: Literal["ENABLED", "FAILED_VERIFICATION", "INSUFFICIENT_FUNDS", "PENDING"] account_token: Optional[str] = None """Indicates which Lithic account the external account is associated with. diff --git a/src/lithic/types/external_bank_account_retry_micro_deposits_response.py b/src/lithic/types/external_bank_account_retry_micro_deposits_response.py new file mode 100644 index 00000000..be343ea7 --- /dev/null +++ b/src/lithic/types/external_bank_account_retry_micro_deposits_response.py @@ -0,0 +1,95 @@ +# File generated from our OpenAPI spec by Stainless. + +from typing import Optional +from datetime import date, datetime +from typing_extensions import Literal + +from .._models import BaseModel +from .external_bank_account_address import ExternalBankAccountAddress + +__all__ = ["ExternalBankAccountRetryMicroDepositsResponse"] + + +class ExternalBankAccountRetryMicroDepositsResponse(BaseModel): + token: str + """ + A globally unique identifier for this record of an external bank account + association. If a program links an external bank account to more than one + end-user or to both the program and the end-user, then Lithic will return each + record of the association + """ + + country: str + """The country that the bank account is located in using ISO 3166-1. + + We will only accept USA bank accounts e.g., USA + """ + + created: datetime + """ + An ISO 8601 string representing when this funding source was added to the Lithic + account. + """ + + currency: str + """currency of the external account 3-digit alphabetic ISO 4217 code""" + + last_four: str + """The last 4 digits of the bank account. + + Derived by Lithic from the account number passed + """ + + owner: str + """Legal Name of the business or individual who owns the external account. + + This will appear in statements + """ + + owner_type: Literal["BUSINESS", "INDIVIDUAL"] + + routing_number: str + + state: Literal["CLOSED", "ENABLED", "PAUSED"] + + type: Literal["CHECKING", "SAVINGS"] + + verification_attempts: int + """The number of attempts at verification""" + + verification_method: Literal["MANUAL", "MICRO_DEPOSIT", "PLAID", "PRENOTE"] + + verification_state: Literal["ENABLED", "FAILED_VERIFICATION", "INSUFFICIENT_FUNDS", "PENDING"] + + account_token: Optional[str] = None + """Indicates which Lithic account the external account is associated with. + + For external accounts that are associated with the program, account_token field + returned will be null + """ + + address: Optional[ExternalBankAccountAddress] = None + """ + Address used during Address Verification Service (AVS) checks during + transactions if enabled via Auth Rules. + """ + + company_id: Optional[str] = None + """Optional field that helps identify bank accounts in receipts""" + + dob: Optional[date] = None + """Date of Birth of the Individual that owns the external bank account""" + + doing_business_as: Optional[str] = None + + name: Optional[str] = None + """The nickname given to this record of External Bank Account""" + + user_defined_id: Optional[str] = None + + verification_failed_reason: Optional[str] = None + """Optional free text description of the reason for the failed verification. + + For ACH micro-deposits returned, this field will display the reason return code + sent by the ACH network + """ diff --git a/src/lithic/types/external_bank_account_update_response.py b/src/lithic/types/external_bank_account_update_response.py index 782c5bf7..85d617fe 100644 --- a/src/lithic/types/external_bank_account_update_response.py +++ b/src/lithic/types/external_bank_account_update_response.py @@ -57,9 +57,9 @@ class ExternalBankAccountUpdateResponse(BaseModel): verification_attempts: int """The number of attempts at verification""" - verification_method: Literal["MANUAL", "MICRO_DEPOSIT", "PLAID"] + verification_method: Literal["MANUAL", "MICRO_DEPOSIT", "PLAID", "PRENOTE"] - verification_state: Literal["ENABLED", "FAILED_VERIFICATION", "PENDING"] + verification_state: Literal["ENABLED", "FAILED_VERIFICATION", "INSUFFICIENT_FUNDS", "PENDING"] account_token: Optional[str] = None """Indicates which Lithic account the external account is associated with. diff --git a/src/lithic/types/external_bank_accounts/micro_deposit_create_response.py b/src/lithic/types/external_bank_accounts/micro_deposit_create_response.py index ce3fe215..b101ce52 100644 --- a/src/lithic/types/external_bank_accounts/micro_deposit_create_response.py +++ b/src/lithic/types/external_bank_accounts/micro_deposit_create_response.py @@ -57,9 +57,9 @@ class MicroDepositCreateResponse(BaseModel): verification_attempts: int """The number of attempts at verification""" - verification_method: Literal["MANUAL", "MICRO_DEPOSIT", "PLAID"] + verification_method: Literal["MANUAL", "MICRO_DEPOSIT", "PLAID", "PRENOTE"] - verification_state: Literal["ENABLED", "FAILED_VERIFICATION", "PENDING"] + verification_state: Literal["ENABLED", "FAILED_VERIFICATION", "INSUFFICIENT_FUNDS", "PENDING"] account_token: Optional[str] = None """Indicates which Lithic account the external account is associated with. diff --git a/src/lithic/types/financial_account_create_params.py b/src/lithic/types/financial_account_create_params.py new file mode 100644 index 00000000..f854cb14 --- /dev/null +++ b/src/lithic/types/financial_account_create_params.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Stainless. + +from __future__ import annotations + +from typing_extensions import Literal, Required, TypedDict + +__all__ = ["FinancialAccountCreateParams"] + + +class FinancialAccountCreateParams(TypedDict, total=False): + nickname: Required[str] + + type: Required[Literal["OPERATING"]] + + account_token: str diff --git a/src/lithic/types/verification_method.py b/src/lithic/types/verification_method.py index 0787038a..9972e037 100644 --- a/src/lithic/types/verification_method.py +++ b/src/lithic/types/verification_method.py @@ -4,4 +4,4 @@ __all__ = ["VerificationMethod"] -VerificationMethod = Literal["MANUAL", "MICRO_DEPOSIT", "PLAID"] +VerificationMethod = Literal["MANUAL", "MICRO_DEPOSIT", "PLAID", "PRENOTE"] diff --git a/tests/api_resources/test_external_bank_accounts.py b/tests/api_resources/test_external_bank_accounts.py index 933ebd4d..45f0d235 100644 --- a/tests/api_resources/test_external_bank_accounts.py +++ b/tests/api_resources/test_external_bank_accounts.py @@ -14,6 +14,7 @@ ExternalBankAccountCreateResponse, ExternalBankAccountUpdateResponse, ExternalBankAccountRetrieveResponse, + ExternalBankAccountRetryMicroDepositsResponse, ) from lithic._utils import parse_date from lithic.pagination import SyncCursorPage, AsyncCursorPage @@ -278,7 +279,7 @@ def test_method_list_with_all_params(self, client: Lithic) -> None: page_size=1, starting_after="string", states=["CLOSED", "ENABLED", "PAUSED"], - verification_states=["ENABLED", "FAILED_VERIFICATION", "PENDING"], + verification_states=["ENABLED", "FAILED_VERIFICATION", "INSUFFICIENT_FUNDS"], ) assert_matches_type(SyncCursorPage[ExternalBankAccountListResponse], external_bank_account, path=["response"]) @@ -304,6 +305,46 @@ def test_streaming_response_list(self, client: Lithic) -> None: assert cast(Any, response.is_closed) is True + @parametrize + def test_method_retry_micro_deposits(self, client: Lithic) -> None: + external_bank_account = client.external_bank_accounts.retry_micro_deposits( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert_matches_type(ExternalBankAccountRetryMicroDepositsResponse, external_bank_account, path=["response"]) + + @parametrize + def test_raw_response_retry_micro_deposits(self, client: Lithic) -> None: + response = client.external_bank_accounts.with_raw_response.retry_micro_deposits( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + external_bank_account = response.parse() + assert_matches_type(ExternalBankAccountRetryMicroDepositsResponse, external_bank_account, path=["response"]) + + @parametrize + def test_streaming_response_retry_micro_deposits(self, client: Lithic) -> None: + with client.external_bank_accounts.with_streaming_response.retry_micro_deposits( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + external_bank_account = response.parse() + assert_matches_type(ExternalBankAccountRetryMicroDepositsResponse, external_bank_account, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_retry_micro_deposits(self, client: Lithic) -> None: + with pytest.raises( + ValueError, match=r"Expected a non-empty value for `external_bank_account_token` but received ''" + ): + client.external_bank_accounts.with_raw_response.retry_micro_deposits( + "", + ) + class TestAsyncExternalBankAccounts: parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) @@ -562,7 +603,7 @@ async def test_method_list_with_all_params(self, async_client: AsyncLithic) -> N page_size=1, starting_after="string", states=["CLOSED", "ENABLED", "PAUSED"], - verification_states=["ENABLED", "FAILED_VERIFICATION", "PENDING"], + verification_states=["ENABLED", "FAILED_VERIFICATION", "INSUFFICIENT_FUNDS"], ) assert_matches_type(AsyncCursorPage[ExternalBankAccountListResponse], external_bank_account, path=["response"]) @@ -587,3 +628,43 @@ async def test_streaming_response_list(self, async_client: AsyncLithic) -> None: ) assert cast(Any, response.is_closed) is True + + @parametrize + async def test_method_retry_micro_deposits(self, async_client: AsyncLithic) -> None: + external_bank_account = await async_client.external_bank_accounts.retry_micro_deposits( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert_matches_type(ExternalBankAccountRetryMicroDepositsResponse, external_bank_account, path=["response"]) + + @parametrize + async def test_raw_response_retry_micro_deposits(self, async_client: AsyncLithic) -> None: + response = await async_client.external_bank_accounts.with_raw_response.retry_micro_deposits( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + external_bank_account = response.parse() + assert_matches_type(ExternalBankAccountRetryMicroDepositsResponse, external_bank_account, path=["response"]) + + @parametrize + async def test_streaming_response_retry_micro_deposits(self, async_client: AsyncLithic) -> None: + async with async_client.external_bank_accounts.with_streaming_response.retry_micro_deposits( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + external_bank_account = await response.parse() + assert_matches_type(ExternalBankAccountRetryMicroDepositsResponse, external_bank_account, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_retry_micro_deposits(self, async_client: AsyncLithic) -> None: + with pytest.raises( + ValueError, match=r"Expected a non-empty value for `external_bank_account_token` but received ''" + ): + await async_client.external_bank_accounts.with_raw_response.retry_micro_deposits( + "", + ) diff --git a/tests/api_resources/test_financial_accounts.py b/tests/api_resources/test_financial_accounts.py index 6afe57c9..32d7e033 100644 --- a/tests/api_resources/test_financial_accounts.py +++ b/tests/api_resources/test_financial_accounts.py @@ -9,7 +9,9 @@ from lithic import Lithic, AsyncLithic from tests.utils import assert_matches_type -from lithic.types import FinancialAccount +from lithic.types import ( + FinancialAccount, +) from lithic.pagination import SyncSinglePage, AsyncSinglePage base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -18,6 +20,49 @@ class TestFinancialAccounts: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + @parametrize + def test_method_create(self, client: Lithic) -> None: + financial_account = client.financial_accounts.create( + nickname="string", + type="OPERATING", + ) + assert_matches_type(FinancialAccount, financial_account, path=["response"]) + + @parametrize + def test_method_create_with_all_params(self, client: Lithic) -> None: + financial_account = client.financial_accounts.create( + nickname="string", + type="OPERATING", + account_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert_matches_type(FinancialAccount, financial_account, path=["response"]) + + @parametrize + def test_raw_response_create(self, client: Lithic) -> None: + response = client.financial_accounts.with_raw_response.create( + nickname="string", + type="OPERATING", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + financial_account = response.parse() + assert_matches_type(FinancialAccount, financial_account, path=["response"]) + + @parametrize + def test_streaming_response_create(self, client: Lithic) -> None: + with client.financial_accounts.with_streaming_response.create( + nickname="string", + type="OPERATING", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + financial_account = response.parse() + assert_matches_type(FinancialAccount, financial_account, path=["response"]) + + assert cast(Any, response.is_closed) is True + @parametrize def test_method_retrieve(self, client: Lithic) -> None: financial_account = client.financial_accounts.retrieve( @@ -144,6 +189,49 @@ def test_streaming_response_list(self, client: Lithic) -> None: class TestAsyncFinancialAccounts: parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + @parametrize + async def test_method_create(self, async_client: AsyncLithic) -> None: + financial_account = await async_client.financial_accounts.create( + nickname="string", + type="OPERATING", + ) + assert_matches_type(FinancialAccount, financial_account, path=["response"]) + + @parametrize + async def test_method_create_with_all_params(self, async_client: AsyncLithic) -> None: + financial_account = await async_client.financial_accounts.create( + nickname="string", + type="OPERATING", + account_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert_matches_type(FinancialAccount, financial_account, path=["response"]) + + @parametrize + async def test_raw_response_create(self, async_client: AsyncLithic) -> None: + response = await async_client.financial_accounts.with_raw_response.create( + nickname="string", + type="OPERATING", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + financial_account = response.parse() + assert_matches_type(FinancialAccount, financial_account, path=["response"]) + + @parametrize + async def test_streaming_response_create(self, async_client: AsyncLithic) -> None: + async with async_client.financial_accounts.with_streaming_response.create( + nickname="string", + type="OPERATING", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + financial_account = await response.parse() + assert_matches_type(FinancialAccount, financial_account, path=["response"]) + + assert cast(Any, response.is_closed) is True + @parametrize async def test_method_retrieve(self, async_client: AsyncLithic) -> None: financial_account = await async_client.financial_accounts.retrieve(