diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 99550732..8406231a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: runs-on: ${{ github.repository == 'stainless-sdks/lithic-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata') steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Install Rye run: | @@ -46,7 +46,7 @@ jobs: id-token: write runs-on: ${{ github.repository == 'stainless-sdks/lithic-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Install Rye run: | @@ -67,7 +67,7 @@ jobs: github.repository == 'stainless-sdks/lithic-python' && !startsWith(github.ref, 'refs/heads/stl/') id: github-oidc - uses: actions/github-script@v8 + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 with: script: core.setOutput('github_token', await core.getIDToken()); @@ -87,7 +87,7 @@ jobs: runs-on: ${{ github.repository == 'stainless-sdks/lithic-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Install Rye run: | @@ -110,7 +110,7 @@ jobs: if: github.repository == 'lithic-com/lithic-python' && (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata') steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Install Rye run: | diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml index e730d88c..69c9b675 100644 --- a/.github/workflows/publish-pypi.yml +++ b/.github/workflows/publish-pypi.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Install Rye run: | diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml index 1811e344..4ba6b65c 100644 --- a/.github/workflows/release-doctor.yml +++ b/.github/workflows/release-doctor.yml @@ -12,7 +12,7 @@ jobs: if: github.repository == 'lithic-com/lithic-python' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'release-please') || github.head_ref == 'next') steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Check release environment run: | diff --git a/.release-please-manifest.json b/.release-please-manifest.json index cadbcc6f..f3343e21 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.124.0" + ".": "0.125.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 277eb3b9..07125239 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 192 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic/lithic-00f07b0edcc0c3c5ef79920ced7f58dac2434df5e4c27ff6041783e8228315f9.yml -openapi_spec_hash: 963688b09480159a06865075c94a2577 -config_hash: 265a2b679964f4ad5706de101ad2a942 +configured_endpoints: 193 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic/lithic-9350b3c0a9a4fc31e1cac88e705f1ac6895108360ba8f7845a8da20db825f82e.yml +openapi_spec_hash: c99714470f6321912e8022434a861897 +config_hash: 1c5c139a2aa0d1d45c063f953a9bc803 diff --git a/CHANGELOG.md b/CHANGELOG.md index 35da48c3..002c7a02 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,24 @@ # Changelog +## 0.125.0 (2026-05-19) + +Full Changelog: [v0.124.0...v0.125.0](https://github.com/lithic-com/lithic-python/compare/v0.124.0...v0.125.0) + +### Features + +* **api:** add card_authorization.challenge webhook event ([b765f10](https://github.com/lithic-com/lithic-python/commit/b765f10fde1ef33f2678fbd822aed1bb038682e7)) +* **api:** add out-of-band challenge method, declined status to card authorization types ([d8076eb](https://github.com/lithic-com/lithic-python/commit/d8076ebdf083ac1107e72d959bc463d20c5352a0)) + + +### Bug Fixes + +* **types:** change ConditionalValue from int to float in auth_rules ([40d3bf0](https://github.com/lithic-com/lithic-python/commit/40d3bf0fee4584c9da3329c38db4be5891cb83e6)) + + +### Documentation + +* **api:** clarify ACCOUNT_AGE attribute behavior in auth_rules conditions ([9fa7ab5](https://github.com/lithic-com/lithic-python/commit/9fa7ab57a8d841dbfba48bf4c7dc322ef30db202)) + ## 0.124.0 (2026-05-11) Full Changelog: [v0.123.0...v0.124.0](https://github.com/lithic-com/lithic-python/compare/v0.123.0...v0.124.0) diff --git a/api.md b/api.md index 2a91f069..a3aae945 100644 --- a/api.md +++ b/api.md @@ -260,6 +260,18 @@ Methods: - client.cards.financial_transactions.retrieve(financial_transaction_token, \*, card_token) -> FinancialTransaction - client.cards.financial_transactions.list(card_token, \*\*params) -> SyncSinglePage[FinancialTransaction] +# CardAuthorizations + +Types: + +```python +from lithic.types import CardAuthorization +``` + +Methods: + +- client.card_authorizations.challenge_response(event_token, \*\*params) -> None + # CardBulkOrders Types: @@ -900,6 +912,7 @@ from lithic.types import ( AccountHolderVerificationWebhookEvent, AccountHolderDocumentUpdatedWebhookEvent, CardAuthorizationApprovalRequestWebhookEvent, + CardAuthorizationChallengeWebhookEvent, CardAuthorizationChallengeResponseWebhookEvent, AuthRulesBacktestReportCreatedWebhookEvent, BalanceUpdatedWebhookEvent, diff --git a/pyproject.toml b/pyproject.toml index 5ad1d5e3..2bf23915 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "lithic" -version = "0.124.0" +version = "0.125.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 a9abdb8e..f93c988c 100644 --- a/src/lithic/_client.py +++ b/src/lithic/_client.py @@ -68,6 +68,7 @@ network_programs, external_payments, financial_accounts, + card_authorizations, responder_endpoints, management_operations, auth_stream_enrollment, @@ -96,6 +97,7 @@ from .resources.network_programs import NetworkPrograms, AsyncNetworkPrograms from .resources.external_payments import ExternalPayments, AsyncExternalPayments from .resources.three_ds.three_ds import ThreeDS, AsyncThreeDS + 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.management_operations import ManagementOperations, AsyncManagementOperations @@ -263,6 +265,12 @@ def cards(self) -> Cards: return Cards(self) + @cached_property + def card_authorizations(self) -> CardAuthorizations: + from .resources.card_authorizations import CardAuthorizations + + return CardAuthorizations(self) + @cached_property def card_bulk_orders(self) -> CardBulkOrders: from .resources.card_bulk_orders import CardBulkOrders @@ -687,6 +695,12 @@ def cards(self) -> AsyncCards: return AsyncCards(self) + @cached_property + def card_authorizations(self) -> AsyncCardAuthorizations: + from .resources.card_authorizations import AsyncCardAuthorizations + + return AsyncCardAuthorizations(self) + @cached_property def card_bulk_orders(self) -> AsyncCardBulkOrders: from .resources.card_bulk_orders import AsyncCardBulkOrders @@ -1025,6 +1039,12 @@ def cards(self) -> cards.CardsWithRawResponse: return CardsWithRawResponse(self._client.cards) + @cached_property + def card_authorizations(self) -> card_authorizations.CardAuthorizationsWithRawResponse: + from .resources.card_authorizations import CardAuthorizationsWithRawResponse + + return CardAuthorizationsWithRawResponse(self._client.card_authorizations) + @cached_property def card_bulk_orders(self) -> card_bulk_orders.CardBulkOrdersWithRawResponse: from .resources.card_bulk_orders import CardBulkOrdersWithRawResponse @@ -1222,6 +1242,12 @@ def cards(self) -> cards.AsyncCardsWithRawResponse: return AsyncCardsWithRawResponse(self._client.cards) + @cached_property + def card_authorizations(self) -> card_authorizations.AsyncCardAuthorizationsWithRawResponse: + from .resources.card_authorizations import AsyncCardAuthorizationsWithRawResponse + + return AsyncCardAuthorizationsWithRawResponse(self._client.card_authorizations) + @cached_property def card_bulk_orders(self) -> card_bulk_orders.AsyncCardBulkOrdersWithRawResponse: from .resources.card_bulk_orders import AsyncCardBulkOrdersWithRawResponse @@ -1419,6 +1445,12 @@ def cards(self) -> cards.CardsWithStreamingResponse: return CardsWithStreamingResponse(self._client.cards) + @cached_property + def card_authorizations(self) -> card_authorizations.CardAuthorizationsWithStreamingResponse: + from .resources.card_authorizations import CardAuthorizationsWithStreamingResponse + + return CardAuthorizationsWithStreamingResponse(self._client.card_authorizations) + @cached_property def card_bulk_orders(self) -> card_bulk_orders.CardBulkOrdersWithStreamingResponse: from .resources.card_bulk_orders import CardBulkOrdersWithStreamingResponse @@ -1616,6 +1648,12 @@ def cards(self) -> cards.AsyncCardsWithStreamingResponse: return AsyncCardsWithStreamingResponse(self._client.cards) + @cached_property + def card_authorizations(self) -> card_authorizations.AsyncCardAuthorizationsWithStreamingResponse: + from .resources.card_authorizations import AsyncCardAuthorizationsWithStreamingResponse + + return AsyncCardAuthorizationsWithStreamingResponse(self._client.card_authorizations) + @cached_property def card_bulk_orders(self) -> card_bulk_orders.AsyncCardBulkOrdersWithStreamingResponse: from .resources.card_bulk_orders import AsyncCardBulkOrdersWithStreamingResponse diff --git a/src/lithic/_version.py b/src/lithic/_version.py index af0c2a6d..dd6fbb88 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.124.0" # x-release-please-version +__version__ = "0.125.0" # x-release-please-version diff --git a/src/lithic/resources/__init__.py b/src/lithic/resources/__init__.py index 47ee1966..d37806d3 100644 --- a/src/lithic/resources/__init__.py +++ b/src/lithic/resources/__init__.py @@ -209,6 +209,14 @@ FinancialAccountsWithStreamingResponse, AsyncFinancialAccountsWithStreamingResponse, ) +from .card_authorizations import ( + CardAuthorizations, + AsyncCardAuthorizations, + CardAuthorizationsWithRawResponse, + AsyncCardAuthorizationsWithRawResponse, + CardAuthorizationsWithStreamingResponse, + AsyncCardAuthorizationsWithStreamingResponse, +) from .responder_endpoints import ( ResponderEndpoints, AsyncResponderEndpoints, @@ -293,6 +301,12 @@ "AsyncCardsWithRawResponse", "CardsWithStreamingResponse", "AsyncCardsWithStreamingResponse", + "CardAuthorizations", + "AsyncCardAuthorizations", + "CardAuthorizationsWithRawResponse", + "AsyncCardAuthorizationsWithRawResponse", + "CardAuthorizationsWithStreamingResponse", + "AsyncCardAuthorizationsWithStreamingResponse", "CardBulkOrders", "AsyncCardBulkOrders", "CardBulkOrdersWithRawResponse", diff --git a/src/lithic/resources/card_authorizations.py b/src/lithic/resources/card_authorizations.py new file mode 100644 index 00000000..217eb046 --- /dev/null +++ b/src/lithic/resources/card_authorizations.py @@ -0,0 +1,186 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal + +import httpx + +from .. import _legacy_response +from ..types import card_authorization_challenge_response_params +from .._types import Body, Query, Headers, NoneType, NotGiven, not_given +from .._utils import path_template, 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 + +__all__ = ["CardAuthorizations", "AsyncCardAuthorizations"] + + +class CardAuthorizations(SyncAPIResource): + @cached_property + def with_raw_response(self) -> CardAuthorizationsWithRawResponse: + """ + 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 CardAuthorizationsWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> CardAuthorizationsWithStreamingResponse: + """ + 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 CardAuthorizationsWithStreamingResponse(self) + + def challenge_response( + self, + event_token: str, + *, + response: Literal["APPROVE", "DECLINE"], + # 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, + ) -> None: + """Card program's response to Authorization Challenge. + + Programs that have + Authorization Challenges configured as Out of Band receive a + [card_authorization.challenge](https://docs.lithic.com/reference/post_card-authorization-challenge) + webhook when an authorization attempt triggers a challenge. The card program + should respond using this endpoint after the cardholder completes the challenge. + + Args: + response: Whether the cardholder has approved or declined the issued challenge + + 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 event_token: + raise ValueError(f"Expected a non-empty value for `event_token` but received {event_token!r}") + return self._post( + path_template("/v1/card_authorizations/{event_token}/challenge_response", event_token=event_token), + body=maybe_transform( + {"response": response}, + card_authorization_challenge_response_params.CardAuthorizationChallengeResponseParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + +class AsyncCardAuthorizations(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncCardAuthorizationsWithRawResponse: + """ + 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 AsyncCardAuthorizationsWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncCardAuthorizationsWithStreamingResponse: + """ + 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 AsyncCardAuthorizationsWithStreamingResponse(self) + + async def challenge_response( + self, + event_token: str, + *, + response: Literal["APPROVE", "DECLINE"], + # 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, + ) -> None: + """Card program's response to Authorization Challenge. + + Programs that have + Authorization Challenges configured as Out of Band receive a + [card_authorization.challenge](https://docs.lithic.com/reference/post_card-authorization-challenge) + webhook when an authorization attempt triggers a challenge. The card program + should respond using this endpoint after the cardholder completes the challenge. + + Args: + response: Whether the cardholder has approved or declined the issued challenge + + 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 event_token: + raise ValueError(f"Expected a non-empty value for `event_token` but received {event_token!r}") + return await self._post( + path_template("/v1/card_authorizations/{event_token}/challenge_response", event_token=event_token), + body=await async_maybe_transform( + {"response": response}, + card_authorization_challenge_response_params.CardAuthorizationChallengeResponseParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + +class CardAuthorizationsWithRawResponse: + def __init__(self, card_authorizations: CardAuthorizations) -> None: + self._card_authorizations = card_authorizations + + self.challenge_response = _legacy_response.to_raw_response_wrapper( + card_authorizations.challenge_response, + ) + + +class AsyncCardAuthorizationsWithRawResponse: + def __init__(self, card_authorizations: AsyncCardAuthorizations) -> None: + self._card_authorizations = card_authorizations + + self.challenge_response = _legacy_response.async_to_raw_response_wrapper( + card_authorizations.challenge_response, + ) + + +class CardAuthorizationsWithStreamingResponse: + def __init__(self, card_authorizations: CardAuthorizations) -> None: + self._card_authorizations = card_authorizations + + self.challenge_response = to_streamed_response_wrapper( + card_authorizations.challenge_response, + ) + + +class AsyncCardAuthorizationsWithStreamingResponse: + def __init__(self, card_authorizations: AsyncCardAuthorizations) -> None: + self._card_authorizations = card_authorizations + + self.challenge_response = async_to_streamed_response_wrapper( + card_authorizations.challenge_response, + ) diff --git a/src/lithic/resources/events/events.py b/src/lithic/resources/events/events.py index 9ce8f012..c234e310 100644 --- a/src/lithic/resources/events/events.py +++ b/src/lithic/resources/events/events.py @@ -116,6 +116,7 @@ def list( "balance.updated", "book_transfer_transaction.created", "book_transfer_transaction.updated", + "card_authorization.challenge", "card_authorization.challenge_response", "card_transaction.enhanced_data.created", "card_transaction.enhanced_data.updated", @@ -391,6 +392,7 @@ def list( "balance.updated", "book_transfer_transaction.created", "book_transfer_transaction.updated", + "card_authorization.challenge", "card_authorization.challenge_response", "card_transaction.enhanced_data.created", "card_transaction.enhanced_data.updated", diff --git a/src/lithic/resources/events/subscriptions.py b/src/lithic/resources/events/subscriptions.py index e1a8af38..80ba0b28 100644 --- a/src/lithic/resources/events/subscriptions.py +++ b/src/lithic/resources/events/subscriptions.py @@ -68,6 +68,7 @@ def create( "balance.updated", "book_transfer_transaction.created", "book_transfer_transaction.updated", + "card_authorization.challenge", "card_authorization.challenge_response", "card_transaction.enhanced_data.created", "card_transaction.enhanced_data.updated", @@ -215,6 +216,7 @@ def update( "balance.updated", "book_transfer_transaction.created", "book_transfer_transaction.updated", + "card_authorization.challenge", "card_authorization.challenge_response", "card_transaction.enhanced_data.created", "card_transaction.enhanced_data.updated", @@ -685,6 +687,7 @@ def send_simulated_example( "balance.updated", "book_transfer_transaction.created", "book_transfer_transaction.updated", + "card_authorization.challenge", "card_authorization.challenge_response", "card_transaction.enhanced_data.created", "card_transaction.enhanced_data.updated", @@ -809,6 +812,7 @@ async def create( "balance.updated", "book_transfer_transaction.created", "book_transfer_transaction.updated", + "card_authorization.challenge", "card_authorization.challenge_response", "card_transaction.enhanced_data.created", "card_transaction.enhanced_data.updated", @@ -956,6 +960,7 @@ async def update( "balance.updated", "book_transfer_transaction.created", "book_transfer_transaction.updated", + "card_authorization.challenge", "card_authorization.challenge_response", "card_transaction.enhanced_data.created", "card_transaction.enhanced_data.updated", @@ -1426,6 +1431,7 @@ async def send_simulated_example( "balance.updated", "book_transfer_transaction.created", "book_transfer_transaction.updated", + "card_authorization.challenge", "card_authorization.challenge_response", "card_transaction.enhanced_data.created", "card_transaction.enhanced_data.updated", diff --git a/src/lithic/types/__init__.py b/src/lithic/types/__init__.py index 33f2749e..b4db2542 100644 --- a/src/lithic/types/__init__.py +++ b/src/lithic/types/__init__.py @@ -59,6 +59,7 @@ from .settlement_detail import SettlementDetail as SettlementDetail from .settlement_report import SettlementReport as SettlementReport from .auth_stream_secret import AuthStreamSecret as AuthStreamSecret +from .card_authorization import CardAuthorization as CardAuthorization from .card_create_params import CardCreateParams as CardCreateParams from .card_update_params import CardUpdateParams as CardUpdateParams from .event_subscription import EventSubscription as EventSubscription @@ -253,6 +254,9 @@ from .transaction_simulate_authorization_params import ( TransactionSimulateAuthorizationParams as TransactionSimulateAuthorizationParams, ) +from .card_authorization_challenge_webhook_event import ( + CardAuthorizationChallengeWebhookEvent as CardAuthorizationChallengeWebhookEvent, +) from .external_bank_account_retry_prenote_params import ( ExternalBankAccountRetryPrenoteParams as ExternalBankAccountRetryPrenoteParams, ) @@ -289,6 +293,9 @@ from .transaction_simulate_return_reversal_params import ( TransactionSimulateReturnReversalParams as TransactionSimulateReturnReversalParams, ) +from .card_authorization_challenge_response_params import ( + CardAuthorizationChallengeResponseParams as CardAuthorizationChallengeResponseParams, +) from .dispute_evidence_upload_failed_webhook_event import ( DisputeEvidenceUploadFailedWebhookEvent as DisputeEvidenceUploadFailedWebhookEvent, ) diff --git a/src/lithic/types/auth_rules/conditional_3ds_action_parameters.py b/src/lithic/types/auth_rules/conditional_3ds_action_parameters.py index f152eb52..fbc10279 100644 --- a/src/lithic/types/auth_rules/conditional_3ds_action_parameters.py +++ b/src/lithic/types/auth_rules/conditional_3ds_action_parameters.py @@ -39,9 +39,10 @@ class Condition(BaseModel): - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the acquirer fee field in the settlement/cardholder billing currency. This is the amount the issuer should authorize against unless the issuer is paying the acquirer - fee on behalf of the cardholder. + fee on behalf of the cardholder. Use an integer value. - `RISK_SCORE`: Mastercard only: Assessment by the network of the authentication - risk level, with a higher value indicating a higher amount of risk. + risk level, with a higher value indicating a higher amount of risk. Use an + integer value. - `MESSAGE_CATEGORY`: The category of the authentication being processed. - `ADDRESS_MATCH`: Lithic's evaluation result comparing transaction's address data with the cardholder KYC data if it exists. Valid values are `MATCH`, diff --git a/src/lithic/types/auth_rules/conditional_3ds_action_parameters_param.py b/src/lithic/types/auth_rules/conditional_3ds_action_parameters_param.py index de980efe..f0991069 100644 --- a/src/lithic/types/auth_rules/conditional_3ds_action_parameters_param.py +++ b/src/lithic/types/auth_rules/conditional_3ds_action_parameters_param.py @@ -43,9 +43,10 @@ class Condition(TypedDict, total=False): - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the acquirer fee field in the settlement/cardholder billing currency. This is the amount the issuer should authorize against unless the issuer is paying the acquirer - fee on behalf of the cardholder. + fee on behalf of the cardholder. Use an integer value. - `RISK_SCORE`: Mastercard only: Assessment by the network of the authentication - risk level, with a higher value indicating a higher amount of risk. + risk level, with a higher value indicating a higher amount of risk. Use an + integer value. - `MESSAGE_CATEGORY`: The category of the authentication being processed. - `ADDRESS_MATCH`: Lithic's evaluation result comparing transaction's address data with the cardholder KYC data if it exists. Valid values are `MATCH`, diff --git a/src/lithic/types/auth_rules/conditional_ach_action_parameters.py b/src/lithic/types/auth_rules/conditional_ach_action_parameters.py index 3d47407b..49d0911f 100644 --- a/src/lithic/types/auth_rules/conditional_ach_action_parameters.py +++ b/src/lithic/types/auth_rules/conditional_ach_action_parameters.py @@ -112,7 +112,7 @@ class Condition(BaseModel): ID) of the entity initiating the ACH transaction. - `TIMESTAMP`: The timestamp of the ACH transaction in ISO 8601 format. - `TRANSACTION_AMOUNT`: The amount of the ACH transaction in minor units - (cents). + (cents). Use an integer value. - `SEC_CODE`: Standard Entry Class code indicating the type of ACH transaction. Valid values include PPD (Prearranged Payment and Deposit Entry), CCD (Corporate Credit or Debit Entry), WEB (Internet-Initiated/Mobile Entry), TEL diff --git a/src/lithic/types/auth_rules/conditional_ach_action_parameters_param.py b/src/lithic/types/auth_rules/conditional_ach_action_parameters_param.py index 85929fd3..f9ea83bc 100644 --- a/src/lithic/types/auth_rules/conditional_ach_action_parameters_param.py +++ b/src/lithic/types/auth_rules/conditional_ach_action_parameters_param.py @@ -116,7 +116,7 @@ class Condition(TypedDict, total=False): ID) of the entity initiating the ACH transaction. - `TIMESTAMP`: The timestamp of the ACH transaction in ISO 8601 format. - `TRANSACTION_AMOUNT`: The amount of the ACH transaction in minor units - (cents). + (cents). Use an integer value. - `SEC_CODE`: Standard Entry Class code indicating the type of ACH transaction. Valid values include PPD (Prearranged Payment and Deposit Entry), CCD (Corporate Credit or Debit Entry), WEB (Internet-Initiated/Mobile Entry), TEL diff --git a/src/lithic/types/auth_rules/conditional_authorization_action_parameters.py b/src/lithic/types/auth_rules/conditional_authorization_action_parameters.py index 4b288ac2..2b8fbb89 100644 --- a/src/lithic/types/auth_rules/conditional_authorization_action_parameters.py +++ b/src/lithic/types/auth_rules/conditional_authorization_action_parameters.py @@ -109,26 +109,27 @@ class Condition(BaseModel): - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the acquirer fee field in the settlement/cardholder billing currency. This is the amount the issuer should authorize against unless the issuer is paying the acquirer - fee on behalf of the cardholder. + fee on behalf of the cardholder. Use an integer value. - `CASH_AMOUNT`: The cash amount of the transaction in minor units (cents). This - represents the amount of cash being withdrawn or advanced. + represents the amount of cash being withdrawn or advanced. Use an integer + value. - `RISK_SCORE`: Network-provided score assessing risk level associated with a given authorization. Scores are on a range of 0-999, with 0 representing the lowest risk and 999 representing the highest risk. For Visa transactions, where the raw score has a range of 0-99, Lithic will normalize the score by - multiplying the raw score by 10x. + multiplying the raw score by 10x. Use an integer value. - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in the - trailing 15 minutes before the authorization. + trailing 15 minutes before the authorization. Use an integer value. - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in the - trailing hour up and until the authorization. + trailing hour up and until the authorization. Use an integer value. - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in the - trailing 24 hours up and until the authorization. + trailing 24 hours up and until the authorization. Use an integer value. - `CARD_DECLINE_COUNT_15M`: The number of declined transactions on the card in - the trailing 15 minutes before the authorization. + the trailing 15 minutes before the authorization. Use an integer value. - `CARD_DECLINE_COUNT_1H`: The number of declined transactions on the card in - the trailing hour up and until the authorization. + the trailing hour up and until the authorization. Use an integer value. - `CARD_DECLINE_COUNT_24H`: The number of declined transactions on the card in - the trailing 24 hours up and until the authorization. + the trailing 24 hours up and until the authorization. Use an integer value. - `CARD_STATE`: The current state of the card associated with the transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. @@ -153,18 +154,21 @@ class Condition(BaseModel): data, the service location postal code is used. Otherwise, falls back to the card acceptor postal code. - `CARD_AGE`: The age of the card in seconds at the time of the authorization. + Use an integer value. - `ACCOUNT_AGE`: The age of the account holder's account in seconds at the time - of the authorization. + of the authorization. Use an integer value. For programs where Lithic does not + manage or retain account holder data, this attribute does not evaluate. - `AMOUNT_Z_SCORE`: The z-score of the transaction amount relative to the entity's transaction history. Null if fewer than 30 approved transactions in the specified window. Requires `parameters.scope` and `parameters.interval`. + Use a decimal value. - `AVG_TRANSACTION_AMOUNT`: The average approved transaction amount for the entity over the specified window, in cents. Requires `parameters.scope` and - `parameters.interval`. + `parameters.interval`. Use a decimal value. - `STDEV_TRANSACTION_AMOUNT`: The standard deviation of approved transaction amounts for the entity over the specified window, in cents. Null if fewer than 30 approved transactions in the specified window. Requires `parameters.scope` - and `parameters.interval`. + and `parameters.interval`. Use a decimal value. - `IS_NEW_COUNTRY`: Whether the transaction's merchant country has not been seen in the entity's transaction history. Valid values are `TRUE`, `FALSE`. Requires `parameters.scope`. @@ -175,26 +179,31 @@ class Condition(BaseModel): Valid values are `TRUE`, `FALSE`. Requires `parameters.scope`. - `CONSECUTIVE_DECLINES`: The number of consecutive declined transactions for the entity over the last 30 days (rolling). Requires `parameters.scope`. Not - supported for `BUSINESS_ACCOUNT` scope. + supported for `BUSINESS_ACCOUNT` scope. Use an integer value. - `TIME_SINCE_LAST_TRANSACTION`: The number of days since the last approved - transaction for the entity. Requires `parameters.scope`. + transaction for the entity, rounded to the nearest whole day. Requires + `parameters.scope`. Use an integer value. - `DISTINCT_COUNTRY_COUNT`: The number of distinct merchant countries seen in - the entity's transaction history. Requires `parameters.scope`. + the entity's transaction history. Requires `parameters.scope`. Use an integer + value. - `IS_NEW_MERCHANT`: Whether the card acceptor ID has not been seen in the card's approved transaction history (capped at the 1000 most recently seen merchants). Valid values are `TRUE`, `FALSE`. Card-scoped only; no `parameters` required. - `THREE_DS_SUCCESS_RATE`: The 3DS authentication success rate for the card, as a percentage from 0.0 to 100.0. Card-scoped only; no `parameters` required. + Use a decimal value. - `TRAVEL_SPEED`: The estimated speed of travel derived from the distance between the postal code centers of the last card-present transaction and the current transaction, divided by the elapsed time. Null if there is no prior card-present transaction, if either postal code cannot be geocoded, or if - elapsed time is zero. Requires `parameters.unit` set to `MPH` or `KPH`. + elapsed time is zero. Requires `parameters.unit` set to `MPH` or `KPH`. Use a + decimal value. - `DISTANCE_FROM_LAST_TRANSACTION`: The estimated distance between the postal code centers of the last card-present transaction and the current transaction. Null if there is no prior card-present transaction or if either postal code cannot be geocoded. Requires `parameters.unit` set to `MILES` or `KILOMETERS`. + Use a decimal value. """ operation: ConditionalOperation diff --git a/src/lithic/types/auth_rules/conditional_authorization_action_parameters_param.py b/src/lithic/types/auth_rules/conditional_authorization_action_parameters_param.py index e903a5e0..84eb0406 100644 --- a/src/lithic/types/auth_rules/conditional_authorization_action_parameters_param.py +++ b/src/lithic/types/auth_rules/conditional_authorization_action_parameters_param.py @@ -113,26 +113,27 @@ class Condition(TypedDict, total=False): - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the acquirer fee field in the settlement/cardholder billing currency. This is the amount the issuer should authorize against unless the issuer is paying the acquirer - fee on behalf of the cardholder. + fee on behalf of the cardholder. Use an integer value. - `CASH_AMOUNT`: The cash amount of the transaction in minor units (cents). This - represents the amount of cash being withdrawn or advanced. + represents the amount of cash being withdrawn or advanced. Use an integer + value. - `RISK_SCORE`: Network-provided score assessing risk level associated with a given authorization. Scores are on a range of 0-999, with 0 representing the lowest risk and 999 representing the highest risk. For Visa transactions, where the raw score has a range of 0-99, Lithic will normalize the score by - multiplying the raw score by 10x. + multiplying the raw score by 10x. Use an integer value. - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in the - trailing 15 minutes before the authorization. + trailing 15 minutes before the authorization. Use an integer value. - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in the - trailing hour up and until the authorization. + trailing hour up and until the authorization. Use an integer value. - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in the - trailing 24 hours up and until the authorization. + trailing 24 hours up and until the authorization. Use an integer value. - `CARD_DECLINE_COUNT_15M`: The number of declined transactions on the card in - the trailing 15 minutes before the authorization. + the trailing 15 minutes before the authorization. Use an integer value. - `CARD_DECLINE_COUNT_1H`: The number of declined transactions on the card in - the trailing hour up and until the authorization. + the trailing hour up and until the authorization. Use an integer value. - `CARD_DECLINE_COUNT_24H`: The number of declined transactions on the card in - the trailing 24 hours up and until the authorization. + the trailing 24 hours up and until the authorization. Use an integer value. - `CARD_STATE`: The current state of the card associated with the transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. @@ -157,18 +158,21 @@ class Condition(TypedDict, total=False): data, the service location postal code is used. Otherwise, falls back to the card acceptor postal code. - `CARD_AGE`: The age of the card in seconds at the time of the authorization. + Use an integer value. - `ACCOUNT_AGE`: The age of the account holder's account in seconds at the time - of the authorization. + of the authorization. Use an integer value. For programs where Lithic does not + manage or retain account holder data, this attribute does not evaluate. - `AMOUNT_Z_SCORE`: The z-score of the transaction amount relative to the entity's transaction history. Null if fewer than 30 approved transactions in the specified window. Requires `parameters.scope` and `parameters.interval`. + Use a decimal value. - `AVG_TRANSACTION_AMOUNT`: The average approved transaction amount for the entity over the specified window, in cents. Requires `parameters.scope` and - `parameters.interval`. + `parameters.interval`. Use a decimal value. - `STDEV_TRANSACTION_AMOUNT`: The standard deviation of approved transaction amounts for the entity over the specified window, in cents. Null if fewer than 30 approved transactions in the specified window. Requires `parameters.scope` - and `parameters.interval`. + and `parameters.interval`. Use a decimal value. - `IS_NEW_COUNTRY`: Whether the transaction's merchant country has not been seen in the entity's transaction history. Valid values are `TRUE`, `FALSE`. Requires `parameters.scope`. @@ -179,26 +183,31 @@ class Condition(TypedDict, total=False): Valid values are `TRUE`, `FALSE`. Requires `parameters.scope`. - `CONSECUTIVE_DECLINES`: The number of consecutive declined transactions for the entity over the last 30 days (rolling). Requires `parameters.scope`. Not - supported for `BUSINESS_ACCOUNT` scope. + supported for `BUSINESS_ACCOUNT` scope. Use an integer value. - `TIME_SINCE_LAST_TRANSACTION`: The number of days since the last approved - transaction for the entity. Requires `parameters.scope`. + transaction for the entity, rounded to the nearest whole day. Requires + `parameters.scope`. Use an integer value. - `DISTINCT_COUNTRY_COUNT`: The number of distinct merchant countries seen in - the entity's transaction history. Requires `parameters.scope`. + the entity's transaction history. Requires `parameters.scope`. Use an integer + value. - `IS_NEW_MERCHANT`: Whether the card acceptor ID has not been seen in the card's approved transaction history (capped at the 1000 most recently seen merchants). Valid values are `TRUE`, `FALSE`. Card-scoped only; no `parameters` required. - `THREE_DS_SUCCESS_RATE`: The 3DS authentication success rate for the card, as a percentage from 0.0 to 100.0. Card-scoped only; no `parameters` required. + Use a decimal value. - `TRAVEL_SPEED`: The estimated speed of travel derived from the distance between the postal code centers of the last card-present transaction and the current transaction, divided by the elapsed time. Null if there is no prior card-present transaction, if either postal code cannot be geocoded, or if - elapsed time is zero. Requires `parameters.unit` set to `MPH` or `KPH`. + elapsed time is zero. Requires `parameters.unit` set to `MPH` or `KPH`. Use a + decimal value. - `DISTANCE_FROM_LAST_TRANSACTION`: The estimated distance between the postal code centers of the last card-present transaction and the current transaction. Null if there is no prior card-present transaction or if either postal code cannot be geocoded. Requires `parameters.unit` set to `MILES` or `KILOMETERS`. + Use a decimal value. """ operation: Required[ConditionalOperation] diff --git a/src/lithic/types/auth_rules/conditional_card_transaction_update_action_parameters.py b/src/lithic/types/auth_rules/conditional_card_transaction_update_action_parameters.py index 007cbf75..1b6efd0b 100644 --- a/src/lithic/types/auth_rules/conditional_card_transaction_update_action_parameters.py +++ b/src/lithic/types/auth_rules/conditional_card_transaction_update_action_parameters.py @@ -65,12 +65,12 @@ class Condition(BaseModel): - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the acquirer fee field in the settlement/cardholder billing currency. This is the amount the issuer should authorize against unless the issuer is paying the acquirer - fee on behalf of the cardholder. + fee on behalf of the cardholder. Use an integer value. - `RISK_SCORE`: Network-provided score assessing risk level associated with a given authorization. Scores are on a range of 0-999, with 0 representing the lowest risk and 999 representing the highest risk. For Visa transactions, where the raw score has a range of 0-99, Lithic will normalize the score by - multiplying the raw score by 10x. + multiplying the raw score by 10x. Use an integer value. - `TRANSACTION_STATUS`: The status of the transaction. Valid values are `PENDING`, `VOIDED`, `SETTLING`, `SETTLED`, `BOUNCED`, `RETURNED`, `DECLINED`, `EXPIRED`. @@ -91,15 +91,17 @@ class Condition(BaseModel): - `WALLET_TYPE`: For transactions using a digital wallet token, indicates the source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. - - `CARD_AGE`: The age of the card in seconds at the time of the transaction. + - `CARD_AGE`: The age of the card in seconds at the time of the transaction. Use + an integer value. - `ACCOUNT_AGE`: The age of the account in seconds at the time of the - transaction. + transaction. Use an integer value. For programs where Lithic does not manage + or retain account holder data, this attribute does not evaluate. - `SPEND_VELOCITY_COUNT`: The number of transactions matching the specified filters within the given period. Requires `parameters` with `scope`, `period`, - and optional `filters`. + and optional `filters`. Use an integer value. - `SPEND_VELOCITY_AMOUNT`: The total spend amount (in cents) of transactions matching the specified filters within the given period. Requires `parameters` - with `scope`, `period`, and optional `filters`. + with `scope`, `period`, and optional `filters`. Use an integer value. """ operation: ConditionalOperation diff --git a/src/lithic/types/auth_rules/conditional_card_transaction_update_action_parameters_param.py b/src/lithic/types/auth_rules/conditional_card_transaction_update_action_parameters_param.py index f35e09e0..e499dfbd 100644 --- a/src/lithic/types/auth_rules/conditional_card_transaction_update_action_parameters_param.py +++ b/src/lithic/types/auth_rules/conditional_card_transaction_update_action_parameters_param.py @@ -69,12 +69,12 @@ class Condition(TypedDict, total=False): - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the acquirer fee field in the settlement/cardholder billing currency. This is the amount the issuer should authorize against unless the issuer is paying the acquirer - fee on behalf of the cardholder. + fee on behalf of the cardholder. Use an integer value. - `RISK_SCORE`: Network-provided score assessing risk level associated with a given authorization. Scores are on a range of 0-999, with 0 representing the lowest risk and 999 representing the highest risk. For Visa transactions, where the raw score has a range of 0-99, Lithic will normalize the score by - multiplying the raw score by 10x. + multiplying the raw score by 10x. Use an integer value. - `TRANSACTION_STATUS`: The status of the transaction. Valid values are `PENDING`, `VOIDED`, `SETTLING`, `SETTLED`, `BOUNCED`, `RETURNED`, `DECLINED`, `EXPIRED`. @@ -95,15 +95,17 @@ class Condition(TypedDict, total=False): - `WALLET_TYPE`: For transactions using a digital wallet token, indicates the source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. - - `CARD_AGE`: The age of the card in seconds at the time of the transaction. + - `CARD_AGE`: The age of the card in seconds at the time of the transaction. Use + an integer value. - `ACCOUNT_AGE`: The age of the account in seconds at the time of the - transaction. + transaction. Use an integer value. For programs where Lithic does not manage + or retain account holder data, this attribute does not evaluate. - `SPEND_VELOCITY_COUNT`: The number of transactions matching the specified filters within the given period. Requires `parameters` with `scope`, `period`, - and optional `filters`. + and optional `filters`. Use an integer value. - `SPEND_VELOCITY_AMOUNT`: The total spend amount (in cents) of transactions matching the specified filters within the given period. Requires `parameters` - with `scope`, `period`, and optional `filters`. + with `scope`, `period`, and optional `filters`. Use an integer value. """ operation: Required[ConditionalOperation] diff --git a/src/lithic/types/auth_rules/conditional_tokenization_action_parameters.py b/src/lithic/types/auth_rules/conditional_tokenization_action_parameters.py index a0cd2e6c..4b8a1f44 100644 --- a/src/lithic/types/auth_rules/conditional_tokenization_action_parameters.py +++ b/src/lithic/types/auth_rules/conditional_tokenization_action_parameters.py @@ -100,10 +100,10 @@ class Condition(BaseModel): `SAMSUNG_PAY`, `UNKNOWN`, `VISA_CHECKOUT`. - `WALLET_ACCOUNT_SCORE`: Risk score for the account in the digital wallet. Numeric value where lower numbers indicate higher risk (e.g., 1 = high risk, 2 - = medium risk). + = medium risk). Use an integer value. - `WALLET_DEVICE_SCORE`: Risk score for the device in the digital wallet. Numeric value where lower numbers indicate higher risk (e.g., 1 = high risk, 2 - = medium risk). + = medium risk). Use an integer value. - `WALLET_RECOMMENDED_DECISION`: The decision recommended by the digital wallet provider. Valid values include APPROVE, DECLINE, REQUIRE_ADDITIONAL_AUTHENTICATION. diff --git a/src/lithic/types/auth_rules/conditional_tokenization_action_parameters_param.py b/src/lithic/types/auth_rules/conditional_tokenization_action_parameters_param.py index 5f8d411b..19296991 100644 --- a/src/lithic/types/auth_rules/conditional_tokenization_action_parameters_param.py +++ b/src/lithic/types/auth_rules/conditional_tokenization_action_parameters_param.py @@ -100,10 +100,10 @@ class Condition(TypedDict, total=False): `SAMSUNG_PAY`, `UNKNOWN`, `VISA_CHECKOUT`. - `WALLET_ACCOUNT_SCORE`: Risk score for the account in the digital wallet. Numeric value where lower numbers indicate higher risk (e.g., 1 = high risk, 2 - = medium risk). + = medium risk). Use an integer value. - `WALLET_DEVICE_SCORE`: Risk score for the device in the digital wallet. Numeric value where lower numbers indicate higher risk (e.g., 1 = high risk, 2 - = medium risk). + = medium risk). Use an integer value. - `WALLET_RECOMMENDED_DECISION`: The decision recommended by the digital wallet provider. Valid values include APPROVE, DECLINE, REQUIRE_ADDITIONAL_AUTHENTICATION. diff --git a/src/lithic/types/auth_rules/conditional_value.py b/src/lithic/types/auth_rules/conditional_value.py index 2f0a8910..91c7dc62 100644 --- a/src/lithic/types/auth_rules/conditional_value.py +++ b/src/lithic/types/auth_rules/conditional_value.py @@ -6,4 +6,4 @@ __all__ = ["ConditionalValue"] -ConditionalValue: TypeAlias = Union[str, int, List[str], datetime] +ConditionalValue: TypeAlias = Union[str, int, float, List[str], datetime] diff --git a/src/lithic/types/auth_rules/conditional_value_param.py b/src/lithic/types/auth_rules/conditional_value_param.py index c1e27c62..dd30fbd2 100644 --- a/src/lithic/types/auth_rules/conditional_value_param.py +++ b/src/lithic/types/auth_rules/conditional_value_param.py @@ -10,4 +10,4 @@ __all__ = ["ConditionalValueParam"] -ConditionalValueParam: TypeAlias = Union[str, int, SequenceNotStr[str], Union[str, datetime]] +ConditionalValueParam: TypeAlias = Union[str, int, float, SequenceNotStr[str], Union[str, datetime]] diff --git a/src/lithic/types/card_authorization.py b/src/lithic/types/card_authorization.py new file mode 100644 index 00000000..b477c63f --- /dev/null +++ b/src/lithic/types/card_authorization.py @@ -0,0 +1,562 @@ +# 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 .shared import merchant +from .._models import BaseModel +from .token_info import TokenInfo +from .shared.currency import Currency +from .cardholder_authentication import CardholderAuthentication + +__all__ = [ + "CardAuthorization", + "Amounts", + "AmountsCardholder", + "AmountsHold", + "AmountsMerchant", + "AmountsSettlement", + "Avs", + "Card", + "Merchant", + "ServiceLocation", + "FleetInfo", + "LatestChallenge", + "NetworkSpecificData", + "NetworkSpecificDataMastercard", + "NetworkSpecificDataMastercardOnBehalfServiceResult", + "NetworkSpecificDataVisa", + "Pos", + "PosEntryMode", + "PosTerminal", +] + + +class AmountsCardholder(BaseModel): + amount: int + """Amount in the smallest unit of the applicable currency (e.g., cents)""" + + conversion_rate: str + """Exchange rate used for currency conversion""" + + currency: Currency + """3-character alphabetic ISO 4217 currency""" + + +class AmountsHold(BaseModel): + amount: int + """Amount in the smallest unit of the applicable currency (e.g., cents)""" + + currency: Currency + """3-character alphabetic ISO 4217 currency""" + + +class AmountsMerchant(BaseModel): + amount: int + """Amount in the smallest unit of the applicable currency (e.g., cents)""" + + currency: Currency + """3-character alphabetic ISO 4217 currency""" + + +class AmountsSettlement(BaseModel): + amount: int + """Amount in the smallest unit of the applicable currency (e.g., cents)""" + + currency: Currency + """3-character alphabetic ISO 4217 currency""" + + +class Amounts(BaseModel): + """Structured amounts for this authorization. + + The `cardholder` and `merchant` amounts reflect the original network authorization values. For programs with hold adjustments enabled (e.g., automated fuel dispensers or tipping MCCs), the `hold` amount may exceed the `cardholder` and `merchant` amounts to account for anticipated final transaction amounts such as tips or fuel fill-ups + """ + + cardholder: AmountsCardholder + + hold: Optional[AmountsHold] = None + + merchant: AmountsMerchant + + settlement: Optional[AmountsSettlement] = None + + +class Avs(BaseModel): + address: str + """Cardholder address""" + + address_on_file_match: Literal["MATCH", "MATCH_ADDRESS_ONLY", "MATCH_ZIP_ONLY", "MISMATCH", "NOT_PRESENT"] + """ + Lithic's evaluation result comparing the transaction's address data with the + cardholder KYC data if it exists. In the event Lithic does not have any + Cardholder KYC data, or the transaction does not contain any address data, + NOT_PRESENT will be returned + """ + + zipcode: str + """Cardholder ZIP code""" + + +class Card(BaseModel): + """Card object in ASA""" + + token: str + """Globally unique identifier for the card.""" + + last_four: str + """Last four digits of the card number""" + + memo: str + """Customizable name to identify the card""" + + spend_limit: int + """Amount (in cents) to limit approved authorizations. + + Purchase requests above the spend limit will be declined (refunds and credits + will be approved). + + Note that while spend limits are enforced based on authorized and settled volume + on a card, they are not recommended to be used for balance or + reconciliation-level accuracy. Spend limits also cannot block force posted + charges (i.e., when a merchant sends a clearing message without a prior + authorization). + """ + + spend_limit_duration: Literal["ANNUALLY", "FOREVER", "MONTHLY", "TRANSACTION"] + """ + Note that to support recurring monthly payments, which can occur on different + day every month, the time window we consider for MONTHLY velocity starts 6 days + after the current calendar date one month prior. + """ + + state: Literal["CLOSED", "OPEN", "PAUSED", "PENDING_ACTIVATION", "PENDING_FULFILLMENT"] + + type: Literal["SINGLE_USE", "MERCHANT_LOCKED", "UNLOCKED", "PHYSICAL", "DIGITAL_WALLET", "VIRTUAL"] + + +class Merchant(merchant.Merchant): + """Merchant information including full location details.""" + + phone_number: Optional[str] = None + """Phone number of card acceptor.""" + + postal_code: Optional[str] = None + """Postal code of card acceptor.""" + + street_address: Optional[str] = None + """Street address of card acceptor.""" + + +class ServiceLocation(BaseModel): + """ + Where the cardholder received the service, when different from the card acceptor location. This is populated from network data elements such as Mastercard DE-122 SE1 SF9-14 and Visa F34 DS02. + """ + + city: Optional[str] = None + """City of service location.""" + + country: Optional[str] = None + """Country code of service location, ISO 3166-1 alpha-3.""" + + postal_code: Optional[str] = None + """Postal code of service location.""" + + state: Optional[str] = None + """State/province code of service location, ISO 3166-2.""" + + street_address: Optional[str] = None + """Street address of service location.""" + + +class FleetInfo(BaseModel): + """ + Optional Object containing information if the Card is a part of a Fleet managed program + """ + + fleet_prompt_code: Literal["NO_PROMPT", "VEHICLE_NUMBER", "DRIVER_NUMBER"] + """Code indicating what the driver was prompted to enter at time of purchase. + + This is configured at a program level and is a static configuration, and does + not change on a request to request basis + """ + + fleet_restriction_code: Literal["NO_RESTRICTIONS", "FUEL_ONLY"] + """Code indicating which restrictions, if any, there are on purchase. + + This is configured at a program level and is a static configuration, and does + not change on a request to request basis + """ + + driver_number: Optional[str] = None + """Number representing the driver""" + + vehicle_number: Optional[str] = None + """Number associated with the vehicle""" + + +class LatestChallenge(BaseModel): + """ + The latest Authorization Challenge that was issued to the cardholder for this merchant. + """ + + method: Literal["SMS", "OUT_OF_BAND"] + """The method used to deliver the challenge to the cardholder + + - `SMS` - Challenge was delivered via SMS + - `OUT_OF_BAND` - Challenge was delivered via an out-of-band method + """ + + phone_number: Optional[str] = None + """The phone number used for sending the Authorization Challenge. + + Present only when the challenge method is `SMS`. + """ + + status: Literal["COMPLETED", "DECLINED", "PENDING", "EXPIRED", "ERROR"] + """The status of the Authorization Challenge + + - `COMPLETED` - Challenge was successfully completed by the cardholder + - `DECLINED` - Challenge was declined by the cardholder + - `PENDING` - Challenge is still open + - `EXPIRED` - Challenge has expired without being completed + - `ERROR` - There was an error processing the challenge + """ + + completed_at: Optional[datetime] = None + """The date and time when the Authorization Challenge was completed in UTC. + + Present only if the status is `COMPLETED`. + """ + + +class NetworkSpecificDataMastercardOnBehalfServiceResult(BaseModel): + result_1: str + """Indicates the results of the service processing.""" + + result_2: str + """Identifies the results of the service processing.""" + + service: str + """Indicates the service performed on the transaction.""" + + +class NetworkSpecificDataMastercard(BaseModel): + ecommerce_security_level_indicator: Optional[str] = None + """Indicates the electronic commerce security level and UCAF collection.""" + + on_behalf_service_result: Optional[List[NetworkSpecificDataMastercardOnBehalfServiceResult]] = None + """The On-behalf Service performed on the transaction and the results. + + Contains all applicable, on-behalf service results that were performed on a + given transaction. + """ + + transaction_type_identifier: Optional[str] = None + """Indicates the type of additional transaction purpose.""" + + +class NetworkSpecificDataVisa(BaseModel): + business_application_identifier: Optional[str] = None + """ + Identifies the purpose or category of a transaction, used to classify and + process transactions according to Visa’s rules. + """ + + +class NetworkSpecificData(BaseModel): + """ + Contains raw data provided by the card network, including attributes that provide further context about the authorization. If populated by the network, data is organized by Lithic and passed through without further modification. Please consult the official network documentation for more details about these values and how to use them. This object is only available to certain programs- contact your Customer Success Manager to discuss enabling access. + """ + + mastercard: Optional[NetworkSpecificDataMastercard] = None + + visa: Optional[NetworkSpecificDataVisa] = None + + +class PosEntryMode(BaseModel): + """POS > Entry Mode object in ASA""" + + card: Optional[Literal["PRESENT", "NOT_PRESENT", "UNKNOWN"]] = None + """Card Presence Indicator""" + + cardholder: Optional[ + Literal[ + "DEFERRED_BILLING", + "ELECTRONIC_ORDER", + "INSTALLMENT", + "MAIL_ORDER", + "NOT_PRESENT", + "PRESENT", + "REOCCURRING", + "TELEPHONE_ORDER", + "UNKNOWN", + ] + ] = None + """Cardholder Presence Indicator""" + + pan: Optional[ + Literal[ + "AUTO_ENTRY", + "BAR_CODE", + "CONTACTLESS", + "ECOMMERCE", + "ERROR_KEYED", + "ERROR_MAGNETIC_STRIPE", + "ICC", + "KEY_ENTERED", + "MAGNETIC_STRIPE", + "MANUAL", + "OCR", + "SECURE_CARDLESS", + "UNSPECIFIED", + "UNKNOWN", + "CREDENTIAL_ON_FILE", + ] + ] = None + """Method of entry for the PAN""" + + pin_entered: Optional[bool] = None + """Indicates whether the cardholder entered the PIN. True if the PIN was entered.""" + + +class PosTerminal(BaseModel): + attended: bool + """True if a clerk is present at the sale.""" + + card_retention_capable: bool + """True if the terminal is capable of retaining the card.""" + + on_premise: bool + """True if the sale was made at the place of business (vs. mobile).""" + + operator: Literal["ADMINISTRATIVE", "CARDHOLDER", "CARD_ACCEPTOR", "UNKNOWN"] + """The person that is designated to swipe the card""" + + partial_approval_capable: bool + """True if the terminal is capable of partial approval. + + Partial approval is when part of a transaction is approved and another payment + must be used for the remainder. Example scenario: A $40 transaction is attempted + on a prepaid card with a $25 balance. If partial approval is enabled, $25 can be + authorized, at which point the POS will prompt the user for an additional + payment of $15. + """ + + pin_capability: Literal["CAPABLE", "INOPERATIVE", "NOT_CAPABLE", "UNSPECIFIED"] + """Status of whether the POS is able to accept PINs""" + + type: Literal[ + "ADMINISTRATIVE", + "ATM", + "AUTHORIZATION", + "COUPON_MACHINE", + "DIAL_TERMINAL", + "ECOMMERCE", + "ECR", + "FUEL_MACHINE", + "HOME_TERMINAL", + "MICR", + "OFF_PREMISE", + "PAYMENT", + "PDA", + "PHONE", + "POINT", + "POS_TERMINAL", + "PUBLIC_UTILITY", + "SELF_SERVICE", + "TELEVISION", + "TELLER", + "TRAVELERS_CHECK_MACHINE", + "VENDING", + "VOICE", + "UNKNOWN", + ] + """POS Type""" + + acceptor_terminal_id: Optional[str] = None + """ + Uniquely identifies a terminal at the card acceptor location of acquiring + institutions or merchant POS Systems. Left justified with trailing spaces. + """ + + +class Pos(BaseModel): + entry_mode: Optional[PosEntryMode] = None + """POS > Entry Mode object in ASA""" + + terminal: Optional[PosTerminal] = None + + +class CardAuthorization(BaseModel): + """Card Authorization""" + + token: str + """The provisional transaction group uuid associated with the authorization""" + + acquirer_fee: int + """Fee (in cents) assessed by the merchant and paid for by the cardholder. + + Will be zero if no fee is assessed. Rebates may be transmitted as a negative + value to indicate credited fees. + """ + + amount: int + """Deprecated, use `amounts`. + + Authorization amount of the transaction (in cents), including any acquirer fees. + The contents of this field are identical to `authorization_amount`. + """ + + amounts: Amounts + """Structured amounts for this authorization. + + The `cardholder` and `merchant` amounts reflect the original network + authorization values. For programs with hold adjustments enabled (e.g., + automated fuel dispensers or tipping MCCs), the `hold` amount may exceed the + `cardholder` and `merchant` amounts to account for anticipated final transaction + amounts such as tips or fuel fill-ups + """ + + authorization_amount: int + """Deprecated, use `amounts`. + + The base transaction amount (in cents) plus the acquirer fee field. This is the + amount the issuer should authorize against unless the issuer is paying the + acquirer fee on behalf of the cardholder. + """ + + avs: Avs + + card: Card + """Card object in ASA""" + + cardholder_currency: str + """Deprecated, use `amounts`. + + 3-character alphabetic ISO 4217 code for cardholder's billing currency. + """ + + cash_amount: int + """ + The portion of the transaction requested as cash back by the cardholder, and + does not include any acquirer fees. The amount field includes the purchase + amount, the requested cash back amount, and any acquirer fees. + + If no cash back was requested, the value of this field will be 0, and the field + will always be present. + """ + + created: datetime + """Date and time when the transaction first occurred in UTC.""" + + merchant: Merchant + """Merchant information including full location details.""" + + merchant_amount: int + """Deprecated, use `amounts`. + + The amount that the merchant will receive, denominated in `merchant_currency` + and in the smallest currency unit. Note the amount includes `acquirer_fee`, + similar to `authorization_amount`. It will be different from + `authorization_amount` if the merchant is taking payment in a different + currency. + """ + + merchant_currency: str + """3-character alphabetic ISO 4217 code for the local currency of the transaction.""" + + service_location: Optional[ServiceLocation] = None + """ + Where the cardholder received the service, when different from the card acceptor + location. This is populated from network data elements such as Mastercard DE-122 + SE1 SF9-14 and Visa F34 DS02. + """ + + settled_amount: int + """Deprecated, use `amounts`. + + Amount (in cents) of the transaction that has been settled, including any + acquirer fees. + """ + + status: Literal[ + "AUTHORIZATION", + "CREDIT_AUTHORIZATION", + "FINANCIAL_AUTHORIZATION", + "FINANCIAL_CREDIT_AUTHORIZATION", + "BALANCE_INQUIRY", + ] + """The type of authorization request that this request is for. + + Note that `CREDIT_AUTHORIZATION` and `FINANCIAL_CREDIT_AUTHORIZATION` is only + available to users with credit decisioning via ASA enabled. + """ + + transaction_initiator: Literal["CARDHOLDER", "MERCHANT", "UNKNOWN"] + """The entity that initiated the transaction.""" + + account_type: Optional[Literal["CHECKING", "SAVINGS"]] = None + + cardholder_authentication: Optional[CardholderAuthentication] = None + + cashback: Optional[int] = None + """Deprecated, use `cash_amount`.""" + + conversion_rate: Optional[float] = None + """Deprecated, use `amounts`. + + If the transaction was requested in a currency other than the settlement + currency, this field will be populated to indicate the rate used to translate + the merchant_amount to the amount (i.e., `merchant_amount` x `conversion_rate` = + `amount`). Note that the `merchant_amount` is in the local currency and the + amount is in the settlement currency. + """ + + event_token: Optional[str] = None + """The event token associated with the authorization. + + This field is only set for programs enrolled into the beta. + """ + + fleet_info: Optional[FleetInfo] = None + """ + Optional Object containing information if the Card is a part of a Fleet managed + program + """ + + latest_challenge: Optional[LatestChallenge] = None + """ + The latest Authorization Challenge that was issued to the cardholder for this + merchant. + """ + + network: Optional[Literal["AMEX", "INTERLINK", "MAESTRO", "MASTERCARD", "UNKNOWN", "VISA"]] = None + """Card network of the authorization.""" + + network_risk_score: Optional[int] = None + """ + Network-provided score assessing risk level associated with a given + authorization. Scores are on a range of 0-999, with 0 representing the lowest + risk and 999 representing the highest risk. For Visa transactions, where the raw + score has a range of 0-99, Lithic will normalize the score by multiplying the + raw score by 10x. + """ + + network_specific_data: Optional[NetworkSpecificData] = None + """ + Contains raw data provided by the card network, including attributes that + provide further context about the authorization. If populated by the network, + data is organized by Lithic and passed through without further modification. + Please consult the official network documentation for more details about these + values and how to use them. This object is only available to certain programs- + contact your Customer Success Manager to discuss enabling access. + """ + + pos: Optional[Pos] = None + + token_info: Optional[TokenInfo] = None + + ttl: Optional[datetime] = None + """Deprecated: approximate time-to-live for the authorization.""" diff --git a/src/lithic/types/card_authorization_approval_request_webhook_event.py b/src/lithic/types/card_authorization_approval_request_webhook_event.py index 489261b9..2c020891 100644 --- a/src/lithic/types/card_authorization_approval_request_webhook_event.py +++ b/src/lithic/types/card_authorization_approval_request_webhook_event.py @@ -1,551 +1,13 @@ # 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 .shared import merchant -from .._models import BaseModel -from .token_info import TokenInfo -from .shared.currency import Currency -from .cardholder_authentication import CardholderAuthentication +from .card_authorization import CardAuthorization -__all__ = [ - "CardAuthorizationApprovalRequestWebhookEvent", - "Amounts", - "AmountsCardholder", - "AmountsHold", - "AmountsMerchant", - "AmountsSettlement", - "Avs", - "Card", - "Merchant", - "ServiceLocation", - "FleetInfo", - "LatestChallenge", - "NetworkSpecificData", - "NetworkSpecificDataMastercard", - "NetworkSpecificDataMastercardOnBehalfServiceResult", - "NetworkSpecificDataVisa", - "Pos", - "PosEntryMode", - "PosTerminal", -] +__all__ = ["CardAuthorizationApprovalRequestWebhookEvent"] -class AmountsCardholder(BaseModel): - amount: int - """Amount in the smallest unit of the applicable currency (e.g., cents)""" - - conversion_rate: str - """Exchange rate used for currency conversion""" - - currency: Currency - """3-character alphabetic ISO 4217 currency""" - - -class AmountsHold(BaseModel): - amount: int - """Amount in the smallest unit of the applicable currency (e.g., cents)""" - - currency: Currency - """3-character alphabetic ISO 4217 currency""" - - -class AmountsMerchant(BaseModel): - amount: int - """Amount in the smallest unit of the applicable currency (e.g., cents)""" - - currency: Currency - """3-character alphabetic ISO 4217 currency""" - - -class AmountsSettlement(BaseModel): - amount: int - """Amount in the smallest unit of the applicable currency (e.g., cents)""" - - currency: Currency - """3-character alphabetic ISO 4217 currency""" - - -class Amounts(BaseModel): - """Structured amounts for this authorization. - - The `cardholder` and `merchant` amounts reflect the original network authorization values. For programs with hold adjustments enabled (e.g., automated fuel dispensers or tipping MCCs), the `hold` amount may exceed the `cardholder` and `merchant` amounts to account for anticipated final transaction amounts such as tips or fuel fill-ups - """ - - cardholder: AmountsCardholder - - hold: Optional[AmountsHold] = None - - merchant: AmountsMerchant - - settlement: Optional[AmountsSettlement] = None - - -class Avs(BaseModel): - address: str - """Cardholder address""" - - address_on_file_match: Literal["MATCH", "MATCH_ADDRESS_ONLY", "MATCH_ZIP_ONLY", "MISMATCH", "NOT_PRESENT"] - """ - Lithic's evaluation result comparing the transaction's address data with the - cardholder KYC data if it exists. In the event Lithic does not have any - Cardholder KYC data, or the transaction does not contain any address data, - NOT_PRESENT will be returned - """ - - zipcode: str - """Cardholder ZIP code""" - - -class Card(BaseModel): - """Card object in ASA""" - - token: str - """Globally unique identifier for the card.""" - - last_four: str - """Last four digits of the card number""" - - memo: str - """Customizable name to identify the card""" - - spend_limit: int - """Amount (in cents) to limit approved authorizations. - - Purchase requests above the spend limit will be declined (refunds and credits - will be approved). - - Note that while spend limits are enforced based on authorized and settled volume - on a card, they are not recommended to be used for balance or - reconciliation-level accuracy. Spend limits also cannot block force posted - charges (i.e., when a merchant sends a clearing message without a prior - authorization). - """ - - spend_limit_duration: Literal["ANNUALLY", "FOREVER", "MONTHLY", "TRANSACTION"] - """ - Note that to support recurring monthly payments, which can occur on different - day every month, the time window we consider for MONTHLY velocity starts 6 days - after the current calendar date one month prior. - """ - - state: Literal["CLOSED", "OPEN", "PAUSED", "PENDING_ACTIVATION", "PENDING_FULFILLMENT"] - - type: Literal["SINGLE_USE", "MERCHANT_LOCKED", "UNLOCKED", "PHYSICAL", "DIGITAL_WALLET", "VIRTUAL"] - - -class Merchant(merchant.Merchant): - """Merchant information including full location details.""" - - phone_number: Optional[str] = None - """Phone number of card acceptor.""" - - postal_code: Optional[str] = None - """Postal code of card acceptor.""" - - street_address: Optional[str] = None - """Street address of card acceptor.""" - - -class ServiceLocation(BaseModel): - """ - Where the cardholder received the service, when different from the card acceptor location. This is populated from network data elements such as Mastercard DE-122 SE1 SF9-14 and Visa F34 DS02. - """ - - city: Optional[str] = None - """City of service location.""" - - country: Optional[str] = None - """Country code of service location, ISO 3166-1 alpha-3.""" - - postal_code: Optional[str] = None - """Postal code of service location.""" - - state: Optional[str] = None - """State/province code of service location, ISO 3166-2.""" - - street_address: Optional[str] = None - """Street address of service location.""" - - -class FleetInfo(BaseModel): - """ - Optional Object containing information if the Card is a part of a Fleet managed program - """ - - fleet_prompt_code: Literal["NO_PROMPT", "VEHICLE_NUMBER", "DRIVER_NUMBER"] - """Code indicating what the driver was prompted to enter at time of purchase. - - This is configured at a program level and is a static configuration, and does - not change on a request to request basis - """ - - fleet_restriction_code: Literal["NO_RESTRICTIONS", "FUEL_ONLY"] - """Code indicating which restrictions, if any, there are on purchase. - - This is configured at a program level and is a static configuration, and does - not change on a request to request basis - """ - - driver_number: Optional[str] = None - """Number representing the driver""" - - vehicle_number: Optional[str] = None - """Number associated with the vehicle""" - - -class LatestChallenge(BaseModel): - """ - The latest Authorization Challenge that was issued to the cardholder for this merchant. - """ - - phone_number: str - """The phone number used for sending Authorization Challenge SMS.""" - - status: Literal["COMPLETED", "PENDING", "EXPIRED", "ERROR"] - """The status of the Authorization Challenge - - - `COMPLETED` - Challenge was successfully completed by the cardholder - - `PENDING` - Challenge is still open - - `EXPIRED` - Challenge has expired without being completed - - `ERROR` - There was an error processing the challenge - """ - - completed_at: Optional[datetime] = None - """The date and time when the Authorization Challenge was completed in UTC. - - Present only if the status is `COMPLETED`. - """ - - -class NetworkSpecificDataMastercardOnBehalfServiceResult(BaseModel): - result_1: str - """Indicates the results of the service processing.""" - - result_2: str - """Identifies the results of the service processing.""" - - service: str - """Indicates the service performed on the transaction.""" - - -class NetworkSpecificDataMastercard(BaseModel): - ecommerce_security_level_indicator: Optional[str] = None - """Indicates the electronic commerce security level and UCAF collection.""" - - on_behalf_service_result: Optional[List[NetworkSpecificDataMastercardOnBehalfServiceResult]] = None - """The On-behalf Service performed on the transaction and the results. - - Contains all applicable, on-behalf service results that were performed on a - given transaction. - """ - - transaction_type_identifier: Optional[str] = None - """Indicates the type of additional transaction purpose.""" - - -class NetworkSpecificDataVisa(BaseModel): - business_application_identifier: Optional[str] = None - """ - Identifies the purpose or category of a transaction, used to classify and - process transactions according to Visa’s rules. - """ - - -class NetworkSpecificData(BaseModel): - """ - Contains raw data provided by the card network, including attributes that provide further context about the authorization. If populated by the network, data is organized by Lithic and passed through without further modification. Please consult the official network documentation for more details about these values and how to use them. This object is only available to certain programs- contact your Customer Success Manager to discuss enabling access. - """ - - mastercard: Optional[NetworkSpecificDataMastercard] = None - - visa: Optional[NetworkSpecificDataVisa] = None - - -class PosEntryMode(BaseModel): - """POS > Entry Mode object in ASA""" - - card: Optional[Literal["PRESENT", "NOT_PRESENT", "UNKNOWN"]] = None - """Card Presence Indicator""" - - cardholder: Optional[ - Literal[ - "DEFERRED_BILLING", - "ELECTRONIC_ORDER", - "INSTALLMENT", - "MAIL_ORDER", - "NOT_PRESENT", - "PRESENT", - "REOCCURRING", - "TELEPHONE_ORDER", - "UNKNOWN", - ] - ] = None - """Cardholder Presence Indicator""" - - pan: Optional[ - Literal[ - "AUTO_ENTRY", - "BAR_CODE", - "CONTACTLESS", - "ECOMMERCE", - "ERROR_KEYED", - "ERROR_MAGNETIC_STRIPE", - "ICC", - "KEY_ENTERED", - "MAGNETIC_STRIPE", - "MANUAL", - "OCR", - "SECURE_CARDLESS", - "UNSPECIFIED", - "UNKNOWN", - "CREDENTIAL_ON_FILE", - ] - ] = None - """Method of entry for the PAN""" - - pin_entered: Optional[bool] = None - """Indicates whether the cardholder entered the PIN. True if the PIN was entered.""" - - -class PosTerminal(BaseModel): - attended: bool - """True if a clerk is present at the sale.""" - - card_retention_capable: bool - """True if the terminal is capable of retaining the card.""" - - on_premise: bool - """True if the sale was made at the place of business (vs. mobile).""" - - operator: Literal["ADMINISTRATIVE", "CARDHOLDER", "CARD_ACCEPTOR", "UNKNOWN"] - """The person that is designated to swipe the card""" - - partial_approval_capable: bool - """True if the terminal is capable of partial approval. - - Partial approval is when part of a transaction is approved and another payment - must be used for the remainder. Example scenario: A $40 transaction is attempted - on a prepaid card with a $25 balance. If partial approval is enabled, $25 can be - authorized, at which point the POS will prompt the user for an additional - payment of $15. - """ - - pin_capability: Literal["CAPABLE", "INOPERATIVE", "NOT_CAPABLE", "UNSPECIFIED"] - """Status of whether the POS is able to accept PINs""" - - type: Literal[ - "ADMINISTRATIVE", - "ATM", - "AUTHORIZATION", - "COUPON_MACHINE", - "DIAL_TERMINAL", - "ECOMMERCE", - "ECR", - "FUEL_MACHINE", - "HOME_TERMINAL", - "MICR", - "OFF_PREMISE", - "PAYMENT", - "PDA", - "PHONE", - "POINT", - "POS_TERMINAL", - "PUBLIC_UTILITY", - "SELF_SERVICE", - "TELEVISION", - "TELLER", - "TRAVELERS_CHECK_MACHINE", - "VENDING", - "VOICE", - "UNKNOWN", - ] - """POS Type""" - - acceptor_terminal_id: Optional[str] = None - """ - Uniquely identifies a terminal at the card acceptor location of acquiring - institutions or merchant POS Systems. Left justified with trailing spaces. - """ - - -class Pos(BaseModel): - entry_mode: Optional[PosEntryMode] = None - """POS > Entry Mode object in ASA""" - - terminal: Optional[PosTerminal] = None - - -class CardAuthorizationApprovalRequestWebhookEvent(BaseModel): - token: str - """The provisional transaction group uuid associated with the authorization""" - - acquirer_fee: int - """Fee (in cents) assessed by the merchant and paid for by the cardholder. - - Will be zero if no fee is assessed. Rebates may be transmitted as a negative - value to indicate credited fees. - """ - - amount: int - """Deprecated, use `amounts`. - - Authorization amount of the transaction (in cents), including any acquirer fees. - The contents of this field are identical to `authorization_amount`. - """ - - amounts: Amounts - """Structured amounts for this authorization. - - The `cardholder` and `merchant` amounts reflect the original network - authorization values. For programs with hold adjustments enabled (e.g., - automated fuel dispensers or tipping MCCs), the `hold` amount may exceed the - `cardholder` and `merchant` amounts to account for anticipated final transaction - amounts such as tips or fuel fill-ups - """ - - authorization_amount: int - """Deprecated, use `amounts`. - - The base transaction amount (in cents) plus the acquirer fee field. This is the - amount the issuer should authorize against unless the issuer is paying the - acquirer fee on behalf of the cardholder. - """ - - avs: Avs - - card: Card - """Card object in ASA""" - - cardholder_currency: str - """Deprecated, use `amounts`. - - 3-character alphabetic ISO 4217 code for cardholder's billing currency. - """ - - cash_amount: int - """ - The portion of the transaction requested as cash back by the cardholder, and - does not include any acquirer fees. The amount field includes the purchase - amount, the requested cash back amount, and any acquirer fees. - - If no cash back was requested, the value of this field will be 0, and the field - will always be present. - """ - - created: datetime - """Date and time when the transaction first occurred in UTC.""" +class CardAuthorizationApprovalRequestWebhookEvent(CardAuthorization): + """The Auth Stream Access request payload that was sent to the ASA responder.""" event_type: Literal["card_authorization.approval_request"] - - merchant: Merchant - """Merchant information including full location details.""" - - merchant_amount: int - """Deprecated, use `amounts`. - - The amount that the merchant will receive, denominated in `merchant_currency` - and in the smallest currency unit. Note the amount includes `acquirer_fee`, - similar to `authorization_amount`. It will be different from - `authorization_amount` if the merchant is taking payment in a different - currency. - """ - - merchant_currency: str - """3-character alphabetic ISO 4217 code for the local currency of the transaction.""" - - service_location: Optional[ServiceLocation] = None - """ - Where the cardholder received the service, when different from the card acceptor - location. This is populated from network data elements such as Mastercard DE-122 - SE1 SF9-14 and Visa F34 DS02. - """ - - settled_amount: int - """Deprecated, use `amounts`. - - Amount (in cents) of the transaction that has been settled, including any - acquirer fees. - """ - - status: Literal[ - "AUTHORIZATION", - "CREDIT_AUTHORIZATION", - "FINANCIAL_AUTHORIZATION", - "FINANCIAL_CREDIT_AUTHORIZATION", - "BALANCE_INQUIRY", - ] - """The type of authorization request that this request is for. - - Note that `CREDIT_AUTHORIZATION` and `FINANCIAL_CREDIT_AUTHORIZATION` is only - available to users with credit decisioning via ASA enabled. - """ - - transaction_initiator: Literal["CARDHOLDER", "MERCHANT", "UNKNOWN"] - """The entity that initiated the transaction.""" - - account_type: Optional[Literal["CHECKING", "SAVINGS"]] = None - - cardholder_authentication: Optional[CardholderAuthentication] = None - - cashback: Optional[int] = None - """Deprecated, use `cash_amount`.""" - - conversion_rate: Optional[float] = None - """Deprecated, use `amounts`. - - If the transaction was requested in a currency other than the settlement - currency, this field will be populated to indicate the rate used to translate - the merchant_amount to the amount (i.e., `merchant_amount` x `conversion_rate` = - `amount`). Note that the `merchant_amount` is in the local currency and the - amount is in the settlement currency. - """ - - event_token: Optional[str] = None - """The event token associated with the authorization. - - This field is only set for programs enrolled into the beta. - """ - - fleet_info: Optional[FleetInfo] = None - """ - Optional Object containing information if the Card is a part of a Fleet managed - program - """ - - latest_challenge: Optional[LatestChallenge] = None - """ - The latest Authorization Challenge that was issued to the cardholder for this - merchant. - """ - - network: Optional[Literal["AMEX", "INTERLINK", "MAESTRO", "MASTERCARD", "UNKNOWN", "VISA"]] = None - """Card network of the authorization.""" - - network_risk_score: Optional[int] = None - """ - Network-provided score assessing risk level associated with a given - authorization. Scores are on a range of 0-999, with 0 representing the lowest - risk and 999 representing the highest risk. For Visa transactions, where the raw - score has a range of 0-99, Lithic will normalize the score by multiplying the - raw score by 10x. - """ - - network_specific_data: Optional[NetworkSpecificData] = None - """ - Contains raw data provided by the card network, including attributes that - provide further context about the authorization. If populated by the network, - data is organized by Lithic and passed through without further modification. - Please consult the official network documentation for more details about these - values and how to use them. This object is only available to certain programs- - contact your Customer Success Manager to discuss enabling access. - """ - - pos: Optional[Pos] = None - - token_info: Optional[TokenInfo] = None - - ttl: Optional[datetime] = None - """Deprecated: approximate time-to-live for the authorization.""" diff --git a/src/lithic/types/card_authorization_challenge_response_params.py b/src/lithic/types/card_authorization_challenge_response_params.py new file mode 100644 index 00000000..5ea230b5 --- /dev/null +++ b/src/lithic/types/card_authorization_challenge_response_params.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, Required, TypedDict + +__all__ = ["CardAuthorizationChallengeResponseParams"] + + +class CardAuthorizationChallengeResponseParams(TypedDict, total=False): + response: Required[Literal["APPROVE", "DECLINE"]] + """Whether the cardholder has approved or declined the issued challenge""" diff --git a/src/lithic/types/card_authorization_challenge_response_webhook_event.py b/src/lithic/types/card_authorization_challenge_response_webhook_event.py index 97ed32a5..f5e87eb8 100644 --- a/src/lithic/types/card_authorization_challenge_response_webhook_event.py +++ b/src/lithic/types/card_authorization_challenge_response_webhook_event.py @@ -13,7 +13,7 @@ class CardAuthorizationChallengeResponseWebhookEvent(BaseModel): card_token: Optional[str] = None """The token of the card associated with the challenge""" - challenge_method: Literal["SMS"] + challenge_method: Literal["SMS", "OUT_OF_BAND"] """The method used to deliver the challenge to the cardholder""" completed: Optional[datetime] = None diff --git a/src/lithic/types/card_authorization_challenge_webhook_event.py b/src/lithic/types/card_authorization_challenge_webhook_event.py new file mode 100644 index 00000000..50a358bd --- /dev/null +++ b/src/lithic/types/card_authorization_challenge_webhook_event.py @@ -0,0 +1,36 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from datetime import datetime +from typing_extensions import Literal + +from .._models import BaseModel +from .card_authorization import CardAuthorization + +__all__ = ["CardAuthorizationChallengeWebhookEvent", "Challenge"] + + +class Challenge(BaseModel): + """Details of the Authorization Challenge issued during card authorization""" + + event_token: str + """Globally unique identifier for the event that triggered the challenge. + + Use this token when calling the challenge response endpoint + """ + + expiry_time: datetime + """ISO-8601 time at which the challenge expires""" + + start_time: datetime + """ISO-8601 time at which the challenge was issued""" + + +class CardAuthorizationChallengeWebhookEvent(BaseModel): + authorization: CardAuthorization + """The authorization that triggered the challenge""" + + challenge: Challenge + """Details of the Authorization Challenge issued during card authorization""" + + event_type: Literal["card_authorization.challenge"] + """The type of event that occurred.""" diff --git a/src/lithic/types/event.py b/src/lithic/types/event.py index 97d8ce22..9866fb12 100644 --- a/src/lithic/types/event.py +++ b/src/lithic/types/event.py @@ -30,6 +30,7 @@ class Event(BaseModel): "balance.updated", "book_transfer_transaction.created", "book_transfer_transaction.updated", + "card_authorization.challenge", "card_authorization.challenge_response", "card_transaction.enhanced_data.created", "card_transaction.enhanced_data.updated", @@ -90,8 +91,12 @@ class Event(BaseModel): created. - book_transfer_transaction.updated: Occurs when a book transfer transaction is updated. - - card_authorization.challenge_response: Occurs when a cardholder responds to an - SMS challenge during card authorization. + - card_authorization.challenge: Occurs when an Out of Band challenge is issued + during card authorization. The card program should issue its own challenge to + the cardholder and then respond via + [/v1/card_authorizations/{event_token}/challenge_response](https://docs.lithic.com/reference/respondtoauthorizationchallenge). + - card_authorization.challenge_response: Occurs when a cardholder responds to a + challenge during card authorization. - card_transaction.enhanced_data.created: Occurs when L2/L3 enhanced commercial data is processed for a transaction event. - card_transaction.enhanced_data.updated: Occurs when L2/L3 enhanced commercial diff --git a/src/lithic/types/event_list_params.py b/src/lithic/types/event_list_params.py index ec270300..b0c037d4 100644 --- a/src/lithic/types/event_list_params.py +++ b/src/lithic/types/event_list_params.py @@ -40,6 +40,7 @@ class EventListParams(TypedDict, total=False): "balance.updated", "book_transfer_transaction.created", "book_transfer_transaction.updated", + "card_authorization.challenge", "card_authorization.challenge_response", "card_transaction.enhanced_data.created", "card_transaction.enhanced_data.updated", diff --git a/src/lithic/types/event_subscription.py b/src/lithic/types/event_subscription.py index 4f4dd071..2b49b308 100644 --- a/src/lithic/types/event_subscription.py +++ b/src/lithic/types/event_subscription.py @@ -33,6 +33,7 @@ class EventSubscription(BaseModel): "balance.updated", "book_transfer_transaction.created", "book_transfer_transaction.updated", + "card_authorization.challenge", "card_authorization.challenge_response", "card_transaction.enhanced_data.created", "card_transaction.enhanced_data.updated", diff --git a/src/lithic/types/events/subscription_create_params.py b/src/lithic/types/events/subscription_create_params.py index fbdeea9c..4c3f5282 100644 --- a/src/lithic/types/events/subscription_create_params.py +++ b/src/lithic/types/events/subscription_create_params.py @@ -28,6 +28,7 @@ class SubscriptionCreateParams(TypedDict, total=False): "balance.updated", "book_transfer_transaction.created", "book_transfer_transaction.updated", + "card_authorization.challenge", "card_authorization.challenge_response", "card_transaction.enhanced_data.created", "card_transaction.enhanced_data.updated", diff --git a/src/lithic/types/events/subscription_send_simulated_example_params.py b/src/lithic/types/events/subscription_send_simulated_example_params.py index 08489d80..348c8ef7 100644 --- a/src/lithic/types/events/subscription_send_simulated_example_params.py +++ b/src/lithic/types/events/subscription_send_simulated_example_params.py @@ -17,6 +17,7 @@ class SubscriptionSendSimulatedExampleParams(TypedDict, total=False): "balance.updated", "book_transfer_transaction.created", "book_transfer_transaction.updated", + "card_authorization.challenge", "card_authorization.challenge_response", "card_transaction.enhanced_data.created", "card_transaction.enhanced_data.updated", diff --git a/src/lithic/types/events/subscription_update_params.py b/src/lithic/types/events/subscription_update_params.py index 3bcdd6c7..b30bdde0 100644 --- a/src/lithic/types/events/subscription_update_params.py +++ b/src/lithic/types/events/subscription_update_params.py @@ -28,6 +28,7 @@ class SubscriptionUpdateParams(TypedDict, total=False): "balance.updated", "book_transfer_transaction.created", "book_transfer_transaction.updated", + "card_authorization.challenge", "card_authorization.challenge_response", "card_transaction.enhanced_data.created", "card_transaction.enhanced_data.updated", diff --git a/src/lithic/types/parsed_webhook_event.py b/src/lithic/types/parsed_webhook_event.py index d355b7d2..c6116e6c 100644 --- a/src/lithic/types/parsed_webhook_event.py +++ b/src/lithic/types/parsed_webhook_event.py @@ -34,6 +34,7 @@ from .dispute_transaction_updated_webhook_event import DisputeTransactionUpdatedWebhookEvent from .payment_transaction_created_webhook_event import PaymentTransactionCreatedWebhookEvent from .payment_transaction_updated_webhook_event import PaymentTransactionUpdatedWebhookEvent +from .card_authorization_challenge_webhook_event import CardAuthorizationChallengeWebhookEvent from .internal_transaction_created_webhook_event import InternalTransactionCreatedWebhookEvent from .internal_transaction_updated_webhook_event import InternalTransactionUpdatedWebhookEvent from .management_operation_created_webhook_event import ManagementOperationCreatedWebhookEvent @@ -432,6 +433,7 @@ class LegacyPayload(BaseModel): AccountHolderVerificationWebhookEvent, AccountHolderDocumentUpdatedWebhookEvent, CardAuthorizationApprovalRequestWebhookEvent, + CardAuthorizationChallengeWebhookEvent, CardAuthorizationChallengeResponseWebhookEvent, AuthRulesBacktestReportCreatedWebhookEvent, BalanceUpdatedWebhookEvent, diff --git a/tests/api_resources/test_card_authorizations.py b/tests/api_resources/test_card_authorizations.py new file mode 100644 index 00000000..87f75e0f --- /dev/null +++ b/tests/api_resources/test_card_authorizations.py @@ -0,0 +1,106 @@ +# 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 + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestCardAuthorizations: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_challenge_response(self, client: Lithic) -> None: + card_authorization = client.card_authorizations.challenge_response( + event_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + response="APPROVE", + ) + assert card_authorization is None + + @parametrize + def test_raw_response_challenge_response(self, client: Lithic) -> None: + response = client.card_authorizations.with_raw_response.challenge_response( + event_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + response="APPROVE", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + card_authorization = response.parse() + assert card_authorization is None + + @parametrize + def test_streaming_response_challenge_response(self, client: Lithic) -> None: + with client.card_authorizations.with_streaming_response.challenge_response( + event_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + response="APPROVE", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + card_authorization = response.parse() + assert card_authorization is None + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_challenge_response(self, client: Lithic) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `event_token` but received ''"): + client.card_authorizations.with_raw_response.challenge_response( + event_token="", + response="APPROVE", + ) + + +class TestAsyncCardAuthorizations: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @parametrize + async def test_method_challenge_response(self, async_client: AsyncLithic) -> None: + card_authorization = await async_client.card_authorizations.challenge_response( + event_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + response="APPROVE", + ) + assert card_authorization is None + + @parametrize + async def test_raw_response_challenge_response(self, async_client: AsyncLithic) -> None: + response = await async_client.card_authorizations.with_raw_response.challenge_response( + event_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + response="APPROVE", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + card_authorization = response.parse() + assert card_authorization is None + + @parametrize + async def test_streaming_response_challenge_response(self, async_client: AsyncLithic) -> None: + async with async_client.card_authorizations.with_streaming_response.challenge_response( + event_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + response="APPROVE", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + card_authorization = await response.parse() + assert card_authorization is None + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_challenge_response(self, async_client: AsyncLithic) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `event_token` but received ''"): + await async_client.card_authorizations.with_raw_response.challenge_response( + event_token="", + response="APPROVE", + )