From 6b3cfd6ac06980b80d110b19b20697068bbeeee9 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 6 Mar 2026 18:41:09 +0000 Subject: [PATCH 1/5] feat(api): add EARLY_DIRECT_DEPOSIT_FLOAT type to financial accounts --- .stats.yml | 8 +- api.md | 15 + src/lithic/_client.py | 38 ++ src/lithic/resources/__init__.py | 14 + src/lithic/resources/account_activity.py | 2 + .../financial_accounts/financial_accounts.py | 4 +- src/lithic/resources/holds.py | 550 ++++++++++++++++++ src/lithic/types/__init__.py | 5 + .../types/account_activity_list_params.py | 1 + .../types/account_activity_list_response.py | 3 + ..._activity_retrieve_transaction_response.py | 3 + src/lithic/types/financial_account.py | 1 + .../types/financial_account_list_params.py | 2 +- .../statements/statement_line_items.py | 1 + src/lithic/types/hold.py | 48 ++ src/lithic/types/hold_create_params.py | 28 + src/lithic/types/hold_event.py | 35 ++ src/lithic/types/hold_list_params.py | 44 ++ src/lithic/types/hold_void_params.py | 13 + src/lithic/types/payment.py | 1 + .../shared/instance_financial_account_type.py | 1 + tests/api_resources/test_holds.py | 412 +++++++++++++ 22 files changed, 1222 insertions(+), 7 deletions(-) create mode 100644 src/lithic/resources/holds.py create mode 100644 src/lithic/types/hold.py create mode 100644 src/lithic/types/hold_create_params.py create mode 100644 src/lithic/types/hold_event.py create mode 100644 src/lithic/types/hold_list_params.py create mode 100644 src/lithic/types/hold_void_params.py create mode 100644 tests/api_resources/test_holds.py diff --git a/.stats.yml b/.stats.yml index eba290a5..8d817154 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 184 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic%2Flithic-ee8607f0a2cdcaee420935050334a439db8dd097be83023fccdaf1d6f9a7de14.yml -openapi_spec_hash: 0f21c68cdddb7c5bd99f42356d507393 -config_hash: fb5070d41fcabdedbc084b83964b592a +configured_endpoints: 188 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic%2Flithic-ee2b9f00d3a9e0000e25abc0774615d6ad3300ce17b2f094e71b0229a907760f.yml +openapi_spec_hash: 01d2cbf4ac692dba2f3831462db929e4 +config_hash: a45e6da4e7b46db4ff6819d1dba5d815 diff --git a/api.md b/api.md index e247a6e0..0fb2d5b8 100644 --- a/api.md +++ b/api.md @@ -827,6 +827,21 @@ Methods: - client.network_programs.retrieve(network_program_token) -> NetworkProgram - client.network_programs.list(\*\*params) -> SyncSinglePage[NetworkProgram] +# Holds + +Types: + +```python +from lithic.types import Hold, HoldEvent +``` + +Methods: + +- client.holds.create(financial_account_token, \*\*params) -> Hold +- client.holds.retrieve(hold_token) -> Hold +- client.holds.list(financial_account_token, \*\*params) -> SyncCursorPage[Hold] +- client.holds.void(hold_token, \*\*params) -> Hold + # AccountActivity Types: diff --git a/src/lithic/_client.py b/src/lithic/_client.py index 4f9fd51a..4a7a8a88 100644 --- a/src/lithic/_client.py +++ b/src/lithic/_client.py @@ -40,6 +40,7 @@ from .resources import ( cards, fraud, + holds, events, reports, accounts, @@ -69,6 +70,7 @@ external_bank_accounts, tokenization_decisioning, ) + from .resources.holds import Holds, AsyncHolds from .resources.accounts import Accounts, AsyncAccounts from .resources.balances import Balances, AsyncBalances from .resources.disputes import Disputes, AsyncDisputes @@ -374,6 +376,12 @@ def network_programs(self) -> NetworkPrograms: return NetworkPrograms(self) + @cached_property + def holds(self) -> Holds: + from .resources.holds import Holds + + return Holds(self) + @cached_property def account_activity(self) -> AccountActivity: from .resources.account_activity import AccountActivity @@ -783,6 +791,12 @@ def network_programs(self) -> AsyncNetworkPrograms: return AsyncNetworkPrograms(self) + @cached_property + def holds(self) -> AsyncHolds: + from .resources.holds import AsyncHolds + + return AsyncHolds(self) + @cached_property def account_activity(self) -> AsyncAccountActivity: from .resources.account_activity import AsyncAccountActivity @@ -1115,6 +1129,12 @@ def network_programs(self) -> network_programs.NetworkProgramsWithRawResponse: return NetworkProgramsWithRawResponse(self._client.network_programs) + @cached_property + def holds(self) -> holds.HoldsWithRawResponse: + from .resources.holds import HoldsWithRawResponse + + return HoldsWithRawResponse(self._client.holds) + @cached_property def account_activity(self) -> account_activity.AccountActivityWithRawResponse: from .resources.account_activity import AccountActivityWithRawResponse @@ -1306,6 +1326,12 @@ def network_programs(self) -> network_programs.AsyncNetworkProgramsWithRawRespon return AsyncNetworkProgramsWithRawResponse(self._client.network_programs) + @cached_property + def holds(self) -> holds.AsyncHoldsWithRawResponse: + from .resources.holds import AsyncHoldsWithRawResponse + + return AsyncHoldsWithRawResponse(self._client.holds) + @cached_property def account_activity(self) -> account_activity.AsyncAccountActivityWithRawResponse: from .resources.account_activity import AsyncAccountActivityWithRawResponse @@ -1497,6 +1523,12 @@ def network_programs(self) -> network_programs.NetworkProgramsWithStreamingRespo return NetworkProgramsWithStreamingResponse(self._client.network_programs) + @cached_property + def holds(self) -> holds.HoldsWithStreamingResponse: + from .resources.holds import HoldsWithStreamingResponse + + return HoldsWithStreamingResponse(self._client.holds) + @cached_property def account_activity(self) -> account_activity.AccountActivityWithStreamingResponse: from .resources.account_activity import AccountActivityWithStreamingResponse @@ -1688,6 +1720,12 @@ def network_programs(self) -> network_programs.AsyncNetworkProgramsWithStreaming return AsyncNetworkProgramsWithStreamingResponse(self._client.network_programs) + @cached_property + def holds(self) -> holds.AsyncHoldsWithStreamingResponse: + from .resources.holds import AsyncHoldsWithStreamingResponse + + return AsyncHoldsWithStreamingResponse(self._client.holds) + @cached_property def account_activity(self) -> account_activity.AsyncAccountActivityWithStreamingResponse: from .resources.account_activity import AsyncAccountActivityWithStreamingResponse diff --git a/src/lithic/resources/__init__.py b/src/lithic/resources/__init__.py index 07be719f..47ee1966 100644 --- a/src/lithic/resources/__init__.py +++ b/src/lithic/resources/__init__.py @@ -16,6 +16,14 @@ FraudWithStreamingResponse, AsyncFraudWithStreamingResponse, ) +from .holds import ( + Holds, + AsyncHolds, + HoldsWithRawResponse, + AsyncHoldsWithRawResponse, + HoldsWithStreamingResponse, + AsyncHoldsWithStreamingResponse, +) from .events import ( Events, AsyncEvents, @@ -411,6 +419,12 @@ "AsyncNetworkProgramsWithRawResponse", "NetworkProgramsWithStreamingResponse", "AsyncNetworkProgramsWithStreamingResponse", + "Holds", + "AsyncHolds", + "HoldsWithRawResponse", + "AsyncHoldsWithRawResponse", + "HoldsWithStreamingResponse", + "AsyncHoldsWithStreamingResponse", "AccountActivity", "AsyncAccountActivity", "AccountActivityWithRawResponse", diff --git a/src/lithic/resources/account_activity.py b/src/lithic/resources/account_activity.py index c9cd0223..6a4045b1 100644 --- a/src/lithic/resources/account_activity.py +++ b/src/lithic/resources/account_activity.py @@ -69,6 +69,7 @@ def list( "MANAGEMENT_FEE", "MANAGEMENT_REWARD", "MANAGEMENT_DISBURSEMENT", + "HOLD", "PROGRAM_FUNDING", ] | Omit = omit, @@ -239,6 +240,7 @@ def list( "MANAGEMENT_FEE", "MANAGEMENT_REWARD", "MANAGEMENT_DISBURSEMENT", + "HOLD", "PROGRAM_FUNDING", ] | Omit = omit, diff --git a/src/lithic/resources/financial_accounts/financial_accounts.py b/src/lithic/resources/financial_accounts/financial_accounts.py index e26c023c..3c42d154 100644 --- a/src/lithic/resources/financial_accounts/financial_accounts.py +++ b/src/lithic/resources/financial_accounts/financial_accounts.py @@ -251,7 +251,7 @@ def list( *, account_token: str | Omit = omit, business_account_token: str | Omit = omit, - type: Literal["ISSUING", "OPERATING", "RESERVE", "SECURITY"] | Omit = omit, + type: Literal["ISSUING", "OPERATING", "RESERVE", "SECURITY", "EARLY_DIRECT_DEPOSIT_FLOAT"] | Omit = omit, # 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, @@ -569,7 +569,7 @@ def list( *, account_token: str | Omit = omit, business_account_token: str | Omit = omit, - type: Literal["ISSUING", "OPERATING", "RESERVE", "SECURITY"] | Omit = omit, + type: Literal["ISSUING", "OPERATING", "RESERVE", "SECURITY", "EARLY_DIRECT_DEPOSIT_FLOAT"] | Omit = omit, # 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, diff --git a/src/lithic/resources/holds.py b/src/lithic/resources/holds.py new file mode 100644 index 00000000..45d6c4ae --- /dev/null +++ b/src/lithic/resources/holds.py @@ -0,0 +1,550 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Union, Optional +from datetime import datetime +from typing_extensions import Literal + +import httpx + +from .. import _legacy_response +from ..types import hold_list_params, hold_void_params, hold_create_params +from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given +from .._utils import maybe_transform, async_maybe_transform +from .._compat import cached_property +from .._resource import SyncAPIResource, AsyncAPIResource +from .._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper +from ..pagination import SyncCursorPage, AsyncCursorPage +from ..types.hold import Hold +from .._base_client import AsyncPaginator, make_request_options + +__all__ = ["Holds", "AsyncHolds"] + + +class Holds(SyncAPIResource): + @cached_property + def with_raw_response(self) -> HoldsWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/lithic-com/lithic-python#accessing-raw-response-data-eg-headers + """ + return HoldsWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> HoldsWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/lithic-com/lithic-python#with_streaming_response + """ + return HoldsWithStreamingResponse(self) + + def create( + self, + financial_account_token: str, + *, + amount: int, + token: str | Omit = omit, + expiration_datetime: Union[str, datetime] | Omit = omit, + memo: Optional[str] | Omit = omit, + user_defined_id: str | Omit = omit, + # 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, + ) -> Hold: + """Create a hold on a financial account. + + Holds reserve funds by moving them from + available to pending balance. They can be resolved via settlement (linked to a + payment or book transfer), voiding, or expiration. + + Args: + amount: Amount to hold in cents + + token: Customer-provided token for idempotency. Becomes the hold token. + + expiration_datetime: When the hold should auto-expire + + memo: Reason for the hold + + user_defined_id: User-provided identifier for the hold + + 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 financial_account_token: + raise ValueError( + f"Expected a non-empty value for `financial_account_token` but received {financial_account_token!r}" + ) + return self._post( + f"/v1/financial_accounts/{financial_account_token}/holds", + body=maybe_transform( + { + "amount": amount, + "token": token, + "expiration_datetime": expiration_datetime, + "memo": memo, + "user_defined_id": user_defined_id, + }, + hold_create_params.HoldCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=Hold, + ) + + def retrieve( + self, + hold_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, + ) -> Hold: + """ + Get hold by token. + + 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 hold_token: + raise ValueError(f"Expected a non-empty value for `hold_token` but received {hold_token!r}") + return self._get( + f"/v1/holds/{hold_token}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=Hold, + ) + + def list( + self, + financial_account_token: str, + *, + begin: Union[str, datetime] | Omit = omit, + end: Union[str, datetime] | Omit = omit, + ending_before: str | Omit = omit, + page_size: int | Omit = omit, + starting_after: str | Omit = omit, + status: Literal["PENDING", "SETTLED", "EXPIRED", "VOIDED"] | Omit = omit, + # 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, + ) -> SyncCursorPage[Hold]: + """ + List holds for a financial account. + + Args: + begin: Date string in RFC 3339 format. Only entries created after the specified time + will be included. UTC time zone. + + end: Date string in RFC 3339 format. Only entries created before the specified time + will be included. UTC time zone. + + ending_before: A cursor representing an item's token before which a page of results should end. + Used to retrieve the previous page of results before this item. + + page_size: Page size (for pagination). + + starting_after: A cursor representing an item's token after which a page of results should + begin. Used to retrieve the next page of results after this item. + + status: Hold status to filter by. + + 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 financial_account_token: + raise ValueError( + f"Expected a non-empty value for `financial_account_token` but received {financial_account_token!r}" + ) + return self._get_api_list( + f"/v1/financial_accounts/{financial_account_token}/holds", + page=SyncCursorPage[Hold], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "begin": begin, + "end": end, + "ending_before": ending_before, + "page_size": page_size, + "starting_after": starting_after, + "status": status, + }, + hold_list_params.HoldListParams, + ), + ), + model=Hold, + ) + + def void( + self, + hold_token: str, + *, + memo: Optional[str] | Omit = omit, + # 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, + ) -> Hold: + """Void an active hold. + + This returns the held funds from pending back to available + balance. Only holds in PENDING status can be voided. + + Args: + memo: Reason for voiding the hold + + 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 hold_token: + raise ValueError(f"Expected a non-empty value for `hold_token` but received {hold_token!r}") + return self._post( + f"/v1/holds/{hold_token}/void", + body=maybe_transform({"memo": memo}, hold_void_params.HoldVoidParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=Hold, + ) + + +class AsyncHolds(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncHoldsWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/lithic-com/lithic-python#accessing-raw-response-data-eg-headers + """ + return AsyncHoldsWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncHoldsWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/lithic-com/lithic-python#with_streaming_response + """ + return AsyncHoldsWithStreamingResponse(self) + + async def create( + self, + financial_account_token: str, + *, + amount: int, + token: str | Omit = omit, + expiration_datetime: Union[str, datetime] | Omit = omit, + memo: Optional[str] | Omit = omit, + user_defined_id: str | Omit = omit, + # 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, + ) -> Hold: + """Create a hold on a financial account. + + Holds reserve funds by moving them from + available to pending balance. They can be resolved via settlement (linked to a + payment or book transfer), voiding, or expiration. + + Args: + amount: Amount to hold in cents + + token: Customer-provided token for idempotency. Becomes the hold token. + + expiration_datetime: When the hold should auto-expire + + memo: Reason for the hold + + user_defined_id: User-provided identifier for the hold + + 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 financial_account_token: + raise ValueError( + f"Expected a non-empty value for `financial_account_token` but received {financial_account_token!r}" + ) + return await self._post( + f"/v1/financial_accounts/{financial_account_token}/holds", + body=await async_maybe_transform( + { + "amount": amount, + "token": token, + "expiration_datetime": expiration_datetime, + "memo": memo, + "user_defined_id": user_defined_id, + }, + hold_create_params.HoldCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=Hold, + ) + + async def retrieve( + self, + hold_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, + ) -> Hold: + """ + Get hold by token. + + 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 hold_token: + raise ValueError(f"Expected a non-empty value for `hold_token` but received {hold_token!r}") + return await self._get( + f"/v1/holds/{hold_token}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=Hold, + ) + + def list( + self, + financial_account_token: str, + *, + begin: Union[str, datetime] | Omit = omit, + end: Union[str, datetime] | Omit = omit, + ending_before: str | Omit = omit, + page_size: int | Omit = omit, + starting_after: str | Omit = omit, + status: Literal["PENDING", "SETTLED", "EXPIRED", "VOIDED"] | Omit = omit, + # 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, + ) -> AsyncPaginator[Hold, AsyncCursorPage[Hold]]: + """ + List holds for a financial account. + + Args: + begin: Date string in RFC 3339 format. Only entries created after the specified time + will be included. UTC time zone. + + end: Date string in RFC 3339 format. Only entries created before the specified time + will be included. UTC time zone. + + ending_before: A cursor representing an item's token before which a page of results should end. + Used to retrieve the previous page of results before this item. + + page_size: Page size (for pagination). + + starting_after: A cursor representing an item's token after which a page of results should + begin. Used to retrieve the next page of results after this item. + + status: Hold status to filter by. + + 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 financial_account_token: + raise ValueError( + f"Expected a non-empty value for `financial_account_token` but received {financial_account_token!r}" + ) + return self._get_api_list( + f"/v1/financial_accounts/{financial_account_token}/holds", + page=AsyncCursorPage[Hold], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "begin": begin, + "end": end, + "ending_before": ending_before, + "page_size": page_size, + "starting_after": starting_after, + "status": status, + }, + hold_list_params.HoldListParams, + ), + ), + model=Hold, + ) + + async def void( + self, + hold_token: str, + *, + memo: Optional[str] | Omit = omit, + # 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, + ) -> Hold: + """Void an active hold. + + This returns the held funds from pending back to available + balance. Only holds in PENDING status can be voided. + + Args: + memo: Reason for voiding the hold + + 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 hold_token: + raise ValueError(f"Expected a non-empty value for `hold_token` but received {hold_token!r}") + return await self._post( + f"/v1/holds/{hold_token}/void", + body=await async_maybe_transform({"memo": memo}, hold_void_params.HoldVoidParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=Hold, + ) + + +class HoldsWithRawResponse: + def __init__(self, holds: Holds) -> None: + self._holds = holds + + self.create = _legacy_response.to_raw_response_wrapper( + holds.create, + ) + self.retrieve = _legacy_response.to_raw_response_wrapper( + holds.retrieve, + ) + self.list = _legacy_response.to_raw_response_wrapper( + holds.list, + ) + self.void = _legacy_response.to_raw_response_wrapper( + holds.void, + ) + + +class AsyncHoldsWithRawResponse: + def __init__(self, holds: AsyncHolds) -> None: + self._holds = holds + + self.create = _legacy_response.async_to_raw_response_wrapper( + holds.create, + ) + self.retrieve = _legacy_response.async_to_raw_response_wrapper( + holds.retrieve, + ) + self.list = _legacy_response.async_to_raw_response_wrapper( + holds.list, + ) + self.void = _legacy_response.async_to_raw_response_wrapper( + holds.void, + ) + + +class HoldsWithStreamingResponse: + def __init__(self, holds: Holds) -> None: + self._holds = holds + + self.create = to_streamed_response_wrapper( + holds.create, + ) + self.retrieve = to_streamed_response_wrapper( + holds.retrieve, + ) + self.list = to_streamed_response_wrapper( + holds.list, + ) + self.void = to_streamed_response_wrapper( + holds.void, + ) + + +class AsyncHoldsWithStreamingResponse: + def __init__(self, holds: AsyncHolds) -> None: + self._holds = holds + + self.create = async_to_streamed_response_wrapper( + holds.create, + ) + self.retrieve = async_to_streamed_response_wrapper( + holds.retrieve, + ) + self.list = async_to_streamed_response_wrapper( + holds.list, + ) + self.void = async_to_streamed_response_wrapper( + holds.void, + ) diff --git a/src/lithic/types/__init__.py b/src/lithic/types/__init__.py index 5532206f..60253cf5 100644 --- a/src/lithic/types/__init__.py +++ b/src/lithic/types/__init__.py @@ -3,6 +3,7 @@ from __future__ import annotations from .card import Card as Card +from .hold import Hold as Hold from .event import Event as Event from .device import Device as Device from .shared import ( @@ -24,6 +25,7 @@ from .kyc_param import KYCParam as KYCParam from .api_status import APIStatus as APIStatus from .dispute_v2 import DisputeV2 as DisputeV2 +from .hold_event import HoldEvent as HoldEvent from .owner_type import OwnerType as OwnerType from .token_info import TokenInfo as TokenInfo from .transaction import Transaction as Transaction @@ -42,6 +44,8 @@ from .digital_card_art import DigitalCardArt as DigitalCardArt from .dispute_evidence import DisputeEvidence as DisputeEvidence from .external_payment import ExternalPayment as ExternalPayment +from .hold_list_params import HoldListParams as HoldListParams +from .hold_void_params import HoldVoidParams as HoldVoidParams from .kyc_exempt_param import KYCExemptParam as KYCExemptParam from .statement_totals import StatementTotals as StatementTotals from .card_embed_params import CardEmbedParams as CardEmbedParams @@ -57,6 +61,7 @@ from .card_create_params import CardCreateParams as CardCreateParams from .card_update_params import CardUpdateParams as CardUpdateParams from .event_subscription import EventSubscription as EventSubscription +from .hold_create_params import HoldCreateParams as HoldCreateParams from .provision_response import ProvisionResponse as ProvisionResponse from .wire_party_details import WirePartyDetails as WirePartyDetails from .account_list_params import AccountListParams as AccountListParams diff --git a/src/lithic/types/account_activity_list_params.py b/src/lithic/types/account_activity_list_params.py index 7b28515b..6e3990c3 100644 --- a/src/lithic/types/account_activity_list_params.py +++ b/src/lithic/types/account_activity_list_params.py @@ -44,6 +44,7 @@ class AccountActivityListParams(TypedDict, total=False): "MANAGEMENT_FEE", "MANAGEMENT_REWARD", "MANAGEMENT_DISBURSEMENT", + "HOLD", "PROGRAM_FUNDING", ] """Filter by transaction category""" diff --git a/src/lithic/types/account_activity_list_response.py b/src/lithic/types/account_activity_list_response.py index 33992124..8b126e38 100644 --- a/src/lithic/types/account_activity_list_response.py +++ b/src/lithic/types/account_activity_list_response.py @@ -4,6 +4,7 @@ from datetime import datetime from typing_extensions import Literal, Annotated, TypeAlias +from .hold import Hold from .._utils import PropertyInfo from .payment import Payment from .._models import BaseModel @@ -42,6 +43,7 @@ class FinancialTransaction(BaseModel): "MANAGEMENT_FEE", "MANAGEMENT_REWARD", "MANAGEMENT_DISBURSEMENT", + "HOLD", "PROGRAM_FUNDING", ] """Transaction category""" @@ -107,6 +109,7 @@ class CardTransaction(Transaction): Payment, ExternalPayment, ManagementOperationTransaction, + Hold, ], PropertyInfo(discriminator="family"), ] diff --git a/src/lithic/types/account_activity_retrieve_transaction_response.py b/src/lithic/types/account_activity_retrieve_transaction_response.py index 202fd3eb..532b7cf3 100644 --- a/src/lithic/types/account_activity_retrieve_transaction_response.py +++ b/src/lithic/types/account_activity_retrieve_transaction_response.py @@ -4,6 +4,7 @@ from datetime import datetime from typing_extensions import Literal, Annotated, TypeAlias +from .hold import Hold from .._utils import PropertyInfo from .payment import Payment from .._models import BaseModel @@ -42,6 +43,7 @@ class FinancialTransaction(BaseModel): "MANAGEMENT_FEE", "MANAGEMENT_REWARD", "MANAGEMENT_DISBURSEMENT", + "HOLD", "PROGRAM_FUNDING", ] """Transaction category""" @@ -107,6 +109,7 @@ class CardTransaction(Transaction): Payment, ExternalPayment, ManagementOperationTransaction, + Hold, ], PropertyInfo(discriminator="family"), ] diff --git a/src/lithic/types/financial_account.py b/src/lithic/types/financial_account.py index 92e7ddd4..f15dfccd 100644 --- a/src/lithic/types/financial_account.py +++ b/src/lithic/types/financial_account.py @@ -69,6 +69,7 @@ class FinancialAccount(BaseModel): "PROGRAM_RECEIVABLES", "COLLECTION", "PROGRAM_BANK_ACCOUNTS_PAYABLE", + "EARLY_DIRECT_DEPOSIT_FLOAT", ] updated: datetime diff --git a/src/lithic/types/financial_account_list_params.py b/src/lithic/types/financial_account_list_params.py index 0228f2b6..20b2605f 100644 --- a/src/lithic/types/financial_account_list_params.py +++ b/src/lithic/types/financial_account_list_params.py @@ -14,5 +14,5 @@ class FinancialAccountListParams(TypedDict, total=False): business_account_token: str """List financial accounts for a given business_account_token""" - type: Literal["ISSUING", "OPERATING", "RESERVE", "SECURITY"] + type: Literal["ISSUING", "OPERATING", "RESERVE", "SECURITY", "EARLY_DIRECT_DEPOSIT_FLOAT"] """List financial accounts of a given type""" diff --git a/src/lithic/types/financial_accounts/statements/statement_line_items.py b/src/lithic/types/financial_accounts/statements/statement_line_items.py index c1816c30..98b9cf97 100644 --- a/src/lithic/types/financial_accounts/statements/statement_line_items.py +++ b/src/lithic/types/financial_accounts/statements/statement_line_items.py @@ -36,6 +36,7 @@ class Data(BaseModel): "MANAGEMENT_FEE", "MANAGEMENT_REWARD", "MANAGEMENT_DISBURSEMENT", + "HOLD", "PROGRAM_FUNDING", ] diff --git a/src/lithic/types/hold.py b/src/lithic/types/hold.py new file mode 100644 index 00000000..448da4cc --- /dev/null +++ b/src/lithic/types/hold.py @@ -0,0 +1,48 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from datetime import datetime +from typing_extensions import Literal + +from .._models import BaseModel +from .hold_event import HoldEvent + +__all__ = ["Hold"] + + +class Hold(BaseModel): + """A hold transaction representing reserved funds on a financial account. + + Holds move funds from available to pending balance in anticipation of future payments. They can be resolved via settlement (linked to payment), manual release, or expiration. + """ + + token: str + """Unique identifier for the transaction""" + + created: datetime + """ISO 8601 timestamp of when the transaction was created""" + + status: Literal["PENDING", "SETTLED", "EXPIRED", "VOIDED", "DECLINED", "REVERSED", "CANCELED", "RETURNED"] + """Status of a hold transaction""" + + updated: datetime + """ISO 8601 timestamp of when the transaction was last updated""" + + currency: Optional[str] = None + + events: Optional[List[HoldEvent]] = None + + expiration_datetime: Optional[datetime] = None + """When the hold will auto-expire if not resolved""" + + family: Optional[Literal["HOLD"]] = None + """HOLD - Hold Transaction""" + + financial_account_token: Optional[str] = None + + pending_amount: Optional[int] = None + """Current pending amount (0 when resolved)""" + + result: Optional[Literal["APPROVED", "DECLINED"]] = None + + user_defined_id: Optional[str] = None diff --git a/src/lithic/types/hold_create_params.py b/src/lithic/types/hold_create_params.py new file mode 100644 index 00000000..fb68d3de --- /dev/null +++ b/src/lithic/types/hold_create_params.py @@ -0,0 +1,28 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Union, Optional +from datetime import datetime +from typing_extensions import Required, Annotated, TypedDict + +from .._utils import PropertyInfo + +__all__ = ["HoldCreateParams"] + + +class HoldCreateParams(TypedDict, total=False): + amount: Required[int] + """Amount to hold in cents""" + + token: str + """Customer-provided token for idempotency. Becomes the hold token.""" + + expiration_datetime: Annotated[Union[str, datetime], PropertyInfo(format="iso8601")] + """When the hold should auto-expire""" + + memo: Optional[str] + """Reason for the hold""" + + user_defined_id: str + """User-provided identifier for the hold""" diff --git a/src/lithic/types/hold_event.py b/src/lithic/types/hold_event.py new file mode 100644 index 00000000..b0c8d0ba --- /dev/null +++ b/src/lithic/types/hold_event.py @@ -0,0 +1,35 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from datetime import datetime +from typing_extensions import Literal + +from .._models import BaseModel + +__all__ = ["HoldEvent"] + + +class HoldEvent(BaseModel): + """Event representing a lifecycle change to a hold""" + + token: str + + amount: int + """Amount in cents""" + + created: datetime + + detailed_results: List[Literal["APPROVED", "INSUFFICIENT_FUNDS"]] + + memo: Optional[str] = None + + result: Literal["APPROVED", "DECLINED"] + + settling_transaction_token: Optional[str] = None + """ + Transaction token of the payment that settled this hold (only populated for + HOLD_SETTLED events) + """ + + type: Literal["HOLD_INITIATED", "HOLD_VOIDED", "HOLD_EXPIRED", "HOLD_SETTLED"] + """Type of hold lifecycle event""" diff --git a/src/lithic/types/hold_list_params.py b/src/lithic/types/hold_list_params.py new file mode 100644 index 00000000..3a7cf534 --- /dev/null +++ b/src/lithic/types/hold_list_params.py @@ -0,0 +1,44 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Union +from datetime import datetime +from typing_extensions import Literal, Annotated, TypedDict + +from .._utils import PropertyInfo + +__all__ = ["HoldListParams"] + + +class HoldListParams(TypedDict, total=False): + begin: Annotated[Union[str, datetime], PropertyInfo(format="iso8601")] + """Date string in RFC 3339 format. + + Only entries created after the specified time will be included. UTC time zone. + """ + + end: Annotated[Union[str, datetime], PropertyInfo(format="iso8601")] + """Date string in RFC 3339 format. + + Only entries created before the specified time will be included. UTC time zone. + """ + + ending_before: str + """A cursor representing an item's token before which a page of results should end. + + Used to retrieve the previous page of results before this item. + """ + + page_size: int + """Page size (for pagination).""" + + starting_after: str + """A cursor representing an item's token after which a page of results should + begin. + + Used to retrieve the next page of results after this item. + """ + + status: Literal["PENDING", "SETTLED", "EXPIRED", "VOIDED"] + """Hold status to filter by.""" diff --git a/src/lithic/types/hold_void_params.py b/src/lithic/types/hold_void_params.py new file mode 100644 index 00000000..c01ce288 --- /dev/null +++ b/src/lithic/types/hold_void_params.py @@ -0,0 +1,13 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Optional +from typing_extensions import TypedDict + +__all__ = ["HoldVoidParams"] + + +class HoldVoidParams(TypedDict, total=False): + memo: Optional[str] + """Reason for voiding the hold""" diff --git a/src/lithic/types/payment.py b/src/lithic/types/payment.py index 686f8978..4095d525 100644 --- a/src/lithic/types/payment.py +++ b/src/lithic/types/payment.py @@ -185,6 +185,7 @@ class Payment(BaseModel): "MANAGEMENT_FEE", "MANAGEMENT_REWARD", "MANAGEMENT_DISBURSEMENT", + "HOLD", "PROGRAM_FUNDING", ] """Transaction category""" diff --git a/src/lithic/types/shared/instance_financial_account_type.py b/src/lithic/types/shared/instance_financial_account_type.py index 72a4a348..4cd1bd35 100644 --- a/src/lithic/types/shared/instance_financial_account_type.py +++ b/src/lithic/types/shared/instance_financial_account_type.py @@ -15,4 +15,5 @@ "PROGRAM_RECEIVABLES", "COLLECTION", "PROGRAM_BANK_ACCOUNTS_PAYABLE", + "EARLY_DIRECT_DEPOSIT_FLOAT", ] diff --git a/tests/api_resources/test_holds.py b/tests/api_resources/test_holds.py new file mode 100644 index 00000000..c2bf4f08 --- /dev/null +++ b/tests/api_resources/test_holds.py @@ -0,0 +1,412 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from lithic import Lithic, AsyncLithic +from tests.utils import assert_matches_type +from lithic.types import Hold +from lithic._utils import parse_datetime +from lithic.pagination import SyncCursorPage, AsyncCursorPage + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestHolds: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_create(self, client: Lithic) -> None: + hold = client.holds.create( + financial_account_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + amount=1, + ) + assert_matches_type(Hold, hold, path=["response"]) + + @parametrize + def test_method_create_with_all_params(self, client: Lithic) -> None: + hold = client.holds.create( + financial_account_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + amount=1, + token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + expiration_datetime=parse_datetime("2019-12-27T18:11:19.117Z"), + memo="memo", + user_defined_id="user_defined_id", + ) + assert_matches_type(Hold, hold, path=["response"]) + + @parametrize + def test_raw_response_create(self, client: Lithic) -> None: + response = client.holds.with_raw_response.create( + financial_account_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + amount=1, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + hold = response.parse() + assert_matches_type(Hold, hold, path=["response"]) + + @parametrize + def test_streaming_response_create(self, client: Lithic) -> None: + with client.holds.with_streaming_response.create( + financial_account_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + amount=1, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + hold = response.parse() + assert_matches_type(Hold, hold, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_create(self, client: Lithic) -> None: + with pytest.raises( + ValueError, match=r"Expected a non-empty value for `financial_account_token` but received ''" + ): + client.holds.with_raw_response.create( + financial_account_token="", + amount=1, + ) + + @parametrize + def test_method_retrieve(self, client: Lithic) -> None: + hold = client.holds.retrieve( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert_matches_type(Hold, hold, path=["response"]) + + @parametrize + def test_raw_response_retrieve(self, client: Lithic) -> None: + response = client.holds.with_raw_response.retrieve( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + hold = response.parse() + assert_matches_type(Hold, hold, path=["response"]) + + @parametrize + def test_streaming_response_retrieve(self, client: Lithic) -> None: + with client.holds.with_streaming_response.retrieve( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + hold = response.parse() + assert_matches_type(Hold, hold, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_retrieve(self, client: Lithic) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `hold_token` but received ''"): + client.holds.with_raw_response.retrieve( + "", + ) + + @parametrize + def test_method_list(self, client: Lithic) -> None: + hold = client.holds.list( + financial_account_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert_matches_type(SyncCursorPage[Hold], hold, path=["response"]) + + @parametrize + def test_method_list_with_all_params(self, client: Lithic) -> None: + hold = client.holds.list( + financial_account_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + begin=parse_datetime("2019-12-27T18:11:19.117Z"), + end=parse_datetime("2019-12-27T18:11:19.117Z"), + ending_before="ending_before", + page_size=1, + starting_after="starting_after", + status="PENDING", + ) + assert_matches_type(SyncCursorPage[Hold], hold, path=["response"]) + + @parametrize + def test_raw_response_list(self, client: Lithic) -> None: + response = client.holds.with_raw_response.list( + financial_account_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + hold = response.parse() + assert_matches_type(SyncCursorPage[Hold], hold, path=["response"]) + + @parametrize + def test_streaming_response_list(self, client: Lithic) -> None: + with client.holds.with_streaming_response.list( + financial_account_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + hold = response.parse() + assert_matches_type(SyncCursorPage[Hold], hold, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_list(self, client: Lithic) -> None: + with pytest.raises( + ValueError, match=r"Expected a non-empty value for `financial_account_token` but received ''" + ): + client.holds.with_raw_response.list( + financial_account_token="", + ) + + @parametrize + def test_method_void(self, client: Lithic) -> None: + hold = client.holds.void( + hold_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert_matches_type(Hold, hold, path=["response"]) + + @parametrize + def test_method_void_with_all_params(self, client: Lithic) -> None: + hold = client.holds.void( + hold_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + memo="memo", + ) + assert_matches_type(Hold, hold, path=["response"]) + + @parametrize + def test_raw_response_void(self, client: Lithic) -> None: + response = client.holds.with_raw_response.void( + hold_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + hold = response.parse() + assert_matches_type(Hold, hold, path=["response"]) + + @parametrize + def test_streaming_response_void(self, client: Lithic) -> None: + with client.holds.with_streaming_response.void( + hold_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + hold = response.parse() + assert_matches_type(Hold, hold, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_void(self, client: Lithic) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `hold_token` but received ''"): + client.holds.with_raw_response.void( + hold_token="", + ) + + +class TestAsyncHolds: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @parametrize + async def test_method_create(self, async_client: AsyncLithic) -> None: + hold = await async_client.holds.create( + financial_account_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + amount=1, + ) + assert_matches_type(Hold, hold, path=["response"]) + + @parametrize + async def test_method_create_with_all_params(self, async_client: AsyncLithic) -> None: + hold = await async_client.holds.create( + financial_account_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + amount=1, + token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + expiration_datetime=parse_datetime("2019-12-27T18:11:19.117Z"), + memo="memo", + user_defined_id="user_defined_id", + ) + assert_matches_type(Hold, hold, path=["response"]) + + @parametrize + async def test_raw_response_create(self, async_client: AsyncLithic) -> None: + response = await async_client.holds.with_raw_response.create( + financial_account_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + amount=1, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + hold = response.parse() + assert_matches_type(Hold, hold, path=["response"]) + + @parametrize + async def test_streaming_response_create(self, async_client: AsyncLithic) -> None: + async with async_client.holds.with_streaming_response.create( + financial_account_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + amount=1, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + hold = await response.parse() + assert_matches_type(Hold, hold, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_create(self, async_client: AsyncLithic) -> None: + with pytest.raises( + ValueError, match=r"Expected a non-empty value for `financial_account_token` but received ''" + ): + await async_client.holds.with_raw_response.create( + financial_account_token="", + amount=1, + ) + + @parametrize + async def test_method_retrieve(self, async_client: AsyncLithic) -> None: + hold = await async_client.holds.retrieve( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert_matches_type(Hold, hold, path=["response"]) + + @parametrize + async def test_raw_response_retrieve(self, async_client: AsyncLithic) -> None: + response = await async_client.holds.with_raw_response.retrieve( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + hold = response.parse() + assert_matches_type(Hold, hold, path=["response"]) + + @parametrize + async def test_streaming_response_retrieve(self, async_client: AsyncLithic) -> None: + async with async_client.holds.with_streaming_response.retrieve( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + hold = await response.parse() + assert_matches_type(Hold, hold, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_retrieve(self, async_client: AsyncLithic) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `hold_token` but received ''"): + await async_client.holds.with_raw_response.retrieve( + "", + ) + + @parametrize + async def test_method_list(self, async_client: AsyncLithic) -> None: + hold = await async_client.holds.list( + financial_account_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert_matches_type(AsyncCursorPage[Hold], hold, path=["response"]) + + @parametrize + async def test_method_list_with_all_params(self, async_client: AsyncLithic) -> None: + hold = await async_client.holds.list( + financial_account_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + begin=parse_datetime("2019-12-27T18:11:19.117Z"), + end=parse_datetime("2019-12-27T18:11:19.117Z"), + ending_before="ending_before", + page_size=1, + starting_after="starting_after", + status="PENDING", + ) + assert_matches_type(AsyncCursorPage[Hold], hold, path=["response"]) + + @parametrize + async def test_raw_response_list(self, async_client: AsyncLithic) -> None: + response = await async_client.holds.with_raw_response.list( + financial_account_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + hold = response.parse() + assert_matches_type(AsyncCursorPage[Hold], hold, path=["response"]) + + @parametrize + async def test_streaming_response_list(self, async_client: AsyncLithic) -> None: + async with async_client.holds.with_streaming_response.list( + financial_account_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + hold = await response.parse() + assert_matches_type(AsyncCursorPage[Hold], hold, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_list(self, async_client: AsyncLithic) -> None: + with pytest.raises( + ValueError, match=r"Expected a non-empty value for `financial_account_token` but received ''" + ): + await async_client.holds.with_raw_response.list( + financial_account_token="", + ) + + @parametrize + async def test_method_void(self, async_client: AsyncLithic) -> None: + hold = await async_client.holds.void( + hold_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert_matches_type(Hold, hold, path=["response"]) + + @parametrize + async def test_method_void_with_all_params(self, async_client: AsyncLithic) -> None: + hold = await async_client.holds.void( + hold_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + memo="memo", + ) + assert_matches_type(Hold, hold, path=["response"]) + + @parametrize + async def test_raw_response_void(self, async_client: AsyncLithic) -> None: + response = await async_client.holds.with_raw_response.void( + hold_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + hold = response.parse() + assert_matches_type(Hold, hold, path=["response"]) + + @parametrize + async def test_streaming_response_void(self, async_client: AsyncLithic) -> None: + async with async_client.holds.with_streaming_response.void( + hold_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + hold = await response.parse() + assert_matches_type(Hold, hold, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_void(self, async_client: AsyncLithic) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `hold_token` but received ''"): + await async_client.holds.with_raw_response.void( + hold_token="", + ) From 845458d17d741e51d1ef212fac9de9a9cbd8b0e5 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 7 Mar 2026 15:05:48 +0000 Subject: [PATCH 2/5] chore(internal): codegen related update --- .github/workflows/ci.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 016de58f..7ec2e07d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -61,14 +61,18 @@ jobs: run: rye build - name: Get GitHub OIDC Token - if: github.repository == 'stainless-sdks/lithic-python' + if: |- + github.repository == 'stainless-sdks/lithic-python' && + !startsWith(github.ref, 'refs/heads/stl/') id: github-oidc uses: actions/github-script@v8 with: script: core.setOutput('github_token', await core.getIDToken()); - name: Upload tarball - if: github.repository == 'stainless-sdks/lithic-python' + if: |- + github.repository == 'stainless-sdks/lithic-python' && + !startsWith(github.ref, 'refs/heads/stl/') env: URL: https://pkg.stainless.com/s AUTH: ${{ steps.github-oidc.outputs.github_token }} From f6dc800f95e413c8a9436c5a966a2bb12d27b6b6 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 9 Mar 2026 16:10:39 +0000 Subject: [PATCH 3/5] feat(api): add typescript_code rule type, state/error fields to auth_rules --- .stats.yml | 6 +- api.md | 3 + src/lithic/resources/auth_rules/v2/v2.py | 28 ++++-- src/lithic/types/auth_rules/__init__.py | 6 ++ src/lithic/types/auth_rules/auth_rule.py | 27 +++++- src/lithic/types/auth_rules/rule_feature.py | 96 ++++++++++++++++++ .../types/auth_rules/rule_feature_param.py | 97 +++++++++++++++++++ .../auth_rules/typescript_code_parameters.py | 23 +++++ .../typescript_code_parameters_param.py | 25 +++++ .../types/auth_rules/v2_create_params.py | 22 ++++- .../types/auth_rules/v2_draft_params.py | 2 + .../v2_retrieve_features_response.py | 63 +----------- .../auth_rules/velocity_limit_filters.py | 64 ++++++++++++ .../velocity_limit_filters_param.py | 66 +++++++++++++ .../types/auth_rules/velocity_limit_params.py | 63 +----------- .../auth_rules/velocity_limit_params_param.py | 64 +----------- 16 files changed, 462 insertions(+), 193 deletions(-) create mode 100644 src/lithic/types/auth_rules/rule_feature.py create mode 100644 src/lithic/types/auth_rules/rule_feature_param.py create mode 100644 src/lithic/types/auth_rules/typescript_code_parameters.py create mode 100644 src/lithic/types/auth_rules/typescript_code_parameters_param.py create mode 100644 src/lithic/types/auth_rules/velocity_limit_filters.py create mode 100644 src/lithic/types/auth_rules/velocity_limit_filters_param.py diff --git a/.stats.yml b/.stats.yml index 8d817154..04ee12c4 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 188 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic%2Flithic-ee2b9f00d3a9e0000e25abc0774615d6ad3300ce17b2f094e71b0229a907760f.yml -openapi_spec_hash: 01d2cbf4ac692dba2f3831462db929e4 -config_hash: a45e6da4e7b46db4ff6819d1dba5d815 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic%2Flithic-1e902917b2eae41d549957e790eb6b137969e451efe673815647deba330fe05a.yml +openapi_spec_hash: 82cab06ce65462e60316939db630460a +config_hash: 00b60697e692f86b5be297d939962921 diff --git a/api.md b/api.md index 0fb2d5b8..ef4fa828 100644 --- a/api.md +++ b/api.md @@ -108,6 +108,9 @@ from lithic.types.auth_rules import ( EventStream, MerchantLockParameters, ReportStats, + RuleFeature, + TypescriptCodeParameters, + VelocityLimitFilters, VelocityLimitParams, VelocityLimitPeriod, V2ListResultsResponse, diff --git a/src/lithic/resources/auth_rules/v2/v2.py b/src/lithic/resources/auth_rules/v2/v2.py index 59a7ad20..3e2ef6ed 100644 --- a/src/lithic/resources/auth_rules/v2/v2.py +++ b/src/lithic/resources/auth_rules/v2/v2.py @@ -72,7 +72,7 @@ def create( self, *, parameters: v2_create_params.AccountLevelRuleParameters, - type: Literal["CONDITIONAL_BLOCK", "VELOCITY_LIMIT", "MERCHANT_LOCK", "CONDITIONAL_ACTION"], + type: Literal["CONDITIONAL_BLOCK", "VELOCITY_LIMIT", "MERCHANT_LOCK", "CONDITIONAL_ACTION", "TYPESCRIPT_CODE"], account_tokens: SequenceNotStr[str] | Omit = omit, business_account_tokens: SequenceNotStr[str] | Omit = omit, event_stream: EventStream | Omit = omit, @@ -101,6 +101,8 @@ def create( - `MERCHANT_LOCK`: AUTHORIZATION event stream. - `CONDITIONAL_ACTION`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, ACH_CREDIT_RECEIPT, or ACH_DEBIT_RECEIPT event stream. + - `TYPESCRIPT_CODE`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, + ACH_CREDIT_RECEIPT, or ACH_DEBIT_RECEIPT event stream. account_tokens: Account tokens to which the Auth Rule applies. @@ -126,7 +128,7 @@ def create( *, card_tokens: SequenceNotStr[str], parameters: v2_create_params.CardLevelRuleParameters, - type: Literal["CONDITIONAL_BLOCK", "VELOCITY_LIMIT", "MERCHANT_LOCK", "CONDITIONAL_ACTION"], + type: Literal["CONDITIONAL_BLOCK", "VELOCITY_LIMIT", "MERCHANT_LOCK", "CONDITIONAL_ACTION", "TYPESCRIPT_CODE"], event_stream: EventStream | Omit = omit, name: Optional[str] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -155,6 +157,8 @@ def create( - `MERCHANT_LOCK`: AUTHORIZATION event stream. - `CONDITIONAL_ACTION`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, ACH_CREDIT_RECEIPT, or ACH_DEBIT_RECEIPT event stream. + - `TYPESCRIPT_CODE`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, + ACH_CREDIT_RECEIPT, or ACH_DEBIT_RECEIPT event stream. event_stream: The event stream during which the rule will be evaluated. @@ -176,7 +180,7 @@ def create( *, parameters: v2_create_params.ProgramLevelRuleParameters, program_level: bool, - type: Literal["CONDITIONAL_BLOCK", "VELOCITY_LIMIT", "MERCHANT_LOCK", "CONDITIONAL_ACTION"], + type: Literal["CONDITIONAL_BLOCK", "VELOCITY_LIMIT", "MERCHANT_LOCK", "CONDITIONAL_ACTION", "TYPESCRIPT_CODE"], event_stream: EventStream | Omit = omit, excluded_card_tokens: SequenceNotStr[str] | Omit = omit, name: Optional[str] | Omit = omit, @@ -206,6 +210,8 @@ def create( - `MERCHANT_LOCK`: AUTHORIZATION event stream. - `CONDITIONAL_ACTION`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, ACH_CREDIT_RECEIPT, or ACH_DEBIT_RECEIPT event stream. + - `TYPESCRIPT_CODE`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, + ACH_CREDIT_RECEIPT, or ACH_DEBIT_RECEIPT event stream. event_stream: The event stream during which the rule will be evaluated. @@ -232,7 +238,7 @@ def create( parameters: v2_create_params.AccountLevelRuleParameters | v2_create_params.CardLevelRuleParameters | v2_create_params.ProgramLevelRuleParameters, - type: Literal["CONDITIONAL_BLOCK", "VELOCITY_LIMIT", "MERCHANT_LOCK", "CONDITIONAL_ACTION"], + type: Literal["CONDITIONAL_BLOCK", "VELOCITY_LIMIT", "MERCHANT_LOCK", "CONDITIONAL_ACTION", "TYPESCRIPT_CODE"], account_tokens: SequenceNotStr[str] | Omit = omit, business_account_tokens: SequenceNotStr[str] | Omit = omit, event_stream: EventStream | Omit = omit, @@ -890,7 +896,7 @@ async def create( self, *, parameters: v2_create_params.AccountLevelRuleParameters, - type: Literal["CONDITIONAL_BLOCK", "VELOCITY_LIMIT", "MERCHANT_LOCK", "CONDITIONAL_ACTION"], + type: Literal["CONDITIONAL_BLOCK", "VELOCITY_LIMIT", "MERCHANT_LOCK", "CONDITIONAL_ACTION", "TYPESCRIPT_CODE"], account_tokens: SequenceNotStr[str] | Omit = omit, business_account_tokens: SequenceNotStr[str] | Omit = omit, event_stream: EventStream | Omit = omit, @@ -919,6 +925,8 @@ async def create( - `MERCHANT_LOCK`: AUTHORIZATION event stream. - `CONDITIONAL_ACTION`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, ACH_CREDIT_RECEIPT, or ACH_DEBIT_RECEIPT event stream. + - `TYPESCRIPT_CODE`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, + ACH_CREDIT_RECEIPT, or ACH_DEBIT_RECEIPT event stream. account_tokens: Account tokens to which the Auth Rule applies. @@ -944,7 +952,7 @@ async def create( *, card_tokens: SequenceNotStr[str], parameters: v2_create_params.CardLevelRuleParameters, - type: Literal["CONDITIONAL_BLOCK", "VELOCITY_LIMIT", "MERCHANT_LOCK", "CONDITIONAL_ACTION"], + type: Literal["CONDITIONAL_BLOCK", "VELOCITY_LIMIT", "MERCHANT_LOCK", "CONDITIONAL_ACTION", "TYPESCRIPT_CODE"], event_stream: EventStream | Omit = omit, name: Optional[str] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -973,6 +981,8 @@ async def create( - `MERCHANT_LOCK`: AUTHORIZATION event stream. - `CONDITIONAL_ACTION`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, ACH_CREDIT_RECEIPT, or ACH_DEBIT_RECEIPT event stream. + - `TYPESCRIPT_CODE`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, + ACH_CREDIT_RECEIPT, or ACH_DEBIT_RECEIPT event stream. event_stream: The event stream during which the rule will be evaluated. @@ -994,7 +1004,7 @@ async def create( *, parameters: v2_create_params.ProgramLevelRuleParameters, program_level: bool, - type: Literal["CONDITIONAL_BLOCK", "VELOCITY_LIMIT", "MERCHANT_LOCK", "CONDITIONAL_ACTION"], + type: Literal["CONDITIONAL_BLOCK", "VELOCITY_LIMIT", "MERCHANT_LOCK", "CONDITIONAL_ACTION", "TYPESCRIPT_CODE"], event_stream: EventStream | Omit = omit, excluded_card_tokens: SequenceNotStr[str] | Omit = omit, name: Optional[str] | Omit = omit, @@ -1024,6 +1034,8 @@ async def create( - `MERCHANT_LOCK`: AUTHORIZATION event stream. - `CONDITIONAL_ACTION`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, ACH_CREDIT_RECEIPT, or ACH_DEBIT_RECEIPT event stream. + - `TYPESCRIPT_CODE`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, + ACH_CREDIT_RECEIPT, or ACH_DEBIT_RECEIPT event stream. event_stream: The event stream during which the rule will be evaluated. @@ -1050,7 +1062,7 @@ async def create( parameters: v2_create_params.AccountLevelRuleParameters | v2_create_params.CardLevelRuleParameters | v2_create_params.ProgramLevelRuleParameters, - type: Literal["CONDITIONAL_BLOCK", "VELOCITY_LIMIT", "MERCHANT_LOCK", "CONDITIONAL_ACTION"], + type: Literal["CONDITIONAL_BLOCK", "VELOCITY_LIMIT", "MERCHANT_LOCK", "CONDITIONAL_ACTION", "TYPESCRIPT_CODE"], account_tokens: SequenceNotStr[str] | Omit = omit, business_account_tokens: SequenceNotStr[str] | Omit = omit, event_stream: EventStream | Omit = omit, diff --git a/src/lithic/types/auth_rules/__init__.py b/src/lithic/types/auth_rules/__init__.py index a580f180..71af2699 100644 --- a/src/lithic/types/auth_rules/__init__.py +++ b/src/lithic/types/auth_rules/__init__.py @@ -5,30 +5,36 @@ from .auth_rule import AuthRule as AuthRule from .event_stream import EventStream as EventStream from .report_stats import ReportStats as ReportStats +from .rule_feature import RuleFeature as RuleFeature from .backtest_stats import BacktestStats as BacktestStats from .v2_list_params import V2ListParams as V2ListParams from .v2_draft_params import V2DraftParams as V2DraftParams from .v2_create_params import V2CreateParams as V2CreateParams from .v2_update_params import V2UpdateParams as V2UpdateParams from .conditional_value import ConditionalValue as ConditionalValue +from .rule_feature_param import RuleFeatureParam as RuleFeatureParam from .auth_rule_condition import AuthRuleCondition as AuthRuleCondition from .conditional_attribute import ConditionalAttribute as ConditionalAttribute from .conditional_operation import ConditionalOperation as ConditionalOperation from .velocity_limit_params import VelocityLimitParams as VelocityLimitParams from .velocity_limit_period import VelocityLimitPeriod as VelocityLimitPeriod from .v2_list_results_params import V2ListResultsParams as V2ListResultsParams +from .velocity_limit_filters import VelocityLimitFilters as VelocityLimitFilters from .conditional_value_param import ConditionalValueParam as ConditionalValueParam from .merchant_lock_parameters import MerchantLockParameters as MerchantLockParameters from .v2_list_results_response import V2ListResultsResponse as V2ListResultsResponse from .auth_rule_condition_param import AuthRuleConditionParam as AuthRuleConditionParam from .v2_retrieve_report_params import V2RetrieveReportParams as V2RetrieveReportParams +from .typescript_code_parameters import TypescriptCodeParameters as TypescriptCodeParameters from .v2_retrieve_features_params import V2RetrieveFeaturesParams as V2RetrieveFeaturesParams from .v2_retrieve_report_response import V2RetrieveReportResponse as V2RetrieveReportResponse from .velocity_limit_params_param import VelocityLimitParamsParam as VelocityLimitParamsParam from .velocity_limit_period_param import VelocityLimitPeriodParam as VelocityLimitPeriodParam from .conditional_block_parameters import ConditionalBlockParameters as ConditionalBlockParameters +from .velocity_limit_filters_param import VelocityLimitFiltersParam as VelocityLimitFiltersParam from .v2_retrieve_features_response import V2RetrieveFeaturesResponse as V2RetrieveFeaturesResponse from .merchant_lock_parameters_param import MerchantLockParametersParam as MerchantLockParametersParam +from .typescript_code_parameters_param import TypescriptCodeParametersParam as TypescriptCodeParametersParam from .conditional_3ds_action_parameters import Conditional3DSActionParameters as Conditional3DSActionParameters from .conditional_ach_action_parameters import ConditionalACHActionParameters as ConditionalACHActionParameters from .conditional_block_parameters_param import ConditionalBlockParametersParam as ConditionalBlockParametersParam diff --git a/src/lithic/types/auth_rules/auth_rule.py b/src/lithic/types/auth_rules/auth_rule.py index 3708f7e1..f85d7c04 100644 --- a/src/lithic/types/auth_rules/auth_rule.py +++ b/src/lithic/types/auth_rules/auth_rule.py @@ -7,6 +7,7 @@ from .event_stream import EventStream from .velocity_limit_params import VelocityLimitParams from .merchant_lock_parameters import MerchantLockParameters +from .typescript_code_parameters import TypescriptCodeParameters from .conditional_block_parameters import ConditionalBlockParameters from .conditional_3ds_action_parameters import Conditional3DSActionParameters from .conditional_ach_action_parameters import ConditionalACHActionParameters @@ -23,6 +24,7 @@ ConditionalAuthorizationActionParameters, ConditionalACHActionParameters, ConditionalTokenizationActionParameters, + TypescriptCodeParameters, ] @@ -45,13 +47,34 @@ class CurrentVersion(BaseModel): ConditionalAuthorizationActionParameters, ConditionalACHActionParameters, ConditionalTokenizationActionParameters, + TypescriptCodeParameters, ] class DraftVersion(BaseModel): + error: Optional[str] = None + """An error message if the draft version failed compilation. + + Populated when `state` is `ERROR`, `null` otherwise. + """ + parameters: DraftVersionParameters """Parameters for the Auth Rule""" + state: Literal["PENDING", "SHADOWING", "ERROR"] + """The state of the draft version. + + Most rules are created synchronously and the state is immediately `SHADOWING`. + Rules backed by TypeScript code are compiled asynchronously — the state starts + as `PENDING` and transitions to `SHADOWING` on success or `ERROR` on failure. + + - `PENDING`: Compilation of the rule is in progress (TypeScript rules only). + - `SHADOWING`: The draft version is ready and evaluating in shadow mode + alongside the current active version. It can be promoted to the active + version. + - `ERROR`: Compilation of the rule failed. Check the `error` field for details. + """ + version: int """ The version of the rule, this is incremented whenever the rule's parameters @@ -94,7 +117,7 @@ class AuthRule(BaseModel): state: Literal["ACTIVE", "INACTIVE"] """The state of the Auth Rule""" - type: Literal["CONDITIONAL_BLOCK", "VELOCITY_LIMIT", "MERCHANT_LOCK", "CONDITIONAL_ACTION"] + type: Literal["CONDITIONAL_BLOCK", "VELOCITY_LIMIT", "MERCHANT_LOCK", "CONDITIONAL_ACTION", "TYPESCRIPT_CODE"] """The type of Auth Rule. For certain rule types, this determines the event stream during which it will be @@ -107,6 +130,8 @@ class AuthRule(BaseModel): - `MERCHANT_LOCK`: AUTHORIZATION event stream. - `CONDITIONAL_ACTION`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, ACH_CREDIT_RECEIPT, or ACH_DEBIT_RECEIPT event stream. + - `TYPESCRIPT_CODE`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, + ACH_CREDIT_RECEIPT, or ACH_DEBIT_RECEIPT event stream. """ excluded_card_tokens: Optional[List[str]] = None diff --git a/src/lithic/types/auth_rules/rule_feature.py b/src/lithic/types/auth_rules/rule_feature.py new file mode 100644 index 00000000..40fffc14 --- /dev/null +++ b/src/lithic/types/auth_rules/rule_feature.py @@ -0,0 +1,96 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Union, Optional +from typing_extensions import Literal, TypeAlias + +from ..._models import BaseModel +from .velocity_limit_period import VelocityLimitPeriod +from .velocity_limit_filters import VelocityLimitFilters + +__all__ = [ + "RuleFeature", + "AuthorizationFeature", + "AuthenticationFeature", + "TokenizationFeature", + "ACHReceiptFeature", + "CardFeature", + "AccountHolderFeature", + "IPMetadataFeature", + "SpendVelocityFeature", +] + + +class AuthorizationFeature(BaseModel): + type: Literal["AUTHORIZATION"] + + name: Optional[str] = None + """The variable name for this feature in the rule function signature""" + + +class AuthenticationFeature(BaseModel): + type: Literal["AUTHENTICATION"] + + name: Optional[str] = None + """The variable name for this feature in the rule function signature""" + + +class TokenizationFeature(BaseModel): + type: Literal["TOKENIZATION"] + + name: Optional[str] = None + """The variable name for this feature in the rule function signature""" + + +class ACHReceiptFeature(BaseModel): + type: Literal["ACH_RECEIPT"] + + name: Optional[str] = None + """The variable name for this feature in the rule function signature""" + + +class CardFeature(BaseModel): + type: Literal["CARD"] + + name: Optional[str] = None + """The variable name for this feature in the rule function signature""" + + +class AccountHolderFeature(BaseModel): + type: Literal["ACCOUNT_HOLDER"] + + name: Optional[str] = None + """The variable name for this feature in the rule function signature""" + + +class IPMetadataFeature(BaseModel): + type: Literal["IP_METADATA"] + + name: Optional[str] = None + """The variable name for this feature in the rule function signature""" + + +class SpendVelocityFeature(BaseModel): + period: VelocityLimitPeriod + """Velocity over the current day since 00:00 / 12 AM in Eastern Time""" + + scope: Literal["CARD", "ACCOUNT"] + """The scope the velocity is calculated for""" + + type: Literal["SPEND_VELOCITY"] + + filters: Optional[VelocityLimitFilters] = None + + name: Optional[str] = None + """The variable name for this feature in the rule function signature""" + + +RuleFeature: TypeAlias = Union[ + AuthorizationFeature, + AuthenticationFeature, + TokenizationFeature, + ACHReceiptFeature, + CardFeature, + AccountHolderFeature, + IPMetadataFeature, + SpendVelocityFeature, +] diff --git a/src/lithic/types/auth_rules/rule_feature_param.py b/src/lithic/types/auth_rules/rule_feature_param.py new file mode 100644 index 00000000..0d32b726 --- /dev/null +++ b/src/lithic/types/auth_rules/rule_feature_param.py @@ -0,0 +1,97 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Union +from typing_extensions import Literal, Required, TypeAlias, TypedDict + +from .velocity_limit_period_param import VelocityLimitPeriodParam +from .velocity_limit_filters_param import VelocityLimitFiltersParam + +__all__ = [ + "RuleFeatureParam", + "AuthorizationFeature", + "AuthenticationFeature", + "TokenizationFeature", + "ACHReceiptFeature", + "CardFeature", + "AccountHolderFeature", + "IPMetadataFeature", + "SpendVelocityFeature", +] + + +class AuthorizationFeature(TypedDict, total=False): + type: Required[Literal["AUTHORIZATION"]] + + name: str + """The variable name for this feature in the rule function signature""" + + +class AuthenticationFeature(TypedDict, total=False): + type: Required[Literal["AUTHENTICATION"]] + + name: str + """The variable name for this feature in the rule function signature""" + + +class TokenizationFeature(TypedDict, total=False): + type: Required[Literal["TOKENIZATION"]] + + name: str + """The variable name for this feature in the rule function signature""" + + +class ACHReceiptFeature(TypedDict, total=False): + type: Required[Literal["ACH_RECEIPT"]] + + name: str + """The variable name for this feature in the rule function signature""" + + +class CardFeature(TypedDict, total=False): + type: Required[Literal["CARD"]] + + name: str + """The variable name for this feature in the rule function signature""" + + +class AccountHolderFeature(TypedDict, total=False): + type: Required[Literal["ACCOUNT_HOLDER"]] + + name: str + """The variable name for this feature in the rule function signature""" + + +class IPMetadataFeature(TypedDict, total=False): + type: Required[Literal["IP_METADATA"]] + + name: str + """The variable name for this feature in the rule function signature""" + + +class SpendVelocityFeature(TypedDict, total=False): + period: Required[VelocityLimitPeriodParam] + """Velocity over the current day since 00:00 / 12 AM in Eastern Time""" + + scope: Required[Literal["CARD", "ACCOUNT"]] + """The scope the velocity is calculated for""" + + type: Required[Literal["SPEND_VELOCITY"]] + + filters: VelocityLimitFiltersParam + + name: str + """The variable name for this feature in the rule function signature""" + + +RuleFeatureParam: TypeAlias = Union[ + AuthorizationFeature, + AuthenticationFeature, + TokenizationFeature, + ACHReceiptFeature, + CardFeature, + AccountHolderFeature, + IPMetadataFeature, + SpendVelocityFeature, +] diff --git a/src/lithic/types/auth_rules/typescript_code_parameters.py b/src/lithic/types/auth_rules/typescript_code_parameters.py new file mode 100644 index 00000000..d80a49db --- /dev/null +++ b/src/lithic/types/auth_rules/typescript_code_parameters.py @@ -0,0 +1,23 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List + +from ..._models import BaseModel +from .rule_feature import RuleFeature + +__all__ = ["TypescriptCodeParameters"] + + +class TypescriptCodeParameters(BaseModel): + """Parameters for defining a TypeScript code rule""" + + code: str + """The TypeScript source code of the rule. + + Must define a `rule()` function that accepts the declared features as positional + arguments (in the same order as the `features` array) and returns an array of + actions. + """ + + features: List[RuleFeature] + """Features available to the TypeScript code at evaluation time""" diff --git a/src/lithic/types/auth_rules/typescript_code_parameters_param.py b/src/lithic/types/auth_rules/typescript_code_parameters_param.py new file mode 100644 index 00000000..3871954d --- /dev/null +++ b/src/lithic/types/auth_rules/typescript_code_parameters_param.py @@ -0,0 +1,25 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Iterable +from typing_extensions import Required, TypedDict + +from .rule_feature_param import RuleFeatureParam + +__all__ = ["TypescriptCodeParametersParam"] + + +class TypescriptCodeParametersParam(TypedDict, total=False): + """Parameters for defining a TypeScript code rule""" + + code: Required[str] + """The TypeScript source code of the rule. + + Must define a `rule()` function that accepts the declared features as positional + arguments (in the same order as the `features` array) and returns an array of + actions. + """ + + features: Required[Iterable[RuleFeatureParam]] + """Features available to the TypeScript code at evaluation time""" diff --git a/src/lithic/types/auth_rules/v2_create_params.py b/src/lithic/types/auth_rules/v2_create_params.py index 2af4efd9..3cbae7f4 100644 --- a/src/lithic/types/auth_rules/v2_create_params.py +++ b/src/lithic/types/auth_rules/v2_create_params.py @@ -9,6 +9,7 @@ from .event_stream import EventStream from .velocity_limit_params_param import VelocityLimitParamsParam from .merchant_lock_parameters_param import MerchantLockParametersParam +from .typescript_code_parameters_param import TypescriptCodeParametersParam from .conditional_block_parameters_param import ConditionalBlockParametersParam from .conditional_3ds_action_parameters_param import Conditional3DSActionParametersParam from .conditional_ach_action_parameters_param import ConditionalACHActionParametersParam @@ -30,7 +31,9 @@ class AccountLevelRule(TypedDict, total=False): parameters: Required[AccountLevelRuleParameters] """Parameters for the Auth Rule""" - type: Required[Literal["CONDITIONAL_BLOCK", "VELOCITY_LIMIT", "MERCHANT_LOCK", "CONDITIONAL_ACTION"]] + type: Required[ + Literal["CONDITIONAL_BLOCK", "VELOCITY_LIMIT", "MERCHANT_LOCK", "CONDITIONAL_ACTION", "TYPESCRIPT_CODE"] + ] """The type of Auth Rule. For certain rule types, this determines the event stream during which it will be @@ -43,6 +46,8 @@ class AccountLevelRule(TypedDict, total=False): - `MERCHANT_LOCK`: AUTHORIZATION event stream. - `CONDITIONAL_ACTION`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, ACH_CREDIT_RECEIPT, or ACH_DEBIT_RECEIPT event stream. + - `TYPESCRIPT_CODE`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, + ACH_CREDIT_RECEIPT, or ACH_DEBIT_RECEIPT event stream. """ account_tokens: SequenceNotStr[str] @@ -66,6 +71,7 @@ class AccountLevelRule(TypedDict, total=False): ConditionalAuthorizationActionParametersParam, ConditionalACHActionParametersParam, ConditionalTokenizationActionParametersParam, + TypescriptCodeParametersParam, ] @@ -76,7 +82,9 @@ class CardLevelRule(TypedDict, total=False): parameters: Required[CardLevelRuleParameters] """Parameters for the Auth Rule""" - type: Required[Literal["CONDITIONAL_BLOCK", "VELOCITY_LIMIT", "MERCHANT_LOCK", "CONDITIONAL_ACTION"]] + type: Required[ + Literal["CONDITIONAL_BLOCK", "VELOCITY_LIMIT", "MERCHANT_LOCK", "CONDITIONAL_ACTION", "TYPESCRIPT_CODE"] + ] """The type of Auth Rule. For certain rule types, this determines the event stream during which it will be @@ -89,6 +97,8 @@ class CardLevelRule(TypedDict, total=False): - `MERCHANT_LOCK`: AUTHORIZATION event stream. - `CONDITIONAL_ACTION`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, ACH_CREDIT_RECEIPT, or ACH_DEBIT_RECEIPT event stream. + - `TYPESCRIPT_CODE`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, + ACH_CREDIT_RECEIPT, or ACH_DEBIT_RECEIPT event stream. """ event_stream: EventStream @@ -106,6 +116,7 @@ class CardLevelRule(TypedDict, total=False): ConditionalAuthorizationActionParametersParam, ConditionalACHActionParametersParam, ConditionalTokenizationActionParametersParam, + TypescriptCodeParametersParam, ] @@ -116,7 +127,9 @@ class ProgramLevelRule(TypedDict, total=False): program_level: Required[bool] """Whether the Auth Rule applies to all authorizations on the card program.""" - type: Required[Literal["CONDITIONAL_BLOCK", "VELOCITY_LIMIT", "MERCHANT_LOCK", "CONDITIONAL_ACTION"]] + type: Required[ + Literal["CONDITIONAL_BLOCK", "VELOCITY_LIMIT", "MERCHANT_LOCK", "CONDITIONAL_ACTION", "TYPESCRIPT_CODE"] + ] """The type of Auth Rule. For certain rule types, this determines the event stream during which it will be @@ -129,6 +142,8 @@ class ProgramLevelRule(TypedDict, total=False): - `MERCHANT_LOCK`: AUTHORIZATION event stream. - `CONDITIONAL_ACTION`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, ACH_CREDIT_RECEIPT, or ACH_DEBIT_RECEIPT event stream. + - `TYPESCRIPT_CODE`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, + ACH_CREDIT_RECEIPT, or ACH_DEBIT_RECEIPT event stream. """ event_stream: EventStream @@ -149,6 +164,7 @@ class ProgramLevelRule(TypedDict, total=False): ConditionalAuthorizationActionParametersParam, ConditionalACHActionParametersParam, ConditionalTokenizationActionParametersParam, + TypescriptCodeParametersParam, ] V2CreateParams: TypeAlias = Union[AccountLevelRule, CardLevelRule, ProgramLevelRule] diff --git a/src/lithic/types/auth_rules/v2_draft_params.py b/src/lithic/types/auth_rules/v2_draft_params.py index 2352a6b7..2b0d4363 100644 --- a/src/lithic/types/auth_rules/v2_draft_params.py +++ b/src/lithic/types/auth_rules/v2_draft_params.py @@ -7,6 +7,7 @@ from .velocity_limit_params_param import VelocityLimitParamsParam from .merchant_lock_parameters_param import MerchantLockParametersParam +from .typescript_code_parameters_param import TypescriptCodeParametersParam from .conditional_block_parameters_param import ConditionalBlockParametersParam from .conditional_3ds_action_parameters_param import Conditional3DSActionParametersParam from .conditional_ach_action_parameters_param import ConditionalACHActionParametersParam @@ -29,4 +30,5 @@ class V2DraftParams(TypedDict, total=False): ConditionalAuthorizationActionParametersParam, ConditionalACHActionParametersParam, ConditionalTokenizationActionParametersParam, + TypescriptCodeParametersParam, ] diff --git a/src/lithic/types/auth_rules/v2_retrieve_features_response.py b/src/lithic/types/auth_rules/v2_retrieve_features_response.py index 708a3fdc..4bfe4037 100644 --- a/src/lithic/types/auth_rules/v2_retrieve_features_response.py +++ b/src/lithic/types/auth_rules/v2_retrieve_features_response.py @@ -1,69 +1,14 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Optional +from typing import List from datetime import datetime from typing_extensions import Literal from ..._models import BaseModel from .velocity_limit_period import VelocityLimitPeriod +from .velocity_limit_filters import VelocityLimitFilters -__all__ = ["V2RetrieveFeaturesResponse", "Feature", "FeatureFilters", "FeatureValue"] - - -class FeatureFilters(BaseModel): - exclude_countries: Optional[List[str]] = None - """ISO-3166-1 alpha-3 Country Codes to exclude from the velocity calculation. - - Transactions matching any of the provided will be excluded from the calculated - velocity. - """ - - exclude_mccs: Optional[List[str]] = None - """Merchant Category Codes to exclude from the velocity calculation. - - Transactions matching this MCC will be excluded from the calculated velocity. - """ - - include_countries: Optional[List[str]] = None - """ISO-3166-1 alpha-3 Country Codes to include in the velocity calculation. - - Transactions not matching any of the provided will not be included in the - calculated velocity. - """ - - include_mccs: Optional[List[str]] = None - """Merchant Category Codes to include in the velocity calculation. - - Transactions not matching this MCC will not be included in the calculated - velocity. - """ - - include_pan_entry_modes: Optional[ - List[ - Literal[ - "AUTO_ENTRY", - "BAR_CODE", - "CONTACTLESS", - "CREDENTIAL_ON_FILE", - "ECOMMERCE", - "ERROR_KEYED", - "ERROR_MAGNETIC_STRIPE", - "ICC", - "KEY_ENTERED", - "MAGNETIC_STRIPE", - "MANUAL", - "OCR", - "SECURE_CARDLESS", - "UNSPECIFIED", - "UNKNOWN", - ] - ] - ] = None - """PAN entry modes to include in the velocity calculation. - - Transactions not matching any of the provided will not be included in the - calculated velocity. - """ +__all__ = ["V2RetrieveFeaturesResponse", "Feature", "FeatureValue"] class FeatureValue(BaseModel): @@ -82,7 +27,7 @@ class FeatureValue(BaseModel): class Feature(BaseModel): - filters: FeatureFilters + filters: VelocityLimitFilters period: VelocityLimitPeriod """Velocity over the current day since 00:00 / 12 AM in Eastern Time""" diff --git a/src/lithic/types/auth_rules/velocity_limit_filters.py b/src/lithic/types/auth_rules/velocity_limit_filters.py new file mode 100644 index 00000000..97bded04 --- /dev/null +++ b/src/lithic/types/auth_rules/velocity_limit_filters.py @@ -0,0 +1,64 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from typing_extensions import Literal + +from ..._models import BaseModel + +__all__ = ["VelocityLimitFilters"] + + +class VelocityLimitFilters(BaseModel): + exclude_countries: Optional[List[str]] = None + """ISO-3166-1 alpha-3 Country Codes to exclude from the velocity calculation. + + Transactions matching any of the provided will be excluded from the calculated + velocity. + """ + + exclude_mccs: Optional[List[str]] = None + """Merchant Category Codes to exclude from the velocity calculation. + + Transactions matching this MCC will be excluded from the calculated velocity. + """ + + include_countries: Optional[List[str]] = None + """ISO-3166-1 alpha-3 Country Codes to include in the velocity calculation. + + Transactions not matching any of the provided will not be included in the + calculated velocity. + """ + + include_mccs: Optional[List[str]] = None + """Merchant Category Codes to include in the velocity calculation. + + Transactions not matching this MCC will not be included in the calculated + velocity. + """ + + include_pan_entry_modes: Optional[ + List[ + Literal[ + "AUTO_ENTRY", + "BAR_CODE", + "CONTACTLESS", + "CREDENTIAL_ON_FILE", + "ECOMMERCE", + "ERROR_KEYED", + "ERROR_MAGNETIC_STRIPE", + "ICC", + "KEY_ENTERED", + "MAGNETIC_STRIPE", + "MANUAL", + "OCR", + "SECURE_CARDLESS", + "UNSPECIFIED", + "UNKNOWN", + ] + ] + ] = None + """PAN entry modes to include in the velocity calculation. + + Transactions not matching any of the provided will not be included in the + calculated velocity. + """ diff --git a/src/lithic/types/auth_rules/velocity_limit_filters_param.py b/src/lithic/types/auth_rules/velocity_limit_filters_param.py new file mode 100644 index 00000000..e9a3498b --- /dev/null +++ b/src/lithic/types/auth_rules/velocity_limit_filters_param.py @@ -0,0 +1,66 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import List, Optional +from typing_extensions import Literal, TypedDict + +from ..._types import SequenceNotStr + +__all__ = ["VelocityLimitFiltersParam"] + + +class VelocityLimitFiltersParam(TypedDict, total=False): + exclude_countries: Optional[SequenceNotStr[str]] + """ISO-3166-1 alpha-3 Country Codes to exclude from the velocity calculation. + + Transactions matching any of the provided will be excluded from the calculated + velocity. + """ + + exclude_mccs: Optional[SequenceNotStr[str]] + """Merchant Category Codes to exclude from the velocity calculation. + + Transactions matching this MCC will be excluded from the calculated velocity. + """ + + include_countries: Optional[SequenceNotStr[str]] + """ISO-3166-1 alpha-3 Country Codes to include in the velocity calculation. + + Transactions not matching any of the provided will not be included in the + calculated velocity. + """ + + include_mccs: Optional[SequenceNotStr[str]] + """Merchant Category Codes to include in the velocity calculation. + + Transactions not matching this MCC will not be included in the calculated + velocity. + """ + + include_pan_entry_modes: Optional[ + List[ + Literal[ + "AUTO_ENTRY", + "BAR_CODE", + "CONTACTLESS", + "CREDENTIAL_ON_FILE", + "ECOMMERCE", + "ERROR_KEYED", + "ERROR_MAGNETIC_STRIPE", + "ICC", + "KEY_ENTERED", + "MAGNETIC_STRIPE", + "MANUAL", + "OCR", + "SECURE_CARDLESS", + "UNSPECIFIED", + "UNKNOWN", + ] + ] + ] + """PAN entry modes to include in the velocity calculation. + + Transactions not matching any of the provided will not be included in the + calculated velocity. + """ diff --git a/src/lithic/types/auth_rules/velocity_limit_params.py b/src/lithic/types/auth_rules/velocity_limit_params.py index fbbe32c9..061a8de7 100644 --- a/src/lithic/types/auth_rules/velocity_limit_params.py +++ b/src/lithic/types/auth_rules/velocity_limit_params.py @@ -1,68 +1,13 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Optional +from typing import Optional from typing_extensions import Literal from ..._models import BaseModel from .velocity_limit_period import VelocityLimitPeriod +from .velocity_limit_filters import VelocityLimitFilters -__all__ = ["VelocityLimitParams", "Filters"] - - -class Filters(BaseModel): - exclude_countries: Optional[List[str]] = None - """ISO-3166-1 alpha-3 Country Codes to exclude from the velocity calculation. - - Transactions matching any of the provided will be excluded from the calculated - velocity. - """ - - exclude_mccs: Optional[List[str]] = None - """Merchant Category Codes to exclude from the velocity calculation. - - Transactions matching this MCC will be excluded from the calculated velocity. - """ - - include_countries: Optional[List[str]] = None - """ISO-3166-1 alpha-3 Country Codes to include in the velocity calculation. - - Transactions not matching any of the provided will not be included in the - calculated velocity. - """ - - include_mccs: Optional[List[str]] = None - """Merchant Category Codes to include in the velocity calculation. - - Transactions not matching this MCC will not be included in the calculated - velocity. - """ - - include_pan_entry_modes: Optional[ - List[ - Literal[ - "AUTO_ENTRY", - "BAR_CODE", - "CONTACTLESS", - "CREDENTIAL_ON_FILE", - "ECOMMERCE", - "ERROR_KEYED", - "ERROR_MAGNETIC_STRIPE", - "ICC", - "KEY_ENTERED", - "MAGNETIC_STRIPE", - "MANUAL", - "OCR", - "SECURE_CARDLESS", - "UNSPECIFIED", - "UNKNOWN", - ] - ] - ] = None - """PAN entry modes to include in the velocity calculation. - - Transactions not matching any of the provided will not be included in the - calculated velocity. - """ +__all__ = ["VelocityLimitParams"] class VelocityLimitParams(BaseModel): @@ -72,7 +17,7 @@ class VelocityLimitParams(BaseModel): scope: Literal["CARD", "ACCOUNT"] """The scope the velocity is calculated for""" - filters: Optional[Filters] = None + filters: Optional[VelocityLimitFilters] = None limit_amount: Optional[int] = None """ diff --git a/src/lithic/types/auth_rules/velocity_limit_params_param.py b/src/lithic/types/auth_rules/velocity_limit_params_param.py index 1bee3cbb..e91557fa 100644 --- a/src/lithic/types/auth_rules/velocity_limit_params_param.py +++ b/src/lithic/types/auth_rules/velocity_limit_params_param.py @@ -2,69 +2,13 @@ from __future__ import annotations -from typing import List, Optional +from typing import Optional from typing_extensions import Literal, Required, TypedDict -from ..._types import SequenceNotStr from .velocity_limit_period_param import VelocityLimitPeriodParam +from .velocity_limit_filters_param import VelocityLimitFiltersParam -__all__ = ["VelocityLimitParamsParam", "Filters"] - - -class Filters(TypedDict, total=False): - exclude_countries: Optional[SequenceNotStr[str]] - """ISO-3166-1 alpha-3 Country Codes to exclude from the velocity calculation. - - Transactions matching any of the provided will be excluded from the calculated - velocity. - """ - - exclude_mccs: Optional[SequenceNotStr[str]] - """Merchant Category Codes to exclude from the velocity calculation. - - Transactions matching this MCC will be excluded from the calculated velocity. - """ - - include_countries: Optional[SequenceNotStr[str]] - """ISO-3166-1 alpha-3 Country Codes to include in the velocity calculation. - - Transactions not matching any of the provided will not be included in the - calculated velocity. - """ - - include_mccs: Optional[SequenceNotStr[str]] - """Merchant Category Codes to include in the velocity calculation. - - Transactions not matching this MCC will not be included in the calculated - velocity. - """ - - include_pan_entry_modes: Optional[ - List[ - Literal[ - "AUTO_ENTRY", - "BAR_CODE", - "CONTACTLESS", - "CREDENTIAL_ON_FILE", - "ECOMMERCE", - "ERROR_KEYED", - "ERROR_MAGNETIC_STRIPE", - "ICC", - "KEY_ENTERED", - "MAGNETIC_STRIPE", - "MANUAL", - "OCR", - "SECURE_CARDLESS", - "UNSPECIFIED", - "UNKNOWN", - ] - ] - ] - """PAN entry modes to include in the velocity calculation. - - Transactions not matching any of the provided will not be included in the - calculated velocity. - """ +__all__ = ["VelocityLimitParamsParam"] class VelocityLimitParamsParam(TypedDict, total=False): @@ -74,7 +18,7 @@ class VelocityLimitParamsParam(TypedDict, total=False): scope: Required[Literal["CARD", "ACCOUNT"]] """The scope the velocity is calculated for""" - filters: Filters + filters: VelocityLimitFiltersParam limit_amount: Optional[int] """ From f23d3022b0b0a860db16cefc008153f09c0bae48 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 10 Mar 2026 08:19:03 +0000 Subject: [PATCH 4/5] fix(api): Disable MCP server to fix TypeScript SDK package publishing --- .stats.yml | 2 +- README.md | 9 --------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/.stats.yml b/.stats.yml index 04ee12c4..9a8e226d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 188 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic%2Flithic-1e902917b2eae41d549957e790eb6b137969e451efe673815647deba330fe05a.yml openapi_spec_hash: 82cab06ce65462e60316939db630460a -config_hash: 00b60697e692f86b5be297d939962921 +config_hash: 8799cfd589579f105ef8696a6d664c71 diff --git a/README.md b/README.md index d91fcf39..0aaa73df 100644 --- a/README.md +++ b/README.md @@ -7,15 +7,6 @@ The Lithic Python library provides convenient access to the Lithic REST API from application. The library includes type definitions for all request params and response fields, and offers both synchronous and asynchronous clients powered by [httpx](https://github.com/encode/httpx). -## MCP Server - -Use the Lithic MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application. - -[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=lithic-mcp&config=eyJuYW1lIjoibGl0aGljLW1jcCIsInRyYW5zcG9ydCI6Imh0dHAiLCJ1cmwiOiJodHRwczovL2xpdGhpYy5zdGxtY3AuY29tIiwiaGVhZGVycyI6eyJ4LWxpdGhpYy1hcGkta2V5IjoiTXkgTGl0aGljIEFQSSBLZXkifX0) -[![Install in VS Code](https://img.shields.io/badge/_-Add_to_VS_Code-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZmlsbD0iI0VFRSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAuMjM1IDM5Ljg4NGEyLjQ5MSAyLjQ5MSAwIDAgMS0xLjc4MS0uNzNMMTIuNyAyNC43OGwtMy40NiAyLjYyNC0zLjQwNiAyLjU4MmExLjY2NSAxLjY2NSAwIDAgMS0xLjA4Mi4zMzggMS42NjQgMS42NjQgMCAwIDEtMS4wNDYtLjQzMWwtMi4yLTJhMS42NjYgMS42NjYgMCAwIDEgMC0yLjQ2M0w3LjQ1OCAyMCA0LjY3IDE3LjQ1MyAxLjUwNyAxNC41N2ExLjY2NSAxLjY2NSAwIDAgMSAwLTIuNDYzbDIuMi0yYTEuNjY1IDEuNjY1IDAgMCAxIDIuMTMtLjA5N2w2Ljg2MyA1LjIwOUwyOC40NTIuODQ0YTIuNDg4IDIuNDg4IDAgMCAxIDEuODQxLS43MjljLjM1MS4wMDkuNjk5LjA5MSAxLjAxOS4yNDVsOC4yMzYgMy45NjFhMi41IDIuNSAwIDAgMSAxLjQxNSAyLjI1M3YuMDk5LS4wNDVWMzMuMzd2LS4wNDUuMDk1YTIuNTAxIDIuNTAxIDAgMCAxLTEuNDE2IDIuMjU3bC04LjIzNSAzLjk2MWEyLjQ5MiAyLjQ5MiAwIDAgMS0xLjA3Ny4yNDZabS43MTYtMjguOTQ3LTExLjk0OCA5LjA2MiAxMS45NTIgOS4wNjUtLjAwNC0xOC4xMjdaIi8+PC9zdmc+)](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22lithic-mcp%22%2C%22type%22%3A%22http%22%2C%22url%22%3A%22https%3A%2F%2Flithic.stlmcp.com%22%2C%22headers%22%3A%7B%22x-lithic-api-key%22%3A%22My%20Lithic%20API%20Key%22%7D%7D) - -> Note: You may need to set environment variables in your MCP client. - ## Documentation The REST API documentation can be found on [docs.lithic.com](https://docs.lithic.com). The full API of this library can be found in [api.md](api.md). From e029b377b44a07d5121c18313987486762544f08 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 10 Mar 2026 08:19:29 +0000 Subject: [PATCH 5/5] release: 0.118.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 19 +++++++++++++++++++ pyproject.toml | 2 +- src/lithic/_version.py | 2 +- 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index b6700282..617f7502 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.117.0" + ".": "0.118.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index b82d9dc5..c350af99 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,24 @@ # Changelog +## 0.118.0 (2026-03-10) + +Full Changelog: [v0.117.0...v0.118.0](https://github.com/lithic-com/lithic-python/compare/v0.117.0...v0.118.0) + +### Features + +* **api:** add EARLY_DIRECT_DEPOSIT_FLOAT type to financial accounts ([6b3cfd6](https://github.com/lithic-com/lithic-python/commit/6b3cfd6ac06980b80d110b19b20697068bbeeee9)) +* **api:** add typescript_code rule type, state/error fields to auth_rules ([f6dc800](https://github.com/lithic-com/lithic-python/commit/f6dc800f95e413c8a9436c5a966a2bb12d27b6b6)) + + +### Bug Fixes + +* **api:** Disable MCP server to fix TypeScript SDK package publishing ([f23d302](https://github.com/lithic-com/lithic-python/commit/f23d3022b0b0a860db16cefc008153f09c0bae48)) + + +### Chores + +* **internal:** codegen related update ([845458d](https://github.com/lithic-com/lithic-python/commit/845458d17d741e51d1ef212fac9de9a9cbd8b0e5)) + ## 0.117.0 (2026-03-05) Full Changelog: [v0.116.0...v0.117.0](https://github.com/lithic-com/lithic-python/compare/v0.116.0...v0.117.0) diff --git a/pyproject.toml b/pyproject.toml index 33fa6251..9df22bbb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "lithic" -version = "0.117.0" +version = "0.118.0" description = "The official Python library for the lithic API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/lithic/_version.py b/src/lithic/_version.py index 39276f3d..86511f28 100644 --- a/src/lithic/_version.py +++ b/src/lithic/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "lithic" -__version__ = "0.117.0" # x-release-please-version +__version__ = "0.118.0" # x-release-please-version