diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 37e99723..a24ae611 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.130.0" + ".": "0.131.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 39c488a2..8a82b350 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 213 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic/lithic-59c09c7355b21b663e001d2ee1086ebd0a70d9b5433823282bca296eedff9eb0.yml -openapi_spec_hash: d9c3b932c810809abc6e973d662ad376 -config_hash: 337a99d8cc30006358b7bc2531401669 +configured_endpoints: 214 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic/lithic-ba08fed613d6854a75abf98f01d4178cb8bee759c7e095b2441733f4f928d12c.yml +openapi_spec_hash: 342b408b7ab6cfe1b27e5b1582aead28 +config_hash: f6d04d790aaddf639fc04b7f0092e7ec diff --git a/CHANGELOG.md b/CHANGELOG.md index 93037f6b..f90e30f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,24 @@ # Changelog +## 0.131.0 (2026-08-13) + +Full Changelog: [v0.130.0...v0.131.0](https://github.com/lithic-com/lithic-python/compare/v0.130.0...v0.131.0) + +### Features + +* **api:** add blockchain_addresses field to financial account ([168e194](https://github.com/lithic-com/lithic-python/commit/168e194dce255e6b907a65b3387dffec89ca0426)) +* **api:** Add limit_cash_amount and limit_cash_count to VelocityLimit template ([64068f8](https://github.com/lithic-com/lithic-python/commit/64068f89bd9400b4e684b8eb1fdf5bdede893a36)) +* **api:** add PROGRAM scope to auth_rules and case entity types ([7d67d35](https://github.com/lithic-com/lithic-python/commit/7d67d35bafb84f3cb24fade78214478bcc3204f2)) +* **api:** add stablecoin event types to payment/statement/financial_event ([9c1cfe4](https://github.com/lithic-com/lithic-python/commit/9c1cfe46e6538c2429653dd65bf72938544f1fe4)) +* **api:** add stablecoin method and attributes to payment ([ed5c9b0](https://github.com/lithic-com/lithic-python/commit/ed5c9b0496b984876497c39a6110020979f93bfb)) +* **api:** add STABLECOIN method, make method_attributes optional in payment ([ebb1b60](https://github.com/lithic-com/lithic-python/commit/ebb1b60c55251a27d0da338875be625a67cea4c2)) +* **api:** Add STABLECOIN to approvals request and transfer type enums ([8c277b5](https://github.com/lithic-com/lithic-python/commit/8c277b59aefd35e571026c97177a50223fd0622d)) + + +### Documentation + +* **api:** clarify CVV format in tokenizations and card ([8980c52](https://github.com/lithic-com/lithic-python/commit/8980c5219db6e83e4cc8e9d2445fbd223c24a728)) + ## 0.130.0 (2026-07-30) Full Changelog: [v0.129.0...v0.130.0](https://github.com/lithic-com/lithic-python/compare/v0.129.0...v0.130.0) diff --git a/api.md b/api.md index ad2ebead..641c9b54 100644 --- a/api.md +++ b/api.md @@ -690,6 +690,18 @@ Methods: - client.external_bank_accounts.micro_deposits.create(external_bank_account_token, \*\*params) -> MicroDepositCreateResponse +# BlockchainRecipients + +Types: + +```python +from lithic.types import BlockchainRecipient +``` + +Methods: + +- client.blockchain_recipients.create(\*\*params) -> BlockchainRecipient + # Payments Types: diff --git a/pyproject.toml b/pyproject.toml index beb88420..0df4f166 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "lithic" -version = "0.130.0" +version = "0.131.0" description = "The official Python library for the lithic API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/lithic/_client.py b/src/lithic/_client.py index 15034895..14b16915 100644 --- a/src/lithic/_client.py +++ b/src/lithic/_client.py @@ -70,6 +70,7 @@ financial_accounts, card_authorizations, responder_endpoints, + blockchain_recipients, management_operations, auth_stream_enrollment, external_bank_accounts, @@ -101,6 +102,7 @@ from .resources.card_authorizations import CardAuthorizations, AsyncCardAuthorizations from .resources.responder_endpoints import ResponderEndpoints, AsyncResponderEndpoints from .resources.auth_rules.auth_rules import AuthRules, AsyncAuthRules + from .resources.blockchain_recipients import BlockchainRecipients, AsyncBlockchainRecipients from .resources.management_operations import ManagementOperations, AsyncManagementOperations from .resources.auth_stream_enrollment import AuthStreamEnrollment, AsyncAuthStreamEnrollment from .resources.tokenization_decisioning import TokenizationDecisioning, AsyncTokenizationDecisioning @@ -336,6 +338,12 @@ def external_bank_accounts(self) -> ExternalBankAccounts: return ExternalBankAccounts(self) + @cached_property + def blockchain_recipients(self) -> BlockchainRecipients: + from .resources.blockchain_recipients import BlockchainRecipients + + return BlockchainRecipients(self) + @cached_property def payments(self) -> Payments: from .resources.payments import Payments @@ -772,6 +780,12 @@ def external_bank_accounts(self) -> AsyncExternalBankAccounts: return AsyncExternalBankAccounts(self) + @cached_property + def blockchain_recipients(self) -> AsyncBlockchainRecipients: + from .resources.blockchain_recipients import AsyncBlockchainRecipients + + return AsyncBlockchainRecipients(self) + @cached_property def payments(self) -> AsyncPayments: from .resources.payments import AsyncPayments @@ -1122,6 +1136,12 @@ def external_bank_accounts(self) -> external_bank_accounts.ExternalBankAccountsW return ExternalBankAccountsWithRawResponse(self._client.external_bank_accounts) + @cached_property + def blockchain_recipients(self) -> blockchain_recipients.BlockchainRecipientsWithRawResponse: + from .resources.blockchain_recipients import BlockchainRecipientsWithRawResponse + + return BlockchainRecipientsWithRawResponse(self._client.blockchain_recipients) + @cached_property def payments(self) -> payments.PaymentsWithRawResponse: from .resources.payments import PaymentsWithRawResponse @@ -1331,6 +1351,12 @@ def external_bank_accounts(self) -> external_bank_accounts.AsyncExternalBankAcco return AsyncExternalBankAccountsWithRawResponse(self._client.external_bank_accounts) + @cached_property + def blockchain_recipients(self) -> blockchain_recipients.AsyncBlockchainRecipientsWithRawResponse: + from .resources.blockchain_recipients import AsyncBlockchainRecipientsWithRawResponse + + return AsyncBlockchainRecipientsWithRawResponse(self._client.blockchain_recipients) + @cached_property def payments(self) -> payments.AsyncPaymentsWithRawResponse: from .resources.payments import AsyncPaymentsWithRawResponse @@ -1540,6 +1566,12 @@ def external_bank_accounts(self) -> external_bank_accounts.ExternalBankAccountsW return ExternalBankAccountsWithStreamingResponse(self._client.external_bank_accounts) + @cached_property + def blockchain_recipients(self) -> blockchain_recipients.BlockchainRecipientsWithStreamingResponse: + from .resources.blockchain_recipients import BlockchainRecipientsWithStreamingResponse + + return BlockchainRecipientsWithStreamingResponse(self._client.blockchain_recipients) + @cached_property def payments(self) -> payments.PaymentsWithStreamingResponse: from .resources.payments import PaymentsWithStreamingResponse @@ -1749,6 +1781,12 @@ def external_bank_accounts(self) -> external_bank_accounts.AsyncExternalBankAcco return AsyncExternalBankAccountsWithStreamingResponse(self._client.external_bank_accounts) + @cached_property + def blockchain_recipients(self) -> blockchain_recipients.AsyncBlockchainRecipientsWithStreamingResponse: + from .resources.blockchain_recipients import AsyncBlockchainRecipientsWithStreamingResponse + + return AsyncBlockchainRecipientsWithStreamingResponse(self._client.blockchain_recipients) + @cached_property def payments(self) -> payments.AsyncPaymentsWithStreamingResponse: from .resources.payments import AsyncPaymentsWithStreamingResponse diff --git a/src/lithic/_version.py b/src/lithic/_version.py index a8fc2b35..5e23cbfb 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.130.0" # x-release-please-version +__version__ = "0.131.0" # x-release-please-version diff --git a/src/lithic/resources/__init__.py b/src/lithic/resources/__init__.py index e0be6a24..76ebb1e2 100644 --- a/src/lithic/resources/__init__.py +++ b/src/lithic/resources/__init__.py @@ -225,6 +225,14 @@ ResponderEndpointsWithStreamingResponse, AsyncResponderEndpointsWithStreamingResponse, ) +from .blockchain_recipients import ( + BlockchainRecipients, + AsyncBlockchainRecipients, + BlockchainRecipientsWithRawResponse, + AsyncBlockchainRecipientsWithRawResponse, + BlockchainRecipientsWithStreamingResponse, + AsyncBlockchainRecipientsWithStreamingResponse, +) from .management_operations import ( ManagementOperations, AsyncManagementOperations, @@ -375,6 +383,12 @@ "AsyncExternalBankAccountsWithRawResponse", "ExternalBankAccountsWithStreamingResponse", "AsyncExternalBankAccountsWithStreamingResponse", + "BlockchainRecipients", + "AsyncBlockchainRecipients", + "BlockchainRecipientsWithRawResponse", + "AsyncBlockchainRecipientsWithRawResponse", + "BlockchainRecipientsWithStreamingResponse", + "AsyncBlockchainRecipientsWithStreamingResponse", "Payments", "AsyncPayments", "PaymentsWithRawResponse", diff --git a/src/lithic/resources/blockchain_recipients.py b/src/lithic/resources/blockchain_recipients.py new file mode 100644 index 00000000..0a6b8e27 --- /dev/null +++ b/src/lithic/resources/blockchain_recipients.py @@ -0,0 +1,236 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import httpx + +from .. import _legacy_response +from ..types import OwnerType, blockchain_recipient_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 .._base_client import make_request_options +from ..types.owner_type import OwnerType +from ..types.blockchain_recipient import BlockchainRecipient + +__all__ = ["BlockchainRecipients", "AsyncBlockchainRecipients"] + + +class BlockchainRecipients(SyncAPIResource): + @cached_property + def with_raw_response(self) -> BlockchainRecipientsWithRawResponse: + """ + 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 BlockchainRecipientsWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> BlockchainRecipientsWithStreamingResponse: + """ + 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 BlockchainRecipientsWithStreamingResponse(self) + + def create( + self, + *, + account_token: str, + address: str, + chain: str, + owner: str, + owner_type: OwnerType, + address_tag: str | Omit = omit, + name: 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, + ) -> BlockchainRecipient: + """ + Register a blockchain address as a withdrawal destination for a financial + account + + The recipient is created with a `PENDING` verification state and cannot receive + a payout until screening of the address completes. Registering an address that + is already registered to the same financial account returns the existing + recipient and its current verification state, rather than creating a second one + + Args: + account_token: The financial account the blockchain recipient belongs to + + address: The blockchain address funds will be withdrawn to + + chain: The blockchain network that the address belongs to + + owner: Legal name of the business or individual who owns the blockchain address + + owner_type: Owner Type + + address_tag: An optional tag or memo used by some chains to identify the destination of a + transfer within a shared address + + name: The nickname for this blockchain recipient + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._post( + "/v1/blockchain_recipients", + body=maybe_transform( + { + "account_token": account_token, + "address": address, + "chain": chain, + "owner": owner, + "owner_type": owner_type, + "address_tag": address_tag, + "name": name, + }, + blockchain_recipient_create_params.BlockchainRecipientCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=BlockchainRecipient, + ) + + +class AsyncBlockchainRecipients(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncBlockchainRecipientsWithRawResponse: + """ + 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 AsyncBlockchainRecipientsWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncBlockchainRecipientsWithStreamingResponse: + """ + 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 AsyncBlockchainRecipientsWithStreamingResponse(self) + + async def create( + self, + *, + account_token: str, + address: str, + chain: str, + owner: str, + owner_type: OwnerType, + address_tag: str | Omit = omit, + name: 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, + ) -> BlockchainRecipient: + """ + Register a blockchain address as a withdrawal destination for a financial + account + + The recipient is created with a `PENDING` verification state and cannot receive + a payout until screening of the address completes. Registering an address that + is already registered to the same financial account returns the existing + recipient and its current verification state, rather than creating a second one + + Args: + account_token: The financial account the blockchain recipient belongs to + + address: The blockchain address funds will be withdrawn to + + chain: The blockchain network that the address belongs to + + owner: Legal name of the business or individual who owns the blockchain address + + owner_type: Owner Type + + address_tag: An optional tag or memo used by some chains to identify the destination of a + transfer within a shared address + + name: The nickname for this blockchain recipient + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._post( + "/v1/blockchain_recipients", + body=await async_maybe_transform( + { + "account_token": account_token, + "address": address, + "chain": chain, + "owner": owner, + "owner_type": owner_type, + "address_tag": address_tag, + "name": name, + }, + blockchain_recipient_create_params.BlockchainRecipientCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=BlockchainRecipient, + ) + + +class BlockchainRecipientsWithRawResponse: + def __init__(self, blockchain_recipients: BlockchainRecipients) -> None: + self._blockchain_recipients = blockchain_recipients + + self.create = _legacy_response.to_raw_response_wrapper( + blockchain_recipients.create, + ) + + +class AsyncBlockchainRecipientsWithRawResponse: + def __init__(self, blockchain_recipients: AsyncBlockchainRecipients) -> None: + self._blockchain_recipients = blockchain_recipients + + self.create = _legacy_response.async_to_raw_response_wrapper( + blockchain_recipients.create, + ) + + +class BlockchainRecipientsWithStreamingResponse: + def __init__(self, blockchain_recipients: BlockchainRecipients) -> None: + self._blockchain_recipients = blockchain_recipients + + self.create = to_streamed_response_wrapper( + blockchain_recipients.create, + ) + + +class AsyncBlockchainRecipientsWithStreamingResponse: + def __init__(self, blockchain_recipients: AsyncBlockchainRecipients) -> None: + self._blockchain_recipients = blockchain_recipients + + self.create = async_to_streamed_response_wrapper( + blockchain_recipients.create, + ) diff --git a/src/lithic/resources/tokenizations.py b/src/lithic/resources/tokenizations.py index 34c28a48..7791b518 100644 --- a/src/lithic/resources/tokenizations.py +++ b/src/lithic/resources/tokenizations.py @@ -354,7 +354,7 @@ def simulate( and merchant tokenization ecosystem. Args: - cvv: The three digit cvv for the card. + cvv: The three or four digit CVV for the card. AMEX cards use four digit CVVs. expiration_date: The expiration date of the card in 'MM/YY' format. @@ -822,7 +822,7 @@ async def simulate( and merchant tokenization ecosystem. Args: - cvv: The three digit cvv for the card. + cvv: The three or four digit CVV for the card. AMEX cards use four digit CVVs. expiration_date: The expiration date of the card in 'MM/YY' format. diff --git a/src/lithic/resources/transaction_monitoring/cases/cases.py b/src/lithic/resources/transaction_monitoring/cases/cases.py index f203ed6d..416fca7d 100644 --- a/src/lithic/resources/transaction_monitoring/cases/cases.py +++ b/src/lithic/resources/transaction_monitoring/cases/cases.py @@ -243,7 +243,9 @@ def list( 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. - entity_token: Only return cases associated with the provided entity. + entity_token: Only return cases associated with the provided entity. Accepts a card, account, + or financial account token. Cases with a `PROGRAM` entity have no entity token + and are never returned by this filter. page_size: Page size (for pagination). @@ -637,7 +639,9 @@ def list( 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. - entity_token: Only return cases associated with the provided entity. + entity_token: Only return cases associated with the provided entity. Accepts a card, account, + or financial account token. Cases with a `PROGRAM` entity have no entity token + and are never returned by this filter. page_size: Page size (for pagination). diff --git a/src/lithic/types/__init__.py b/src/lithic/types/__init__.py index a1dac934..32183f5b 100644 --- a/src/lithic/types/__init__.py +++ b/src/lithic/types/__init__.py @@ -78,6 +78,7 @@ from .verification_method import VerificationMethod as VerificationMethod from .account_spend_limits import AccountSpendLimits as AccountSpendLimits from .address_update_param import AddressUpdateParam as AddressUpdateParam +from .blockchain_recipient import BlockchainRecipient as BlockchainRecipient from .internal_transaction import InternalTransaction as InternalTransaction from .parsed_webhook_event import ParsedWebhookEvent as ParsedWebhookEvent from .spend_limit_duration import SpendLimitDuration as SpendLimitDuration @@ -175,6 +176,7 @@ from .payment_simulate_receipt_response import PaymentSimulateReceiptResponse as PaymentSimulateReceiptResponse from .payment_simulate_release_response import PaymentSimulateReleaseResponse as PaymentSimulateReleaseResponse from .tokenization_result_webhook_event import TokenizationResultWebhookEvent as TokenizationResultWebhookEvent +from .blockchain_recipient_create_params import BlockchainRecipientCreateParams as BlockchainRecipientCreateParams from .management_operation_create_params import ManagementOperationCreateParams as ManagementOperationCreateParams from .responder_endpoint_create_response import ResponderEndpointCreateResponse as ResponderEndpointCreateResponse from .tokenization_updated_webhook_event import TokenizationUpdatedWebhookEvent as TokenizationUpdatedWebhookEvent diff --git a/src/lithic/types/auth_rules/ach_payment_update_action.py b/src/lithic/types/auth_rules/ach_payment_update_action.py index 841dc939..4726290c 100644 --- a/src/lithic/types/auth_rules/ach_payment_update_action.py +++ b/src/lithic/types/auth_rules/ach_payment_update_action.py @@ -23,7 +23,7 @@ class CreateCaseAction(BaseModel): queue_token: str """The token of the queue to create the case in""" - scope: Literal["FINANCIAL_ACCOUNT"] + scope: Literal["FINANCIAL_ACCOUNT", "PROGRAM"] """The scope of the case to create""" type: Literal["CREATE_CASE"] diff --git a/src/lithic/types/auth_rules/ach_payment_update_action_param.py b/src/lithic/types/auth_rules/ach_payment_update_action_param.py index b4625d5c..08ae0f25 100644 --- a/src/lithic/types/auth_rules/ach_payment_update_action_param.py +++ b/src/lithic/types/auth_rules/ach_payment_update_action_param.py @@ -23,7 +23,7 @@ class CreateCaseAction(TypedDict, total=False): queue_token: Required[str] """The token of the queue to create the case in""" - scope: Required[Literal["FINANCIAL_ACCOUNT"]] + scope: Required[Literal["FINANCIAL_ACCOUNT", "PROGRAM"]] """The scope of the case to create""" type: Required[Literal["CREATE_CASE"]] diff --git a/src/lithic/types/auth_rules/card_transaction_update_action.py b/src/lithic/types/auth_rules/card_transaction_update_action.py index 902af1fc..9f366ba9 100644 --- a/src/lithic/types/auth_rules/card_transaction_update_action.py +++ b/src/lithic/types/auth_rules/card_transaction_update_action.py @@ -23,7 +23,7 @@ class CreateCaseAction(BaseModel): queue_token: str """The token of the queue to create the case in""" - scope: Literal["CARD", "ACCOUNT"] + scope: Literal["CARD", "ACCOUNT", "PROGRAM"] """The scope of the case to create""" type: Literal["CREATE_CASE"] diff --git a/src/lithic/types/auth_rules/card_transaction_update_action_param.py b/src/lithic/types/auth_rules/card_transaction_update_action_param.py index 9eb27dea..edce44cf 100644 --- a/src/lithic/types/auth_rules/card_transaction_update_action_param.py +++ b/src/lithic/types/auth_rules/card_transaction_update_action_param.py @@ -23,7 +23,7 @@ class CreateCaseAction(TypedDict, total=False): queue_token: Required[str] """The token of the queue to create the case in""" - scope: Required[Literal["CARD", "ACCOUNT"]] + scope: Required[Literal["CARD", "ACCOUNT", "PROGRAM"]] """The scope of the case to create""" type: Required[Literal["CREATE_CASE"]] diff --git a/src/lithic/types/auth_rules/v2_list_results_response.py b/src/lithic/types/auth_rules/v2_list_results_response.py index 2cc038bb..c42048e1 100644 --- a/src/lithic/types/auth_rules/v2_list_results_response.py +++ b/src/lithic/types/auth_rules/v2_list_results_response.py @@ -412,7 +412,7 @@ class CardTransactionUpdateResultActionCreateCaseAction(BaseModel): queue_token: str """The token of the queue to create the case in""" - scope: Literal["CARD", "ACCOUNT"] + scope: Literal["CARD", "ACCOUNT", "PROGRAM"] """The scope of the case to create""" type: Literal["CREATE_CASE"] @@ -474,7 +474,7 @@ class ACHPaymentUpdateResultActionCreateCaseAction(BaseModel): queue_token: str """The token of the queue to create the case in""" - scope: Literal["FINANCIAL_ACCOUNT"] + scope: Literal["FINANCIAL_ACCOUNT", "PROGRAM"] """The scope of the case to create""" type: Literal["CREATE_CASE"] diff --git a/src/lithic/types/auth_rules/velocity_limit_params.py b/src/lithic/types/auth_rules/velocity_limit_params.py index 061a8de7..6914b7d9 100644 --- a/src/lithic/types/auth_rules/velocity_limit_params.py +++ b/src/lithic/types/auth_rules/velocity_limit_params.py @@ -26,6 +26,23 @@ class VelocityLimitParams(BaseModel): limit will be declined. """ + limit_cash_amount: Optional[int] = None + """ + The maximum amount of cash spend velocity allowed in the period in minor units + (the smallest unit of a currency, e.g. cents for USD). Cash spend covers ATM + withdrawals, cash disbursements, and purchases with cashback. Transactions + exceeding this limit will be declined. + """ + + limit_cash_count: Optional[int] = None + """ + The number of cash spend velocity impacting transactions may not exceed this + limit in the period. Transactions exceeding this limit will be declined. A cash + velocity impacting transaction is an ATM withdrawal, cash disbursement, or + purchase with cashback that has been authorized, and optionally settled, or a + force post (a transaction that settled without prior authorization). + """ + limit_count: Optional[int] = None """ The number of spend velocity impacting transactions may not exceed this limit in 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 e91557fa..8fe6b058 100644 --- a/src/lithic/types/auth_rules/velocity_limit_params_param.py +++ b/src/lithic/types/auth_rules/velocity_limit_params_param.py @@ -27,6 +27,23 @@ class VelocityLimitParamsParam(TypedDict, total=False): limit will be declined. """ + limit_cash_amount: Optional[int] + """ + The maximum amount of cash spend velocity allowed in the period in minor units + (the smallest unit of a currency, e.g. cents for USD). Cash spend covers ATM + withdrawals, cash disbursements, and purchases with cashback. Transactions + exceeding this limit will be declined. + """ + + limit_cash_count: Optional[int] + """ + The number of cash spend velocity impacting transactions may not exceed this + limit in the period. Transactions exceeding this limit will be declined. A cash + velocity impacting transaction is an ATM withdrawal, cash disbursement, or + purchase with cashback that has been authorized, and optionally settled, or a + force post (a transaction that settled without prior authorization). + """ + limit_count: Optional[int] """ The number of spend velocity impacting transactions may not exceed this limit in diff --git a/src/lithic/types/blockchain_recipient.py b/src/lithic/types/blockchain_recipient.py new file mode 100644 index 00000000..e90f5350 --- /dev/null +++ b/src/lithic/types/blockchain_recipient.py @@ -0,0 +1,57 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from datetime import datetime +from typing_extensions import Literal + +from .._models import BaseModel +from .owner_type import OwnerType + +__all__ = ["BlockchainRecipient"] + + +class BlockchainRecipient(BaseModel): + token: str + """A globally unique identifier for this blockchain recipient""" + + account_token: str + """The financial account the blockchain recipient belongs to""" + + address_tag: Optional[str] = None + """ + An optional tag or memo used by some chains to identify the destination of a + transfer within a shared address + """ + + chain: str + """The blockchain network that the address belongs to""" + + created: datetime + """An ISO 8601 string representing when this blockchain recipient was created""" + + external_id: Optional[str] = None + """The identifier the recipient is registered under with the payment provider""" + + name: Optional[str] = None + """The nickname for this blockchain recipient""" + + owner: str + """Legal name of the business or individual who owns the blockchain address""" + + owner_type: OwnerType + """Owner Type""" + + program_id: str + """ + Globally unique identifier for the program the blockchain recipient is + associated with + """ + + state: Literal["ENABLED", "CLOSED", "PAUSED"] + """Account State""" + + updated: datetime + """An ISO 8601 string representing when this blockchain recipient was last updated""" + + verification_state: Literal["PENDING", "ENABLED", "FAILED_VERIFICATION", "INSUFFICIENT_FUNDS"] + """Verification State""" diff --git a/src/lithic/types/blockchain_recipient_create_params.py b/src/lithic/types/blockchain_recipient_create_params.py new file mode 100644 index 00000000..7725cfbc --- /dev/null +++ b/src/lithic/types/blockchain_recipient_create_params.py @@ -0,0 +1,35 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +from .owner_type import OwnerType + +__all__ = ["BlockchainRecipientCreateParams"] + + +class BlockchainRecipientCreateParams(TypedDict, total=False): + account_token: Required[str] + """The financial account the blockchain recipient belongs to""" + + address: Required[str] + """The blockchain address funds will be withdrawn to""" + + chain: Required[str] + """The blockchain network that the address belongs to""" + + owner: Required[str] + """Legal name of the business or individual who owns the blockchain address""" + + owner_type: Required[OwnerType] + """Owner Type""" + + address_tag: str + """ + An optional tag or memo used by some chains to identify the destination of a + transfer within a shared address + """ + + name: str + """The nickname for this blockchain recipient""" diff --git a/src/lithic/types/card.py b/src/lithic/types/card.py index 3bb986c2..53c1eae0 100644 --- a/src/lithic/types/card.py +++ b/src/lithic/types/card.py @@ -13,7 +13,7 @@ class Card(NonPCICard): """ cvv: Optional[str] = None - """Three digit cvv printed on the back of the card.""" + """Three or four digit CVV printed on the card. Amex cards use four digit CVVs""" pan: Optional[str] = None """Primary Account Number (PAN) (i.e. diff --git a/src/lithic/types/financial_account.py b/src/lithic/types/financial_account.py index 28502aef..c738d406 100644 --- a/src/lithic/types/financial_account.py +++ b/src/lithic/types/financial_account.py @@ -1,6 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Optional +from typing import Dict, Optional from datetime import datetime from typing_extensions import Literal @@ -80,4 +80,11 @@ class FinancialAccount(BaseModel): account_number: Optional[str] = None + blockchain_addresses: Optional[Dict[str, str]] = None + """ + Provisioned blockchain deposit addresses for this financial account, keyed by + the full name of the blockchain network that each address belongs to (e.g. + `ETHEREUM`) + """ + routing_number: Optional[str] = None 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 10740060..d62c53bf 100644 --- a/src/lithic/types/financial_accounts/statements/statement_line_items.py +++ b/src/lithic/types/financial_accounts/statements/statement_line_items.py @@ -152,8 +152,11 @@ class Data(BaseModel): "MONTHLY_REVERSAL", "ACCOUNT_TO_ACCOUNT", "STABLECOIN_RECEIVED", + "STABLECOIN_INITIATED", "STABLECOIN_REVIEWED", + "STABLECOIN_SENT", "STABLECOIN_SETTLED", + "STABLECOIN_REJECTED", ] financial_account_token: str diff --git a/src/lithic/types/payment.py b/src/lithic/types/payment.py index ee223791..b789e4f7 100644 --- a/src/lithic/types/payment.py +++ b/src/lithic/types/payment.py @@ -13,6 +13,7 @@ "MethodAttributes", "MethodAttributesACHMethodAttributes", "MethodAttributesWireMethodAttributes", + "MethodAttributesStablecoinMethodAttributes", "RelatedAccountTokens", ] @@ -66,8 +67,11 @@ class Event(BaseModel): "WIRE_RETURN_OUTBOUND_SETTLED", "WIRE_RETURN_OUTBOUND_REJECTED", "STABLECOIN_RECEIVED", + "STABLECOIN_INITIATED", "STABLECOIN_REVIEWED", + "STABLECOIN_SENT", "STABLECOIN_SETTLED", + "STABLECOIN_REJECTED", ] """ Note: Inbound wire transfers are coming soon (availability varies by partner @@ -127,8 +131,16 @@ class Event(BaseModel): - `STABLECOIN_RECEIVED` - Stablecoin pay-in received on-chain and pending release to available balance. - - `STABLECOIN_REVIEWED` - Stablecoin pay-in has completed the review process. - - `STABLECOIN_SETTLED` - Stablecoin pay-in funds released to available balance. + - `STABLECOIN_INITIATED` - Stablecoin withdrawal initiated, with the funds + placed on hold. + - `STABLECOIN_REVIEWED` - Stablecoin pay-in or withdrawal has completed the + review process. + - `STABLECOIN_SENT` - Stablecoin withdrawal accepted for on-chain submission to + the destination address, and pending confirmation. + - `STABLECOIN_SETTLED` - Stablecoin pay-in funds released to available balance, + or stablecoin withdrawal confirmed on-chain. + - `STABLECOIN_REJECTED` - Stablecoin withdrawal failed and the hold placed at + initiation has been reversed. """ detailed_results: Optional[ @@ -150,7 +162,9 @@ class Event(BaseModel): """Payment event external ID. For ACH transactions, this is the ACH trace number. For inbound wire transfers, - this is the IMAD (Input Message Accountability Data). + this is the IMAD (Input Message Accountability Data). For stablecoin payments, + this is the on-chain transaction hash of the transfer; it is present on events + that reflect on-chain activity and null on internal lifecycle events. """ @@ -210,7 +224,22 @@ class MethodAttributesWireMethodAttributes(BaseModel): """Payment details or invoice reference""" -MethodAttributes: TypeAlias = Union[MethodAttributesACHMethodAttributes, MethodAttributesWireMethodAttributes] +class MethodAttributesStablecoinMethodAttributes(BaseModel): + chain: str + """Blockchain the stablecoin transfer settled on""" + + transaction_hash: Optional[str] = None + """On-chain transaction hash of the transfer. + + Null until the transfer has settled on chain + """ + + +MethodAttributes: TypeAlias = Union[ + MethodAttributesACHMethodAttributes, + MethodAttributesWireMethodAttributes, + MethodAttributesStablecoinMethodAttributes, +] class RelatedAccountTokens(BaseModel): @@ -275,7 +304,7 @@ class Payment(BaseModel): financial_account_token: str """Financial account token""" - method: Literal["ACH_NEXT_DAY", "ACH_SAME_DAY", "WIRE"] + method: Literal["ACH_NEXT_DAY", "ACH_SAME_DAY", "WIRE", "STABLECOIN"] """Transfer method""" method_attributes: MethodAttributes @@ -302,6 +331,9 @@ class Payment(BaseModel): updated: datetime """ISO 8601 timestamp of when the transaction was last updated""" + blockchain_recipient_token: Optional[str] = None + """Token of the blockchain recipient the payout is sent to""" + currency: Optional[str] = None """Currency of the transaction in ISO 4217 format""" @@ -329,6 +361,7 @@ class Payment(BaseModel): "WIRE_OUTBOUND_PAYMENT", "WIRE_OUTBOUND_ADMIN", "WIRE_INBOUND_DRAWDOWN_REQUEST", + "STABLECOIN", ] ] = None diff --git a/src/lithic/types/shared/financial_event.py b/src/lithic/types/shared/financial_event.py index 2ad57159..9d677eb0 100644 --- a/src/lithic/types/shared/financial_event.py +++ b/src/lithic/types/shared/financial_event.py @@ -123,7 +123,10 @@ class FinancialEvent(BaseModel): "MONTHLY_REVERSAL", "ACCOUNT_TO_ACCOUNT", "STABLECOIN_RECEIVED", + "STABLECOIN_INITIATED", "STABLECOIN_REVIEWED", + "STABLECOIN_SENT", "STABLECOIN_SETTLED", + "STABLECOIN_REJECTED", ] ] = None diff --git a/src/lithic/types/tokenization_simulate_params.py b/src/lithic/types/tokenization_simulate_params.py index 1b04cf6e..560cda31 100644 --- a/src/lithic/types/tokenization_simulate_params.py +++ b/src/lithic/types/tokenization_simulate_params.py @@ -9,7 +9,7 @@ class TokenizationSimulateParams(TypedDict, total=False): cvv: Required[str] - """The three digit cvv for the card.""" + """The three or four digit CVV for the card. AMEX cards use four digit CVVs.""" expiration_date: Required[str] """The expiration date of the card in 'MM/YY' format.""" diff --git a/src/lithic/types/transaction_monitoring/case_entity.py b/src/lithic/types/transaction_monitoring/case_entity.py index a85b9e3f..b03bfa3e 100644 --- a/src/lithic/types/transaction_monitoring/case_entity.py +++ b/src/lithic/types/transaction_monitoring/case_entity.py @@ -1,5 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +from typing import Optional from typing_extensions import Literal from ..._models import BaseModel @@ -10,12 +11,19 @@ class CaseEntity(BaseModel): """The entity a case is associated with""" - entity_token: str - """Globally unique identifier for the associated entity""" + entity_token: Optional[str] = None + """ + Globally unique identifier for the associated entity: the card token for `CARD`, + the account token for `ACCOUNT`, and the financial account token for + `FINANCIAL_ACCOUNT`. Null for `PROGRAM`, which is not scoped to an individual + entity + """ - entity_type: Literal["CARD", "ACCOUNT"] + entity_type: Literal["CARD", "ACCOUNT", "FINANCIAL_ACCOUNT", "PROGRAM"] """The type of entity a case is associated with: - `CARD` - The case is associated with a card - `ACCOUNT` - The case is associated with an account + - `FINANCIAL_ACCOUNT` - The case is associated with a financial account + - `PROGRAM` - The case is associated with the whole program """ diff --git a/src/lithic/types/transaction_monitoring/case_list_params.py b/src/lithic/types/transaction_monitoring/case_list_params.py index 7265c87b..2712be44 100644 --- a/src/lithic/types/transaction_monitoring/case_list_params.py +++ b/src/lithic/types/transaction_monitoring/case_list_params.py @@ -45,7 +45,11 @@ class CaseListParams(TypedDict, total=False): """ entity_token: str - """Only return cases associated with the provided entity.""" + """Only return cases associated with the provided entity. + + Accepts a card, account, or financial account token. Cases with a `PROGRAM` + entity have no entity token and are never returned by this filter. + """ page_size: int """Page size (for pagination).""" diff --git a/tests/api_resources/test_blockchain_recipients.py b/tests/api_resources/test_blockchain_recipients.py new file mode 100644 index 00000000..97b65d38 --- /dev/null +++ b/tests/api_resources/test_blockchain_recipients.py @@ -0,0 +1,136 @@ +# 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 BlockchainRecipient + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestBlockchainRecipients: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_create(self, client: Lithic) -> None: + blockchain_recipient = client.blockchain_recipients.create( + account_token="dabadb3b-700c-41e3-8801-d5dfc84ebea0", + address="0x45bfcf1a6289a0b77b4d3f7d12005a05949fd8c3", + chain="ETHEREUM", + owner="John Doe", + owner_type="INDIVIDUAL", + ) + assert_matches_type(BlockchainRecipient, blockchain_recipient, path=["response"]) + + @parametrize + def test_method_create_with_all_params(self, client: Lithic) -> None: + blockchain_recipient = client.blockchain_recipients.create( + account_token="dabadb3b-700c-41e3-8801-d5dfc84ebea0", + address="0x45bfcf1a6289a0b77b4d3f7d12005a05949fd8c3", + chain="ETHEREUM", + owner="John Doe", + owner_type="INDIVIDUAL", + address_tag="address_tag", + name="Cold wallet", + ) + assert_matches_type(BlockchainRecipient, blockchain_recipient, path=["response"]) + + @parametrize + def test_raw_response_create(self, client: Lithic) -> None: + response = client.blockchain_recipients.with_raw_response.create( + account_token="dabadb3b-700c-41e3-8801-d5dfc84ebea0", + address="0x45bfcf1a6289a0b77b4d3f7d12005a05949fd8c3", + chain="ETHEREUM", + owner="John Doe", + owner_type="INDIVIDUAL", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + blockchain_recipient = response.parse() + assert_matches_type(BlockchainRecipient, blockchain_recipient, path=["response"]) + + @parametrize + def test_streaming_response_create(self, client: Lithic) -> None: + with client.blockchain_recipients.with_streaming_response.create( + account_token="dabadb3b-700c-41e3-8801-d5dfc84ebea0", + address="0x45bfcf1a6289a0b77b4d3f7d12005a05949fd8c3", + chain="ETHEREUM", + owner="John Doe", + owner_type="INDIVIDUAL", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + blockchain_recipient = response.parse() + assert_matches_type(BlockchainRecipient, blockchain_recipient, path=["response"]) + + assert cast(Any, response.is_closed) is True + + +class TestAsyncBlockchainRecipients: + 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: + blockchain_recipient = await async_client.blockchain_recipients.create( + account_token="dabadb3b-700c-41e3-8801-d5dfc84ebea0", + address="0x45bfcf1a6289a0b77b4d3f7d12005a05949fd8c3", + chain="ETHEREUM", + owner="John Doe", + owner_type="INDIVIDUAL", + ) + assert_matches_type(BlockchainRecipient, blockchain_recipient, path=["response"]) + + @parametrize + async def test_method_create_with_all_params(self, async_client: AsyncLithic) -> None: + blockchain_recipient = await async_client.blockchain_recipients.create( + account_token="dabadb3b-700c-41e3-8801-d5dfc84ebea0", + address="0x45bfcf1a6289a0b77b4d3f7d12005a05949fd8c3", + chain="ETHEREUM", + owner="John Doe", + owner_type="INDIVIDUAL", + address_tag="address_tag", + name="Cold wallet", + ) + assert_matches_type(BlockchainRecipient, blockchain_recipient, path=["response"]) + + @parametrize + async def test_raw_response_create(self, async_client: AsyncLithic) -> None: + response = await async_client.blockchain_recipients.with_raw_response.create( + account_token="dabadb3b-700c-41e3-8801-d5dfc84ebea0", + address="0x45bfcf1a6289a0b77b4d3f7d12005a05949fd8c3", + chain="ETHEREUM", + owner="John Doe", + owner_type="INDIVIDUAL", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + blockchain_recipient = response.parse() + assert_matches_type(BlockchainRecipient, blockchain_recipient, path=["response"]) + + @parametrize + async def test_streaming_response_create(self, async_client: AsyncLithic) -> None: + async with async_client.blockchain_recipients.with_streaming_response.create( + account_token="dabadb3b-700c-41e3-8801-d5dfc84ebea0", + address="0x45bfcf1a6289a0b77b4d3f7d12005a05949fd8c3", + chain="ETHEREUM", + owner="John Doe", + owner_type="INDIVIDUAL", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + blockchain_recipient = await response.parse() + assert_matches_type(BlockchainRecipient, blockchain_recipient, path=["response"]) + + assert cast(Any, response.is_closed) is True