From 81c2860a37078364b3f4c1876f407b60bdb88bec Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 26 Jun 2025 14:03:54 +0000
Subject: [PATCH 1/7] feat(client): adds support for on-demand Auth Rule
Performance Reports
---
.stats.yml | 8 +-
api.md | 18 +
src/lithic/_client.py | 38 ++
src/lithic/resources/__init__.py | 14 +
.../resources/auth_rules/v2/backtests.py | 30 +-
src/lithic/resources/auth_rules/v2/v2.py | 197 +++++++++-
src/lithic/resources/cards/cards.py | 64 ++--
.../external_bank_accounts.py | 152 +++++++-
src/lithic/resources/fraud/__init__.py | 33 ++
src/lithic/resources/fraud/fraud.py | 102 +++++
src/lithic/resources/fraud/transactions.py | 348 ++++++++++++++++++
.../resources/three_ds/authentication.py | 20 +-
src/lithic/resources/three_ds/decisioning.py | 36 +-
src/lithic/types/auth_rules/__init__.py | 3 +
src/lithic/types/auth_rules/rule_stats.py | 56 +++
.../types/auth_rules/v2/backtest_results.py | 112 +-----
.../auth_rules/v2_retrieve_report_params.py | 19 +
.../auth_rules/v2_retrieve_report_response.py | 34 ++
.../types/card_convert_physical_params.py | 8 +-
src/lithic/types/card_create_params.py | 8 +-
src/lithic/types/card_reissue_params.py | 8 +-
src/lithic/types/card_renew_params.py | 8 +-
.../external_bank_account_create_params.py | 59 +++
.../statements/statement_line_items.py | 1 +
src/lithic/types/financial_transaction.py | 1 +
src/lithic/types/fraud/__init__.py | 7 +
.../types/fraud/transaction_report_params.py | 57 +++
.../fraud/transaction_report_response.py | 73 ++++
.../fraud/transaction_retrieve_response.py | 73 ++++
src/lithic/types/payment.py | 2 +
src/lithic/types/payment_create_params.py | 3 +
.../authentication_retrieve_response.py | 128 ++++---
.../authentication_simulate_params.py | 2 +
.../authentication_simulate_response.py | 5 +-
.../decisioning_challenge_response_params.py | 10 +-
tests/api_resources/auth_rules/test_v2.py | 152 ++++++--
tests/api_resources/fraud/__init__.py | 1 +
.../api_resources/fraud/test_transactions.py | 204 ++++++++++
tests/api_resources/test_account_holders.py | 16 +-
tests/api_resources/test_cards.py | 20 +-
.../test_external_bank_accounts.py | 160 ++++++++
tests/api_resources/test_payments.py | 10 +-
tests/api_resources/test_tokenizations.py | 4 +-
.../three_ds/test_authentication.py | 32 +-
44 files changed, 2015 insertions(+), 321 deletions(-)
create mode 100644 src/lithic/resources/fraud/__init__.py
create mode 100644 src/lithic/resources/fraud/fraud.py
create mode 100644 src/lithic/resources/fraud/transactions.py
create mode 100644 src/lithic/types/auth_rules/rule_stats.py
create mode 100644 src/lithic/types/auth_rules/v2_retrieve_report_params.py
create mode 100644 src/lithic/types/auth_rules/v2_retrieve_report_response.py
create mode 100644 src/lithic/types/fraud/__init__.py
create mode 100644 src/lithic/types/fraud/transaction_report_params.py
create mode 100644 src/lithic/types/fraud/transaction_report_response.py
create mode 100644 src/lithic/types/fraud/transaction_retrieve_response.py
create mode 100644 tests/api_resources/fraud/__init__.py
create mode 100644 tests/api_resources/fraud/test_transactions.py
diff --git a/.stats.yml b/.stats.yml
index 2d0fb2d5..93eec907 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 161
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic%2Flithic-67859c948e3b903a317f4bd14135c7ee44254d2760068117bab34b7c4058be71.yml
-openapi_spec_hash: 23a4716c6168e96f040ac8575582d075
-config_hash: 227ad54062905d4ae964b24cef0505b0
+configured_endpoints: 164
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic%2Flithic-a0d3bcd9c54616729a7e43847e3134205e0695d78f357cc7a25c2775b588dbbd.yml
+openapi_spec_hash: 36c423c286ca426f7510b27fadbdd66f
+config_hash: 56632a1c934324aa46c1e5c610c2de85
diff --git a/api.md b/api.md
index 323fabf8..5a10a649 100644
--- a/api.md
+++ b/api.md
@@ -83,6 +83,7 @@ from lithic.types.auth_rules import (
AuthRuleCondition,
ConditionalAttribute,
ConditionalBlockParameters,
+ RuleStats,
VelocityLimitParams,
VelocityLimitParamsPeriodWindow,
V2CreateResponse,
@@ -93,6 +94,7 @@ from lithic.types.auth_rules import (
V2DraftResponse,
V2PromoteResponse,
V2ReportResponse,
+ V2RetrieveReportResponse,
)
```
@@ -107,6 +109,7 @@ Methods:
- client.auth_rules.v2.draft(auth_rule_token, \*\*params) -> V2DraftResponse
- client.auth_rules.v2.promote(auth_rule_token) -> V2PromoteResponse
- client.auth_rules.v2.report(auth_rule_token) -> V2ReportResponse
+- client.auth_rules.v2.retrieve_report(auth_rule_token, \*\*params) -> V2RetrieveReportResponse
### Backtests
@@ -734,3 +737,18 @@ Methods:
- client.funding_events.retrieve(funding_event_token) -> FundingEventRetrieveResponse
- client.funding_events.list(\*\*params) -> SyncCursorPage[FundingEventListResponse]
- client.funding_events.retrieve_details(funding_event_token) -> FundingEventRetrieveDetailsResponse
+
+# Fraud
+
+## Transactions
+
+Types:
+
+```python
+from lithic.types.fraud import TransactionRetrieveResponse, TransactionReportResponse
+```
+
+Methods:
+
+- client.fraud.transactions.retrieve(transaction_token) -> TransactionRetrieveResponse
+- client.fraud.transactions.report(transaction_token, \*\*params) -> TransactionReportResponse
diff --git a/src/lithic/_client.py b/src/lithic/_client.py
index 1e97d5c2..04f3d4c0 100644
--- a/src/lithic/_client.py
+++ b/src/lithic/_client.py
@@ -39,6 +39,7 @@
if TYPE_CHECKING:
from .resources import (
cards,
+ fraud,
events,
reports,
accounts,
@@ -70,6 +71,7 @@
from .resources.disputes import Disputes, AsyncDisputes
from .resources.payments import Payments, AsyncPayments
from .resources.cards.cards import Cards, AsyncCards
+ from .resources.fraud.fraud import Fraud, AsyncFraud
from .resources.card_programs import CardPrograms, AsyncCardPrograms
from .resources.events.events import Events, AsyncEvents
from .resources.tokenizations import Tokenizations, AsyncTokenizations
@@ -352,6 +354,12 @@ def webhooks(self) -> webhooks.Webhooks:
return Webhooks(self)
+ @cached_property
+ def fraud(self) -> Fraud:
+ from .resources.fraud import Fraud
+
+ return Fraud(self)
+
@cached_property
def with_raw_response(self) -> LithicWithRawResponse:
return LithicWithRawResponse(self)
@@ -726,6 +734,12 @@ def funding_events(self) -> AsyncFundingEvents:
return AsyncFundingEvents(self)
+ @cached_property
+ def fraud(self) -> AsyncFraud:
+ from .resources.fraud import AsyncFraud
+
+ return AsyncFraud(self)
+
@cached_property
def webhooks(self) -> webhooks.AsyncWebhooks:
from .resources.webhooks import AsyncWebhooks
@@ -1029,6 +1043,12 @@ def funding_events(self) -> funding_events.FundingEventsWithRawResponse:
return FundingEventsWithRawResponse(self._client.funding_events)
+ @cached_property
+ def fraud(self) -> fraud.FraudWithRawResponse:
+ from .resources.fraud import FraudWithRawResponse
+
+ return FraudWithRawResponse(self._client.fraud)
+
class AsyncLithicWithRawResponse:
_client: AsyncLithic
@@ -1190,6 +1210,12 @@ def funding_events(self) -> funding_events.AsyncFundingEventsWithRawResponse:
return AsyncFundingEventsWithRawResponse(self._client.funding_events)
+ @cached_property
+ def fraud(self) -> fraud.AsyncFraudWithRawResponse:
+ from .resources.fraud import AsyncFraudWithRawResponse
+
+ return AsyncFraudWithRawResponse(self._client.fraud)
+
class LithicWithStreamedResponse:
_client: Lithic
@@ -1351,6 +1377,12 @@ def funding_events(self) -> funding_events.FundingEventsWithStreamingResponse:
return FundingEventsWithStreamingResponse(self._client.funding_events)
+ @cached_property
+ def fraud(self) -> fraud.FraudWithStreamingResponse:
+ from .resources.fraud import FraudWithStreamingResponse
+
+ return FraudWithStreamingResponse(self._client.fraud)
+
class AsyncLithicWithStreamedResponse:
_client: AsyncLithic
@@ -1512,6 +1544,12 @@ def funding_events(self) -> funding_events.AsyncFundingEventsWithStreamingRespon
return AsyncFundingEventsWithStreamingResponse(self._client.funding_events)
+ @cached_property
+ def fraud(self) -> fraud.AsyncFraudWithStreamingResponse:
+ from .resources.fraud import AsyncFraudWithStreamingResponse
+
+ return AsyncFraudWithStreamingResponse(self._client.fraud)
+
Client = Lithic
diff --git a/src/lithic/resources/__init__.py b/src/lithic/resources/__init__.py
index 6186ee94..4aeeec9b 100644
--- a/src/lithic/resources/__init__.py
+++ b/src/lithic/resources/__init__.py
@@ -8,6 +8,14 @@
CardsWithStreamingResponse,
AsyncCardsWithStreamingResponse,
)
+from .fraud import (
+ Fraud,
+ AsyncFraud,
+ FraudWithRawResponse,
+ AsyncFraudWithRawResponse,
+ FraudWithStreamingResponse,
+ AsyncFraudWithStreamingResponse,
+)
from .events import (
Events,
AsyncEvents,
@@ -355,4 +363,10 @@
"AsyncFundingEventsWithRawResponse",
"FundingEventsWithStreamingResponse",
"AsyncFundingEventsWithStreamingResponse",
+ "Fraud",
+ "AsyncFraud",
+ "FraudWithRawResponse",
+ "AsyncFraudWithRawResponse",
+ "FraudWithStreamingResponse",
+ "AsyncFraudWithStreamingResponse",
]
diff --git a/src/lithic/resources/auth_rules/v2/backtests.py b/src/lithic/resources/auth_rules/v2/backtests.py
index ae5e9db0..760c4a37 100644
--- a/src/lithic/resources/auth_rules/v2/backtests.py
+++ b/src/lithic/resources/auth_rules/v2/backtests.py
@@ -72,13 +72,14 @@ def create(
`/v2/auth_rules/{auth_rule_token}/backtests/{auth_rule_backtest_token}`
endpoint.
- Lithic currently supports backtesting for `CONDITIONAL_BLOCK` rules. Backtesting
- for `VELOCITY_LIMIT` rules is generally not supported. In specific cases (i.e.
- where Lithic has pre-calculated the requested velocity metrics for historical
- transactions), a backtest may be feasible. However, such cases are uncommon and
- customers should not anticipate support for velocity backtests under most
- configurations. If a historical transaction does not feature the required inputs
- to evaluate the rule, then it will not be included in the final backtest report.
+ Lithic currently supports backtesting for `CONDITIONAL_BLOCK` /
+ `CONDITIONAL_3DS_ACTION` rules. Backtesting for `VELOCITY_LIMIT` rules is
+ generally not supported. In specific cases (i.e. where Lithic has pre-calculated
+ the requested velocity metrics for historical transactions), a backtest may be
+ feasible. However, such cases are uncommon and customers should not anticipate
+ support for velocity backtests under most configurations. If a historical
+ transaction does not feature the required inputs to evaluate the rule, then it
+ will not be included in the final backtest report.
Args:
end: The end time of the backtest.
@@ -217,13 +218,14 @@ async def create(
`/v2/auth_rules/{auth_rule_token}/backtests/{auth_rule_backtest_token}`
endpoint.
- Lithic currently supports backtesting for `CONDITIONAL_BLOCK` rules. Backtesting
- for `VELOCITY_LIMIT` rules is generally not supported. In specific cases (i.e.
- where Lithic has pre-calculated the requested velocity metrics for historical
- transactions), a backtest may be feasible. However, such cases are uncommon and
- customers should not anticipate support for velocity backtests under most
- configurations. If a historical transaction does not feature the required inputs
- to evaluate the rule, then it will not be included in the final backtest report.
+ Lithic currently supports backtesting for `CONDITIONAL_BLOCK` /
+ `CONDITIONAL_3DS_ACTION` rules. Backtesting for `VELOCITY_LIMIT` rules is
+ generally not supported. In specific cases (i.e. where Lithic has pre-calculated
+ the requested velocity metrics for historical transactions), a backtest may be
+ feasible. However, such cases are uncommon and customers should not anticipate
+ support for velocity backtests under most configurations. If a historical
+ transaction does not feature the required inputs to evaluate the rule, then it
+ will not be included in the final backtest report.
Args:
end: The end time of the backtest.
diff --git a/src/lithic/resources/auth_rules/v2/v2.py b/src/lithic/resources/auth_rules/v2/v2.py
index fd793e41..3d3f89cc 100644
--- a/src/lithic/resources/auth_rules/v2/v2.py
+++ b/src/lithic/resources/auth_rules/v2/v2.py
@@ -3,7 +3,8 @@
from __future__ import annotations
import typing_extensions
-from typing import List, Optional
+from typing import List, Union, Optional
+from datetime import date
from typing_extensions import Literal, overload
import httpx
@@ -24,7 +25,14 @@
from ...._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper
from ....pagination import SyncCursorPage, AsyncCursorPage
from ...._base_client import AsyncPaginator, make_request_options
-from ....types.auth_rules import v2_list_params, v2_apply_params, v2_draft_params, v2_create_params, v2_update_params
+from ....types.auth_rules import (
+ v2_list_params,
+ v2_apply_params,
+ v2_draft_params,
+ v2_create_params,
+ v2_update_params,
+ v2_retrieve_report_params,
+)
from ....types.auth_rules.v2_list_response import V2ListResponse
from ....types.auth_rules.v2_apply_response import V2ApplyResponse
from ....types.auth_rules.v2_draft_response import V2DraftResponse
@@ -33,6 +41,7 @@
from ....types.auth_rules.v2_update_response import V2UpdateResponse
from ....types.auth_rules.v2_promote_response import V2PromoteResponse
from ....types.auth_rules.v2_retrieve_response import V2RetrieveResponse
+from ....types.auth_rules.v2_retrieve_report_response import V2RetrieveReportResponse
__all__ = ["V2", "AsyncV2"]
@@ -752,6 +761,7 @@ def promote(
cast_to=V2PromoteResponse,
)
+ @typing_extensions.deprecated("deprecated")
def report(
self,
auth_rule_token: str,
@@ -763,11 +773,13 @@ def report(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
) -> V2ReportResponse:
- """
- Requests a performance report of an Auth rule to be asynchronously generated.
- Reports can only be run on rules in draft or active mode and will included
- approved and declined statistics as well as examples. The generated report will
- be delivered asynchronously through a webhook with `event_type` =
+ """This endpoint is deprecated and will be removed in the future.
+
+ Requests a
+ performance report of an Auth rule to be asynchronously generated. Reports can
+ only be run on rules in draft or active mode and will included approved and
+ declined statistics as well as examples. The generated report will be delivered
+ asynchronously through a webhook with `event_type` =
`auth_rules.performance_report.created`. See the docs on setting up
[webhook subscriptions](https://docs.lithic.com/docs/events-api).
@@ -834,6 +846,67 @@ def report(
cast_to=V2ReportResponse,
)
+ def retrieve_report(
+ self,
+ auth_rule_token: str,
+ *,
+ begin: Union[str, date],
+ end: Union[str, date],
+ # 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,
+ ) -> V2RetrieveReportResponse:
+ """
+ Retrieves a performance report for an Auth rule containing daily statistics and
+ evaluation outcomes.
+
+ **Time Range Limitations:**
+
+ - Reports are supported for the past 3 months only
+ - Maximum interval length is 1 month
+ - Report data is available only through the previous day in UTC (current day
+ data is not available)
+
+ The report provides daily statistics for both current and draft versions of the
+ Auth rule, including approval, decline, and challenge counts along with sample
+ events.
+
+ Args:
+ begin: Start date for the report
+
+ end: End date for the report
+
+ 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 auth_rule_token:
+ raise ValueError(f"Expected a non-empty value for `auth_rule_token` but received {auth_rule_token!r}")
+ return self._get(
+ f"/v2/auth_rules/{auth_rule_token}/report",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "begin": begin,
+ "end": end,
+ },
+ v2_retrieve_report_params.V2RetrieveReportParams,
+ ),
+ ),
+ cast_to=V2RetrieveReportResponse,
+ )
+
class AsyncV2(AsyncAPIResource):
@cached_property
@@ -1550,6 +1623,7 @@ async def promote(
cast_to=V2PromoteResponse,
)
+ @typing_extensions.deprecated("deprecated")
async def report(
self,
auth_rule_token: str,
@@ -1561,11 +1635,13 @@ async def report(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
) -> V2ReportResponse:
- """
- Requests a performance report of an Auth rule to be asynchronously generated.
- Reports can only be run on rules in draft or active mode and will included
- approved and declined statistics as well as examples. The generated report will
- be delivered asynchronously through a webhook with `event_type` =
+ """This endpoint is deprecated and will be removed in the future.
+
+ Requests a
+ performance report of an Auth rule to be asynchronously generated. Reports can
+ only be run on rules in draft or active mode and will included approved and
+ declined statistics as well as examples. The generated report will be delivered
+ asynchronously through a webhook with `event_type` =
`auth_rules.performance_report.created`. See the docs on setting up
[webhook subscriptions](https://docs.lithic.com/docs/events-api).
@@ -1632,6 +1708,67 @@ async def report(
cast_to=V2ReportResponse,
)
+ async def retrieve_report(
+ self,
+ auth_rule_token: str,
+ *,
+ begin: Union[str, date],
+ end: Union[str, date],
+ # 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,
+ ) -> V2RetrieveReportResponse:
+ """
+ Retrieves a performance report for an Auth rule containing daily statistics and
+ evaluation outcomes.
+
+ **Time Range Limitations:**
+
+ - Reports are supported for the past 3 months only
+ - Maximum interval length is 1 month
+ - Report data is available only through the previous day in UTC (current day
+ data is not available)
+
+ The report provides daily statistics for both current and draft versions of the
+ Auth rule, including approval, decline, and challenge counts along with sample
+ events.
+
+ Args:
+ begin: Start date for the report
+
+ end: End date for the report
+
+ 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 auth_rule_token:
+ raise ValueError(f"Expected a non-empty value for `auth_rule_token` but received {auth_rule_token!r}")
+ return await self._get(
+ f"/v2/auth_rules/{auth_rule_token}/report",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=await async_maybe_transform(
+ {
+ "begin": begin,
+ "end": end,
+ },
+ v2_retrieve_report_params.V2RetrieveReportParams,
+ ),
+ ),
+ cast_to=V2RetrieveReportResponse,
+ )
+
class V2WithRawResponse:
def __init__(self, v2: V2) -> None:
@@ -1663,8 +1800,13 @@ def __init__(self, v2: V2) -> None:
self.promote = _legacy_response.to_raw_response_wrapper(
v2.promote,
)
- self.report = _legacy_response.to_raw_response_wrapper(
- v2.report,
+ self.report = ( # pyright: ignore[reportDeprecated]
+ _legacy_response.to_raw_response_wrapper(
+ v2.report # pyright: ignore[reportDeprecated],
+ )
+ )
+ self.retrieve_report = _legacy_response.to_raw_response_wrapper(
+ v2.retrieve_report,
)
@cached_property
@@ -1702,8 +1844,13 @@ def __init__(self, v2: AsyncV2) -> None:
self.promote = _legacy_response.async_to_raw_response_wrapper(
v2.promote,
)
- self.report = _legacy_response.async_to_raw_response_wrapper(
- v2.report,
+ self.report = ( # pyright: ignore[reportDeprecated]
+ _legacy_response.async_to_raw_response_wrapper(
+ v2.report # pyright: ignore[reportDeprecated],
+ )
+ )
+ self.retrieve_report = _legacy_response.async_to_raw_response_wrapper(
+ v2.retrieve_report,
)
@cached_property
@@ -1741,8 +1888,13 @@ def __init__(self, v2: V2) -> None:
self.promote = to_streamed_response_wrapper(
v2.promote,
)
- self.report = to_streamed_response_wrapper(
- v2.report,
+ self.report = ( # pyright: ignore[reportDeprecated]
+ to_streamed_response_wrapper(
+ v2.report # pyright: ignore[reportDeprecated],
+ )
+ )
+ self.retrieve_report = to_streamed_response_wrapper(
+ v2.retrieve_report,
)
@cached_property
@@ -1780,8 +1932,13 @@ def __init__(self, v2: AsyncV2) -> None:
self.promote = async_to_streamed_response_wrapper(
v2.promote,
)
- self.report = async_to_streamed_response_wrapper(
- v2.report,
+ self.report = ( # pyright: ignore[reportDeprecated]
+ async_to_streamed_response_wrapper(
+ v2.report # pyright: ignore[reportDeprecated],
+ )
+ )
+ self.retrieve_report = async_to_streamed_response_wrapper(
+ v2.retrieve_report,
)
@cached_property
diff --git a/src/lithic/resources/cards/cards.py b/src/lithic/resources/cards/cards.py
index 231704c7..6794a99d 100644
--- a/src/lithic/resources/cards/cards.py
+++ b/src/lithic/resources/cards/cards.py
@@ -206,10 +206,12 @@ def create(
- `STANDARD_WITH_TRACKING` - USPS regular mail or similar international option,
with tracking
- `PRIORITY` - USPS Priority, 1-3 day shipping, with tracking
- - `EXPRESS` - FedEx Express, 3-day shipping, with tracking
- - `2_DAY` - FedEx 2-day shipping, with tracking
- - `EXPEDITED` - FedEx Standard Overnight or similar international option, with
+ - `EXPRESS` - FedEx or UPS depending on card manufacturer, Express, 3-day
+ shipping, with tracking
+ - `2_DAY` - FedEx or UPS depending on card manufacturer, 2-day shipping, with
tracking
+ - `EXPEDITED` - FedEx or UPS depending on card manufacturer, Standard Overnight
+ or similar international option, with tracking
spend_limit: Amount (in cents) to limit approved authorizations (e.g. 100000 would be a
$1,000 limit). Transaction requests above the spend limit will be declined. Note
@@ -532,10 +534,12 @@ def convert_physical(
- `STANDARD_WITH_TRACKING` - USPS regular mail or similar international option,
with tracking
- `PRIORITY` - USPS Priority, 1-3 day shipping, with tracking
- - `EXPRESS` - FedEx Express, 3-day shipping, with tracking
- - `2_DAY` - FedEx 2-day shipping, with tracking
- - `EXPEDITED` - FedEx Standard Overnight or similar international option, with
+ - `EXPRESS` - FedEx or UPS depending on card manufacturer, Express, 3-day
+ shipping, with tracking
+ - `2_DAY` - FedEx or UPS depending on card manufacturer, 2-day shipping, with
tracking
+ - `EXPEDITED` - FedEx or UPS depending on card manufacturer, Standard Overnight
+ or similar international option, with tracking
extra_headers: Send extra headers
@@ -867,10 +871,12 @@ def reissue(
- `STANDARD_WITH_TRACKING` - USPS regular mail or similar international option,
with tracking
- `PRIORITY` - USPS Priority, 1-3 day shipping, with tracking
- - `EXPRESS` - FedEx Express, 3-day shipping, with tracking
- - `2_DAY` - FedEx 2-day shipping, with tracking
- - `EXPEDITED` - FedEx Standard Overnight or similar international option, with
+ - `EXPRESS` - FedEx or UPS depending on card manufacturer, Express, 3-day
+ shipping, with tracking
+ - `2_DAY` - FedEx or UPS depending on card manufacturer, 2-day shipping, with
tracking
+ - `EXPEDITED` - FedEx or UPS depending on card manufacturer, Standard Overnight
+ or similar international option, with tracking
extra_headers: Send extra headers
@@ -952,10 +958,12 @@ def renew(
- `STANDARD_WITH_TRACKING` - USPS regular mail or similar international option,
with tracking
- `PRIORITY` - USPS Priority, 1-3 day shipping, with tracking
- - `EXPRESS` - FedEx Express, 3-day shipping, with tracking
- - `2_DAY` - FedEx 2-day shipping, with tracking
- - `EXPEDITED` - FedEx Standard Overnight or similar international option, with
+ - `EXPRESS` - FedEx or UPS depending on card manufacturer, Express, 3-day
+ shipping, with tracking
+ - `2_DAY` - FedEx or UPS depending on card manufacturer, 2-day shipping, with
tracking
+ - `EXPEDITED` - FedEx or UPS depending on card manufacturer, Standard Overnight
+ or similar international option, with tracking
extra_headers: Send extra headers
@@ -1239,10 +1247,12 @@ async def create(
- `STANDARD_WITH_TRACKING` - USPS regular mail or similar international option,
with tracking
- `PRIORITY` - USPS Priority, 1-3 day shipping, with tracking
- - `EXPRESS` - FedEx Express, 3-day shipping, with tracking
- - `2_DAY` - FedEx 2-day shipping, with tracking
- - `EXPEDITED` - FedEx Standard Overnight or similar international option, with
+ - `EXPRESS` - FedEx or UPS depending on card manufacturer, Express, 3-day
+ shipping, with tracking
+ - `2_DAY` - FedEx or UPS depending on card manufacturer, 2-day shipping, with
tracking
+ - `EXPEDITED` - FedEx or UPS depending on card manufacturer, Standard Overnight
+ or similar international option, with tracking
spend_limit: Amount (in cents) to limit approved authorizations (e.g. 100000 would be a
$1,000 limit). Transaction requests above the spend limit will be declined. Note
@@ -1565,10 +1575,12 @@ async def convert_physical(
- `STANDARD_WITH_TRACKING` - USPS regular mail or similar international option,
with tracking
- `PRIORITY` - USPS Priority, 1-3 day shipping, with tracking
- - `EXPRESS` - FedEx Express, 3-day shipping, with tracking
- - `2_DAY` - FedEx 2-day shipping, with tracking
- - `EXPEDITED` - FedEx Standard Overnight or similar international option, with
+ - `EXPRESS` - FedEx or UPS depending on card manufacturer, Express, 3-day
+ shipping, with tracking
+ - `2_DAY` - FedEx or UPS depending on card manufacturer, 2-day shipping, with
tracking
+ - `EXPEDITED` - FedEx or UPS depending on card manufacturer, Standard Overnight
+ or similar international option, with tracking
extra_headers: Send extra headers
@@ -1900,10 +1912,12 @@ async def reissue(
- `STANDARD_WITH_TRACKING` - USPS regular mail or similar international option,
with tracking
- `PRIORITY` - USPS Priority, 1-3 day shipping, with tracking
- - `EXPRESS` - FedEx Express, 3-day shipping, with tracking
- - `2_DAY` - FedEx 2-day shipping, with tracking
- - `EXPEDITED` - FedEx Standard Overnight or similar international option, with
+ - `EXPRESS` - FedEx or UPS depending on card manufacturer, Express, 3-day
+ shipping, with tracking
+ - `2_DAY` - FedEx or UPS depending on card manufacturer, 2-day shipping, with
tracking
+ - `EXPEDITED` - FedEx or UPS depending on card manufacturer, Standard Overnight
+ or similar international option, with tracking
extra_headers: Send extra headers
@@ -1985,10 +1999,12 @@ async def renew(
- `STANDARD_WITH_TRACKING` - USPS regular mail or similar international option,
with tracking
- `PRIORITY` - USPS Priority, 1-3 day shipping, with tracking
- - `EXPRESS` - FedEx Express, 3-day shipping, with tracking
- - `2_DAY` - FedEx 2-day shipping, with tracking
- - `EXPEDITED` - FedEx Standard Overnight or similar international option, with
+ - `EXPRESS` - FedEx or UPS depending on card manufacturer, Express, 3-day
+ shipping, with tracking
+ - `2_DAY` - FedEx or UPS depending on card manufacturer, 2-day shipping, with
tracking
+ - `EXPEDITED` - FedEx or UPS depending on card manufacturer, Standard Overnight
+ or similar international option, with tracking
extra_headers: Send extra headers
diff --git a/src/lithic/resources/external_bank_accounts/external_bank_accounts.py b/src/lithic/resources/external_bank_accounts/external_bank_accounts.py
index 03fd2188..4805c971 100644
--- a/src/lithic/resources/external_bank_accounts/external_bank_accounts.py
+++ b/src/lithic/resources/external_bank_accounts/external_bank_accounts.py
@@ -275,6 +275,80 @@ def create(
"""
...
+ @overload
+ def create(
+ self,
+ *,
+ account_number: str,
+ country: str,
+ currency: str,
+ owner: str,
+ owner_type: OwnerType,
+ routing_number: str,
+ type: Literal["CHECKING", "SAVINGS"],
+ verification_method: Literal["UNVERIFIED"],
+ account_token: str | NotGiven = NOT_GIVEN,
+ address: ExternalBankAccountAddressParam | NotGiven = NOT_GIVEN,
+ company_id: str | NotGiven = NOT_GIVEN,
+ dob: Union[str, date] | NotGiven = NOT_GIVEN,
+ doing_business_as: str | NotGiven = NOT_GIVEN,
+ name: str | NotGiven = NOT_GIVEN,
+ user_defined_id: str | NotGiven = NOT_GIVEN,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
+ ) -> ExternalBankAccountCreateResponse:
+ """
+ Creates an external bank account within a program or Lithic account.
+
+ Args:
+ account_number: Account Number
+
+ country: The country that the bank account is located in using ISO 3166-1. We will only
+ accept USA bank accounts e.g., USA
+
+ currency: currency of the external account 3-character alphabetic ISO 4217 code
+
+ owner: Legal Name of the business or individual who owns the external account. This
+ will appear in statements
+
+ owner_type: Owner Type
+
+ routing_number: Routing Number
+
+ type: Account Type
+
+ verification_method: Verification Method
+
+ account_token: Indicates which Lithic account the external account is associated with. For
+ external accounts that are associated with the program, account_token field
+ returned will be null
+
+ address: Address
+
+ company_id: Optional field that helps identify bank accounts in receipts
+
+ dob: Date of Birth of the Individual that owns the external bank account
+
+ doing_business_as: Doing Business As
+
+ name: The nickname for this External Bank Account
+
+ user_defined_id: User Defined ID
+
+ 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
+ """
+ ...
+
@required_args(
[
"account_number",
@@ -310,7 +384,7 @@ def create(
owner_type: OwnerType,
routing_number: str | NotGiven = NOT_GIVEN,
type: Literal["CHECKING", "SAVINGS"] | NotGiven = NOT_GIVEN,
- verification_method: VerificationMethod | Literal["EXTERNALLY_VERIFIED"],
+ verification_method: VerificationMethod | Literal["EXTERNALLY_VERIFIED"] | Literal["UNVERIFIED"],
account_token: str | NotGiven = NOT_GIVEN,
address: ExternalBankAccountAddressParam | NotGiven = NOT_GIVEN,
company_id: str | NotGiven = NOT_GIVEN,
@@ -844,6 +918,80 @@ async def create(
"""
...
+ @overload
+ async def create(
+ self,
+ *,
+ account_number: str,
+ country: str,
+ currency: str,
+ owner: str,
+ owner_type: OwnerType,
+ routing_number: str,
+ type: Literal["CHECKING", "SAVINGS"],
+ verification_method: Literal["UNVERIFIED"],
+ account_token: str | NotGiven = NOT_GIVEN,
+ address: ExternalBankAccountAddressParam | NotGiven = NOT_GIVEN,
+ company_id: str | NotGiven = NOT_GIVEN,
+ dob: Union[str, date] | NotGiven = NOT_GIVEN,
+ doing_business_as: str | NotGiven = NOT_GIVEN,
+ name: str | NotGiven = NOT_GIVEN,
+ user_defined_id: str | NotGiven = NOT_GIVEN,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
+ ) -> ExternalBankAccountCreateResponse:
+ """
+ Creates an external bank account within a program or Lithic account.
+
+ Args:
+ account_number: Account Number
+
+ country: The country that the bank account is located in using ISO 3166-1. We will only
+ accept USA bank accounts e.g., USA
+
+ currency: currency of the external account 3-character alphabetic ISO 4217 code
+
+ owner: Legal Name of the business or individual who owns the external account. This
+ will appear in statements
+
+ owner_type: Owner Type
+
+ routing_number: Routing Number
+
+ type: Account Type
+
+ verification_method: Verification Method
+
+ account_token: Indicates which Lithic account the external account is associated with. For
+ external accounts that are associated with the program, account_token field
+ returned will be null
+
+ address: Address
+
+ company_id: Optional field that helps identify bank accounts in receipts
+
+ dob: Date of Birth of the Individual that owns the external bank account
+
+ doing_business_as: Doing Business As
+
+ name: The nickname for this External Bank Account
+
+ user_defined_id: User Defined ID
+
+ 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
+ """
+ ...
+
@required_args(
[
"account_number",
@@ -879,7 +1027,7 @@ async def create(
owner_type: OwnerType,
routing_number: str | NotGiven = NOT_GIVEN,
type: Literal["CHECKING", "SAVINGS"] | NotGiven = NOT_GIVEN,
- verification_method: VerificationMethod | Literal["EXTERNALLY_VERIFIED"],
+ verification_method: VerificationMethod | Literal["EXTERNALLY_VERIFIED"] | Literal["UNVERIFIED"],
account_token: str | NotGiven = NOT_GIVEN,
address: ExternalBankAccountAddressParam | NotGiven = NOT_GIVEN,
company_id: str | NotGiven = NOT_GIVEN,
diff --git a/src/lithic/resources/fraud/__init__.py b/src/lithic/resources/fraud/__init__.py
new file mode 100644
index 00000000..5ebcc75e
--- /dev/null
+++ b/src/lithic/resources/fraud/__init__.py
@@ -0,0 +1,33 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .fraud import (
+ Fraud,
+ AsyncFraud,
+ FraudWithRawResponse,
+ AsyncFraudWithRawResponse,
+ FraudWithStreamingResponse,
+ AsyncFraudWithStreamingResponse,
+)
+from .transactions import (
+ Transactions,
+ AsyncTransactions,
+ TransactionsWithRawResponse,
+ AsyncTransactionsWithRawResponse,
+ TransactionsWithStreamingResponse,
+ AsyncTransactionsWithStreamingResponse,
+)
+
+__all__ = [
+ "Transactions",
+ "AsyncTransactions",
+ "TransactionsWithRawResponse",
+ "AsyncTransactionsWithRawResponse",
+ "TransactionsWithStreamingResponse",
+ "AsyncTransactionsWithStreamingResponse",
+ "Fraud",
+ "AsyncFraud",
+ "FraudWithRawResponse",
+ "AsyncFraudWithRawResponse",
+ "FraudWithStreamingResponse",
+ "AsyncFraudWithStreamingResponse",
+]
diff --git a/src/lithic/resources/fraud/fraud.py b/src/lithic/resources/fraud/fraud.py
new file mode 100644
index 00000000..ba851033
--- /dev/null
+++ b/src/lithic/resources/fraud/fraud.py
@@ -0,0 +1,102 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from ..._compat import cached_property
+from ..._resource import SyncAPIResource, AsyncAPIResource
+from .transactions import (
+ Transactions,
+ AsyncTransactions,
+ TransactionsWithRawResponse,
+ AsyncTransactionsWithRawResponse,
+ TransactionsWithStreamingResponse,
+ AsyncTransactionsWithStreamingResponse,
+)
+
+__all__ = ["Fraud", "AsyncFraud"]
+
+
+class Fraud(SyncAPIResource):
+ @cached_property
+ def transactions(self) -> Transactions:
+ return Transactions(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> FraudWithRawResponse:
+ """
+ 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 FraudWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> FraudWithStreamingResponse:
+ """
+ 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 FraudWithStreamingResponse(self)
+
+
+class AsyncFraud(AsyncAPIResource):
+ @cached_property
+ def transactions(self) -> AsyncTransactions:
+ return AsyncTransactions(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> AsyncFraudWithRawResponse:
+ """
+ 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 AsyncFraudWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncFraudWithStreamingResponse:
+ """
+ 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 AsyncFraudWithStreamingResponse(self)
+
+
+class FraudWithRawResponse:
+ def __init__(self, fraud: Fraud) -> None:
+ self._fraud = fraud
+
+ @cached_property
+ def transactions(self) -> TransactionsWithRawResponse:
+ return TransactionsWithRawResponse(self._fraud.transactions)
+
+
+class AsyncFraudWithRawResponse:
+ def __init__(self, fraud: AsyncFraud) -> None:
+ self._fraud = fraud
+
+ @cached_property
+ def transactions(self) -> AsyncTransactionsWithRawResponse:
+ return AsyncTransactionsWithRawResponse(self._fraud.transactions)
+
+
+class FraudWithStreamingResponse:
+ def __init__(self, fraud: Fraud) -> None:
+ self._fraud = fraud
+
+ @cached_property
+ def transactions(self) -> TransactionsWithStreamingResponse:
+ return TransactionsWithStreamingResponse(self._fraud.transactions)
+
+
+class AsyncFraudWithStreamingResponse:
+ def __init__(self, fraud: AsyncFraud) -> None:
+ self._fraud = fraud
+
+ @cached_property
+ def transactions(self) -> AsyncTransactionsWithStreamingResponse:
+ return AsyncTransactionsWithStreamingResponse(self._fraud.transactions)
diff --git a/src/lithic/resources/fraud/transactions.py b/src/lithic/resources/fraud/transactions.py
new file mode 100644
index 00000000..3ec3e274
--- /dev/null
+++ b/src/lithic/resources/fraud/transactions.py
@@ -0,0 +1,348 @@
+# 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 NOT_GIVEN, Body, Query, Headers, NotGiven
+from ..._utils import maybe_transform, async_maybe_transform
+from ..._compat import cached_property
+from ..._resource import SyncAPIResource, AsyncAPIResource
+from ..._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper
+from ...types.fraud import transaction_report_params
+from ..._base_client import make_request_options
+from ...types.fraud.transaction_report_response import TransactionReportResponse
+from ...types.fraud.transaction_retrieve_response import TransactionRetrieveResponse
+
+__all__ = ["Transactions", "AsyncTransactions"]
+
+
+class Transactions(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> TransactionsWithRawResponse:
+ """
+ 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 TransactionsWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> TransactionsWithStreamingResponse:
+ """
+ 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 TransactionsWithStreamingResponse(self)
+
+ def retrieve(
+ self,
+ transaction_token: str,
+ *,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
+ ) -> TransactionRetrieveResponse:
+ """
+ Retrieve a fraud report for a specific transaction identified by its unique
+ transaction token.
+
+ Args:
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ if not transaction_token:
+ raise ValueError(f"Expected a non-empty value for `transaction_token` but received {transaction_token!r}")
+ return self._get(
+ f"/v1/fraud/transactions/{transaction_token}",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=TransactionRetrieveResponse,
+ )
+
+ def report(
+ self,
+ transaction_token: str,
+ *,
+ fraud_status: Literal["SUSPECTED_FRAUD", "FRAUDULENT", "NOT_FRAUDULENT"],
+ comment: str | NotGiven = NOT_GIVEN,
+ fraud_type: Literal[
+ "FIRST_PARTY_FRAUD", "ACCOUNT_TAKEOVER", "CARD_COMPROMISED", "IDENTITY_THEFT", "CARDHOLDER_MANIPULATION"
+ ]
+ | NotGiven = NOT_GIVEN,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
+ ) -> TransactionReportResponse:
+ """
+ Report fraud for a specific transaction token by providing details such as fraud
+ type, fraud status, and any additional comments.
+
+ Args:
+ fraud_status: The fraud status of the transaction, string (enum) supporting the following
+ values:
+
+ - `SUSPECTED_FRAUD`: The transaction is suspected to be fraudulent, but this
+ hasn’t been confirmed.
+ - `FRAUDULENT`: The transaction is confirmed to be fraudulent. A transaction may
+ immediately be moved into this state, or be graduated into this state from the
+ `SUSPECTED_FRAUD` state.
+ - `NOT_FRAUDULENT`: The transaction is (explicitly) marked as not fraudulent. A
+ transaction may immediately be moved into this state, or be graduated into
+ this state from the `SUSPECTED_FRAUD` state.
+
+ comment: Optional field providing additional information or context about why the
+ transaction is considered fraudulent.
+
+ fraud_type: Specifies the type or category of fraud that the transaction is suspected or
+ confirmed to involve, string (enum) supporting the following values:
+
+ - `FIRST_PARTY_FRAUD`: First-party fraud occurs when a legitimate account or
+ cardholder intentionally misuses financial services for personal gain. This
+ includes actions such as disputing legitimate transactions to obtain a refund,
+ abusing return policies, or defaulting on credit obligations without intent to
+ repay.
+ - `ACCOUNT_TAKEOVER`: Account takeover fraud occurs when a fraudster gains
+ unauthorized access to an existing account, modifies account settings, and
+ carries out fraudulent transactions.
+ - `CARD_COMPROMISED`: Card compromised fraud occurs when a fraudster gains
+ access to card details without taking over the account, such as through
+ physical card theft, cloning, or online data breaches.
+ - `IDENTITY_THEFT`: Identity theft fraud occurs when a fraudster uses stolen
+ personal information, such as Social Security numbers or addresses, to open
+ accounts, apply for loans, or conduct financial transactions in someone's
+ name.
+ - `CARDHOLDER_MANIPULATION`: This type of fraud occurs when a fraudster
+ manipulates or coerces a legitimate cardholder into unauthorized transactions,
+ often through social engineering tactics.
+
+ 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 transaction_token:
+ raise ValueError(f"Expected a non-empty value for `transaction_token` but received {transaction_token!r}")
+ return self._post(
+ f"/v1/fraud/transactions/{transaction_token}",
+ body=maybe_transform(
+ {
+ "fraud_status": fraud_status,
+ "comment": comment,
+ "fraud_type": fraud_type,
+ },
+ transaction_report_params.TransactionReportParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=TransactionReportResponse,
+ )
+
+
+class AsyncTransactions(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncTransactionsWithRawResponse:
+ """
+ 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 AsyncTransactionsWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncTransactionsWithStreamingResponse:
+ """
+ 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 AsyncTransactionsWithStreamingResponse(self)
+
+ async def retrieve(
+ self,
+ transaction_token: str,
+ *,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
+ ) -> TransactionRetrieveResponse:
+ """
+ Retrieve a fraud report for a specific transaction identified by its unique
+ transaction token.
+
+ Args:
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ if not transaction_token:
+ raise ValueError(f"Expected a non-empty value for `transaction_token` but received {transaction_token!r}")
+ return await self._get(
+ f"/v1/fraud/transactions/{transaction_token}",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=TransactionRetrieveResponse,
+ )
+
+ async def report(
+ self,
+ transaction_token: str,
+ *,
+ fraud_status: Literal["SUSPECTED_FRAUD", "FRAUDULENT", "NOT_FRAUDULENT"],
+ comment: str | NotGiven = NOT_GIVEN,
+ fraud_type: Literal[
+ "FIRST_PARTY_FRAUD", "ACCOUNT_TAKEOVER", "CARD_COMPROMISED", "IDENTITY_THEFT", "CARDHOLDER_MANIPULATION"
+ ]
+ | NotGiven = NOT_GIVEN,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
+ ) -> TransactionReportResponse:
+ """
+ Report fraud for a specific transaction token by providing details such as fraud
+ type, fraud status, and any additional comments.
+
+ Args:
+ fraud_status: The fraud status of the transaction, string (enum) supporting the following
+ values:
+
+ - `SUSPECTED_FRAUD`: The transaction is suspected to be fraudulent, but this
+ hasn’t been confirmed.
+ - `FRAUDULENT`: The transaction is confirmed to be fraudulent. A transaction may
+ immediately be moved into this state, or be graduated into this state from the
+ `SUSPECTED_FRAUD` state.
+ - `NOT_FRAUDULENT`: The transaction is (explicitly) marked as not fraudulent. A
+ transaction may immediately be moved into this state, or be graduated into
+ this state from the `SUSPECTED_FRAUD` state.
+
+ comment: Optional field providing additional information or context about why the
+ transaction is considered fraudulent.
+
+ fraud_type: Specifies the type or category of fraud that the transaction is suspected or
+ confirmed to involve, string (enum) supporting the following values:
+
+ - `FIRST_PARTY_FRAUD`: First-party fraud occurs when a legitimate account or
+ cardholder intentionally misuses financial services for personal gain. This
+ includes actions such as disputing legitimate transactions to obtain a refund,
+ abusing return policies, or defaulting on credit obligations without intent to
+ repay.
+ - `ACCOUNT_TAKEOVER`: Account takeover fraud occurs when a fraudster gains
+ unauthorized access to an existing account, modifies account settings, and
+ carries out fraudulent transactions.
+ - `CARD_COMPROMISED`: Card compromised fraud occurs when a fraudster gains
+ access to card details without taking over the account, such as through
+ physical card theft, cloning, or online data breaches.
+ - `IDENTITY_THEFT`: Identity theft fraud occurs when a fraudster uses stolen
+ personal information, such as Social Security numbers or addresses, to open
+ accounts, apply for loans, or conduct financial transactions in someone's
+ name.
+ - `CARDHOLDER_MANIPULATION`: This type of fraud occurs when a fraudster
+ manipulates or coerces a legitimate cardholder into unauthorized transactions,
+ often through social engineering tactics.
+
+ 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 transaction_token:
+ raise ValueError(f"Expected a non-empty value for `transaction_token` but received {transaction_token!r}")
+ return await self._post(
+ f"/v1/fraud/transactions/{transaction_token}",
+ body=await async_maybe_transform(
+ {
+ "fraud_status": fraud_status,
+ "comment": comment,
+ "fraud_type": fraud_type,
+ },
+ transaction_report_params.TransactionReportParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=TransactionReportResponse,
+ )
+
+
+class TransactionsWithRawResponse:
+ def __init__(self, transactions: Transactions) -> None:
+ self._transactions = transactions
+
+ self.retrieve = _legacy_response.to_raw_response_wrapper(
+ transactions.retrieve,
+ )
+ self.report = _legacy_response.to_raw_response_wrapper(
+ transactions.report,
+ )
+
+
+class AsyncTransactionsWithRawResponse:
+ def __init__(self, transactions: AsyncTransactions) -> None:
+ self._transactions = transactions
+
+ self.retrieve = _legacy_response.async_to_raw_response_wrapper(
+ transactions.retrieve,
+ )
+ self.report = _legacy_response.async_to_raw_response_wrapper(
+ transactions.report,
+ )
+
+
+class TransactionsWithStreamingResponse:
+ def __init__(self, transactions: Transactions) -> None:
+ self._transactions = transactions
+
+ self.retrieve = to_streamed_response_wrapper(
+ transactions.retrieve,
+ )
+ self.report = to_streamed_response_wrapper(
+ transactions.report,
+ )
+
+
+class AsyncTransactionsWithStreamingResponse:
+ def __init__(self, transactions: AsyncTransactions) -> None:
+ self._transactions = transactions
+
+ self.retrieve = async_to_streamed_response_wrapper(
+ transactions.retrieve,
+ )
+ self.report = async_to_streamed_response_wrapper(
+ transactions.report,
+ )
diff --git a/src/lithic/resources/three_ds/authentication.py b/src/lithic/resources/three_ds/authentication.py
index 81b628cf..789b7498 100644
--- a/src/lithic/resources/three_ds/authentication.py
+++ b/src/lithic/resources/three_ds/authentication.py
@@ -98,8 +98,12 @@ def simulate(
has a valid phone number configured to receive the OTP code via SMS.
Args:
+ merchant: Merchant information for the simulated transaction
+
pan: Sixteen digit card number.
+ transaction: Transaction details for the simulation
+
card_expiry_check: When set will use the following values as part of the Simulated Authentication.
When not set defaults to MATCH
@@ -143,9 +147,9 @@ def simulate_otp_entry(
"""Endpoint for simulating entering OTP into 3DS Challenge UI.
A call to
- /v1/three_ds_authentication/simulate that resulted in triggered SMS-OTP
- challenge must precede. Only a single attempt is supported; upon entering OTP,
- the challenge is either approved or declined.
+ [/v1/three_ds_authentication/simulate](https://docs.lithic.com/reference/postsimulateauthentication)
+ that resulted in triggered SMS-OTP challenge must precede. Only a single attempt
+ is supported; upon entering OTP, the challenge is either approved or declined.
Args:
token: A unique token returned as part of a /v1/three_ds_authentication/simulate call
@@ -255,8 +259,12 @@ async def simulate(
has a valid phone number configured to receive the OTP code via SMS.
Args:
+ merchant: Merchant information for the simulated transaction
+
pan: Sixteen digit card number.
+ transaction: Transaction details for the simulation
+
card_expiry_check: When set will use the following values as part of the Simulated Authentication.
When not set defaults to MATCH
@@ -300,9 +308,9 @@ async def simulate_otp_entry(
"""Endpoint for simulating entering OTP into 3DS Challenge UI.
A call to
- /v1/three_ds_authentication/simulate that resulted in triggered SMS-OTP
- challenge must precede. Only a single attempt is supported; upon entering OTP,
- the challenge is either approved or declined.
+ [/v1/three_ds_authentication/simulate](https://docs.lithic.com/reference/postsimulateauthentication)
+ that resulted in triggered SMS-OTP challenge must precede. Only a single attempt
+ is supported; upon entering OTP, the challenge is either approved or declined.
Args:
token: A unique token returned as part of a /v1/three_ds_authentication/simulate call
diff --git a/src/lithic/resources/three_ds/decisioning.py b/src/lithic/resources/three_ds/decisioning.py
index c9721bc6..7ad3a088 100644
--- a/src/lithic/resources/three_ds/decisioning.py
+++ b/src/lithic/resources/three_ds/decisioning.py
@@ -50,16 +50,20 @@ def challenge_response(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
) -> None:
- """
- Card program's response to a 3DS Challenge Request (CReq)
+ """Card program's response to a 3DS Challenge Request.
+
+ Challenge Request is emitted
+ as a webhook
+ [three_ds_authentication.challenge](https://docs.lithic.com/reference/post_three-ds-authentication-challenge)
+ and your Card Program needs to be configured with Out of Band (OOB) Challenges
+ in order to receive it (see https://docs.lithic.com/docs/3ds-challenge-flow for
+ more information).
Args:
- token: Globally unique identifier for the 3DS authentication. This token is sent as
- part of the initial 3DS Decisioning Request and as part of the 3DS Challenge
- Event in the [ThreeDSAuthentication](#/components/schemas/ThreeDSAuthentication)
- object
+ token: Globally unique identifier for 3DS Authentication that resulted in
+ PENDING_CHALLENGE authentication result.
- challenge_response: Whether the Cardholder has Approved or Declined the issued Challenge
+ challenge_response: Whether the Cardholder has approved or declined the issued Challenge
extra_headers: Send extra headers
@@ -169,16 +173,20 @@ async def challenge_response(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
) -> None:
- """
- Card program's response to a 3DS Challenge Request (CReq)
+ """Card program's response to a 3DS Challenge Request.
+
+ Challenge Request is emitted
+ as a webhook
+ [three_ds_authentication.challenge](https://docs.lithic.com/reference/post_three-ds-authentication-challenge)
+ and your Card Program needs to be configured with Out of Band (OOB) Challenges
+ in order to receive it (see https://docs.lithic.com/docs/3ds-challenge-flow for
+ more information).
Args:
- token: Globally unique identifier for the 3DS authentication. This token is sent as
- part of the initial 3DS Decisioning Request and as part of the 3DS Challenge
- Event in the [ThreeDSAuthentication](#/components/schemas/ThreeDSAuthentication)
- object
+ token: Globally unique identifier for 3DS Authentication that resulted in
+ PENDING_CHALLENGE authentication result.
- challenge_response: Whether the Cardholder has Approved or Declined the issued Challenge
+ challenge_response: Whether the Cardholder has approved or declined the issued Challenge
extra_headers: Send extra headers
diff --git a/src/lithic/types/auth_rules/__init__.py b/src/lithic/types/auth_rules/__init__.py
index b2982d4a..cb697fd1 100644
--- a/src/lithic/types/auth_rules/__init__.py
+++ b/src/lithic/types/auth_rules/__init__.py
@@ -2,6 +2,7 @@
from __future__ import annotations
+from .rule_stats import RuleStats as RuleStats
from .v2_list_params import V2ListParams as V2ListParams
from .v2_apply_params import V2ApplyParams as V2ApplyParams
from .v2_draft_params import V2DraftParams as V2DraftParams
@@ -19,6 +20,8 @@
from .conditional_attribute import ConditionalAttribute as ConditionalAttribute
from .velocity_limit_params import VelocityLimitParams as VelocityLimitParams
from .auth_rule_condition_param import AuthRuleConditionParam as AuthRuleConditionParam
+from .v2_retrieve_report_params import V2RetrieveReportParams as V2RetrieveReportParams
+from .v2_retrieve_report_response import V2RetrieveReportResponse as V2RetrieveReportResponse
from .velocity_limit_params_param import VelocityLimitParamsParam as VelocityLimitParamsParam
from .conditional_block_parameters import ConditionalBlockParameters as ConditionalBlockParameters
from .conditional_block_parameters_param import ConditionalBlockParametersParam as ConditionalBlockParametersParam
diff --git a/src/lithic/types/auth_rules/rule_stats.py b/src/lithic/types/auth_rules/rule_stats.py
new file mode 100644
index 00000000..b3e621f9
--- /dev/null
+++ b/src/lithic/types/auth_rules/rule_stats.py
@@ -0,0 +1,56 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Optional
+from datetime import datetime
+from typing_extensions import Literal
+
+from ..._models import BaseModel
+
+__all__ = ["RuleStats", "Example"]
+
+
+class Example(BaseModel):
+ approved: Optional[bool] = None
+ """Whether the rule would have approved the request."""
+
+ decision: Optional[Literal["APPROVED", "DECLINED", "CHALLENGED"]] = None
+ """The decision made by the rule for this event."""
+
+ event_token: Optional[str] = None
+ """The event token."""
+
+ timestamp: Optional[datetime] = None
+ """The timestamp of the event."""
+
+
+class RuleStats(BaseModel):
+ approved: Optional[int] = None
+ """
+ The total number of historical transactions approved by this rule during the
+ relevant period, or the number of transactions that would have been approved if
+ the rule was evaluated in shadow mode.
+ """
+
+ challenged: Optional[int] = None
+ """
+ The total number of historical transactions challenged by this rule during the
+ relevant period, or the number of transactions that would have been challenged
+ if the rule was evaluated in shadow mode. Currently applicable only for 3DS Auth
+ Rules.
+ """
+
+ declined: Optional[int] = None
+ """
+ The total number of historical transactions declined by this rule during the
+ relevant period, or the number of transactions that would have been declined if
+ the rule was evaluated in shadow mode.
+ """
+
+ examples: Optional[List[Example]] = None
+ """Example events and their outcomes."""
+
+ version: Optional[int] = None
+ """
+ The version of the rule, this is incremented whenever the rule's parameters
+ change.
+ """
diff --git a/src/lithic/types/auth_rules/v2/backtest_results.py b/src/lithic/types/auth_rules/v2/backtest_results.py
index 7d5e223f..5496ba32 100644
--- a/src/lithic/types/auth_rules/v2/backtest_results.py
+++ b/src/lithic/types/auth_rules/v2/backtest_results.py
@@ -1,120 +1,18 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from typing import List, Optional
+from typing import Optional
from datetime import datetime
-from typing_extensions import Literal
from ...._models import BaseModel
+from ..rule_stats import RuleStats
-__all__ = [
- "BacktestResults",
- "Results",
- "ResultsCurrentVersion",
- "ResultsCurrentVersionExample",
- "ResultsDraftVersion",
- "ResultsDraftVersionExample",
- "SimulationParameters",
-]
-
-
-class ResultsCurrentVersionExample(BaseModel):
- approved: Optional[bool] = None
- """Whether the rule would have approved the request."""
-
- decision: Optional[Literal["APPROVED", "DECLINED", "CHALLENGED"]] = None
- """The decision made by the rule for this event."""
-
- event_token: Optional[str] = None
- """The event token."""
-
- timestamp: Optional[datetime] = None
- """The timestamp of the event."""
-
-
-class ResultsCurrentVersion(BaseModel):
- approved: Optional[int] = None
- """
- The total number of historical transactions approved by this rule during the
- relevant period, or the number of transactions that would have been approved if
- the rule was evaluated in shadow mode.
- """
-
- challenged: Optional[int] = None
- """
- The total number of historical transactions challenged by this rule during the
- relevant period, or the number of transactions that would have been challenged
- if the rule was evaluated in shadow mode. Currently applicable only for 3DS Auth
- Rules.
- """
-
- declined: Optional[int] = None
- """
- The total number of historical transactions declined by this rule during the
- relevant period, or the number of transactions that would have been declined if
- the rule was evaluated in shadow mode.
- """
-
- examples: Optional[List[ResultsCurrentVersionExample]] = None
- """Example events and their outcomes."""
-
- version: Optional[int] = None
- """
- The version of the rule, this is incremented whenever the rule's parameters
- change.
- """
-
-
-class ResultsDraftVersionExample(BaseModel):
- approved: Optional[bool] = None
- """Whether the rule would have approved the request."""
-
- decision: Optional[Literal["APPROVED", "DECLINED", "CHALLENGED"]] = None
- """The decision made by the rule for this event."""
-
- event_token: Optional[str] = None
- """The event token."""
-
- timestamp: Optional[datetime] = None
- """The timestamp of the event."""
-
-
-class ResultsDraftVersion(BaseModel):
- approved: Optional[int] = None
- """
- The total number of historical transactions approved by this rule during the
- relevant period, or the number of transactions that would have been approved if
- the rule was evaluated in shadow mode.
- """
-
- challenged: Optional[int] = None
- """
- The total number of historical transactions challenged by this rule during the
- relevant period, or the number of transactions that would have been challenged
- if the rule was evaluated in shadow mode. Currently applicable only for 3DS Auth
- Rules.
- """
-
- declined: Optional[int] = None
- """
- The total number of historical transactions declined by this rule during the
- relevant period, or the number of transactions that would have been declined if
- the rule was evaluated in shadow mode.
- """
-
- examples: Optional[List[ResultsDraftVersionExample]] = None
- """Example events and their outcomes."""
-
- version: Optional[int] = None
- """
- The version of the rule, this is incremented whenever the rule's parameters
- change.
- """
+__all__ = ["BacktestResults", "Results", "SimulationParameters"]
class Results(BaseModel):
- current_version: Optional[ResultsCurrentVersion] = None
+ current_version: Optional[RuleStats] = None
- draft_version: Optional[ResultsDraftVersion] = None
+ draft_version: Optional[RuleStats] = None
class SimulationParameters(BaseModel):
diff --git a/src/lithic/types/auth_rules/v2_retrieve_report_params.py b/src/lithic/types/auth_rules/v2_retrieve_report_params.py
new file mode 100644
index 00000000..79d6b615
--- /dev/null
+++ b/src/lithic/types/auth_rules/v2_retrieve_report_params.py
@@ -0,0 +1,19 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Union
+from datetime import date
+from typing_extensions import Required, Annotated, TypedDict
+
+from ..._utils import PropertyInfo
+
+__all__ = ["V2RetrieveReportParams"]
+
+
+class V2RetrieveReportParams(TypedDict, total=False):
+ begin: Required[Annotated[Union[str, date], PropertyInfo(format="iso8601")]]
+ """Start date for the report"""
+
+ end: Required[Annotated[Union[str, date], PropertyInfo(format="iso8601")]]
+ """End date for the report"""
diff --git a/src/lithic/types/auth_rules/v2_retrieve_report_response.py b/src/lithic/types/auth_rules/v2_retrieve_report_response.py
new file mode 100644
index 00000000..27169af6
--- /dev/null
+++ b/src/lithic/types/auth_rules/v2_retrieve_report_response.py
@@ -0,0 +1,34 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+import datetime
+from typing import List, Optional
+
+from ..._models import BaseModel
+from .rule_stats import RuleStats
+
+__all__ = ["V2RetrieveReportResponse", "DailyStatistic"]
+
+
+class DailyStatistic(BaseModel):
+ current_version_statistics: Optional[RuleStats] = None
+ """Detailed statistics for the current version of the rule."""
+
+ date: datetime.date
+ """The date (UTC) for which the statistics are reported."""
+
+ draft_version_statistics: Optional[RuleStats] = None
+ """Detailed statistics for the draft version of the rule."""
+
+
+class V2RetrieveReportResponse(BaseModel):
+ auth_rule_token: str
+ """Auth Rule Token"""
+
+ begin: datetime.date
+ """The start date (UTC) of the report."""
+
+ daily_statistics: List[DailyStatistic]
+ """Daily evaluation statistics for the Auth Rule."""
+
+ end: datetime.date
+ """The end date (UTC) of the report."""
diff --git a/src/lithic/types/card_convert_physical_params.py b/src/lithic/types/card_convert_physical_params.py
index 745c0426..879679cf 100644
--- a/src/lithic/types/card_convert_physical_params.py
+++ b/src/lithic/types/card_convert_physical_params.py
@@ -35,8 +35,10 @@ class CardConvertPhysicalParams(TypedDict, total=False):
- `STANDARD_WITH_TRACKING` - USPS regular mail or similar international option,
with tracking
- `PRIORITY` - USPS Priority, 1-3 day shipping, with tracking
- - `EXPRESS` - FedEx Express, 3-day shipping, with tracking
- - `2_DAY` - FedEx 2-day shipping, with tracking
- - `EXPEDITED` - FedEx Standard Overnight or similar international option, with
+ - `EXPRESS` - FedEx or UPS depending on card manufacturer, Express, 3-day
+ shipping, with tracking
+ - `2_DAY` - FedEx or UPS depending on card manufacturer, 2-day shipping, with
tracking
+ - `EXPEDITED` - FedEx or UPS depending on card manufacturer, Standard Overnight
+ or similar international option, with tracking
"""
diff --git a/src/lithic/types/card_create_params.py b/src/lithic/types/card_create_params.py
index fb295a5b..3318f48e 100644
--- a/src/lithic/types/card_create_params.py
+++ b/src/lithic/types/card_create_params.py
@@ -121,10 +121,12 @@ class CardCreateParams(TypedDict, total=False):
- `STANDARD_WITH_TRACKING` - USPS regular mail or similar international option,
with tracking
- `PRIORITY` - USPS Priority, 1-3 day shipping, with tracking
- - `EXPRESS` - FedEx Express, 3-day shipping, with tracking
- - `2_DAY` - FedEx 2-day shipping, with tracking
- - `EXPEDITED` - FedEx Standard Overnight or similar international option, with
+ - `EXPRESS` - FedEx or UPS depending on card manufacturer, Express, 3-day
+ shipping, with tracking
+ - `2_DAY` - FedEx or UPS depending on card manufacturer, 2-day shipping, with
tracking
+ - `EXPEDITED` - FedEx or UPS depending on card manufacturer, Standard Overnight
+ or similar international option, with tracking
"""
spend_limit: int
diff --git a/src/lithic/types/card_reissue_params.py b/src/lithic/types/card_reissue_params.py
index ca25add9..2067ba9c 100644
--- a/src/lithic/types/card_reissue_params.py
+++ b/src/lithic/types/card_reissue_params.py
@@ -35,8 +35,10 @@ class CardReissueParams(TypedDict, total=False):
- `STANDARD_WITH_TRACKING` - USPS regular mail or similar international option,
with tracking
- `PRIORITY` - USPS Priority, 1-3 day shipping, with tracking
- - `EXPRESS` - FedEx Express, 3-day shipping, with tracking
- - `2_DAY` - FedEx 2-day shipping, with tracking
- - `EXPEDITED` - FedEx Standard Overnight or similar international option, with
+ - `EXPRESS` - FedEx or UPS depending on card manufacturer, Express, 3-day
+ shipping, with tracking
+ - `2_DAY` - FedEx or UPS depending on card manufacturer, 2-day shipping, with
tracking
+ - `EXPEDITED` - FedEx or UPS depending on card manufacturer, Standard Overnight
+ or similar international option, with tracking
"""
diff --git a/src/lithic/types/card_renew_params.py b/src/lithic/types/card_renew_params.py
index 832b2ca6..9c832103 100644
--- a/src/lithic/types/card_renew_params.py
+++ b/src/lithic/types/card_renew_params.py
@@ -49,8 +49,10 @@ class CardRenewParams(TypedDict, total=False):
- `STANDARD_WITH_TRACKING` - USPS regular mail or similar international option,
with tracking
- `PRIORITY` - USPS Priority, 1-3 day shipping, with tracking
- - `EXPRESS` - FedEx Express, 3-day shipping, with tracking
- - `2_DAY` - FedEx 2-day shipping, with tracking
- - `EXPEDITED` - FedEx Standard Overnight or similar international option, with
+ - `EXPRESS` - FedEx or UPS depending on card manufacturer, Express, 3-day
+ shipping, with tracking
+ - `2_DAY` - FedEx or UPS depending on card manufacturer, 2-day shipping, with
tracking
+ - `EXPEDITED` - FedEx or UPS depending on card manufacturer, Standard Overnight
+ or similar international option, with tracking
"""
diff --git a/src/lithic/types/external_bank_account_create_params.py b/src/lithic/types/external_bank_account_create_params.py
index 441ce050..10cefa11 100644
--- a/src/lithic/types/external_bank_account_create_params.py
+++ b/src/lithic/types/external_bank_account_create_params.py
@@ -16,6 +16,7 @@
"BankVerifiedCreateBankAccountAPIRequest",
"PlaidCreateBankAccountAPIRequest",
"ExternallyVerifiedCreateBankAccountAPIRequest",
+ "UnverifiedCreateBankAccountAPIRequest",
]
@@ -177,8 +178,66 @@ class ExternallyVerifiedCreateBankAccountAPIRequest(TypedDict, total=False):
"""User Defined ID"""
+class UnverifiedCreateBankAccountAPIRequest(TypedDict, total=False):
+ account_number: Required[str]
+ """Account Number"""
+
+ country: Required[str]
+ """The country that the bank account is located in using ISO 3166-1.
+
+ We will only accept USA bank accounts e.g., USA
+ """
+
+ currency: Required[str]
+ """currency of the external account 3-character alphabetic ISO 4217 code"""
+
+ owner: Required[str]
+ """Legal Name of the business or individual who owns the external account.
+
+ This will appear in statements
+ """
+
+ owner_type: Required[OwnerType]
+ """Owner Type"""
+
+ routing_number: Required[str]
+ """Routing Number"""
+
+ type: Required[Literal["CHECKING", "SAVINGS"]]
+ """Account Type"""
+
+ verification_method: Required[Literal["UNVERIFIED"]]
+ """Verification Method"""
+
+ account_token: str
+ """Indicates which Lithic account the external account is associated with.
+
+ For external accounts that are associated with the program, account_token field
+ returned will be null
+ """
+
+ address: ExternalBankAccountAddressParam
+ """Address"""
+
+ company_id: str
+ """Optional field that helps identify bank accounts in receipts"""
+
+ dob: Annotated[Union[str, date], PropertyInfo(format="iso8601")]
+ """Date of Birth of the Individual that owns the external bank account"""
+
+ doing_business_as: str
+ """Doing Business As"""
+
+ name: str
+ """The nickname for this External Bank Account"""
+
+ user_defined_id: str
+ """User Defined ID"""
+
+
ExternalBankAccountCreateParams: TypeAlias = Union[
BankVerifiedCreateBankAccountAPIRequest,
PlaidCreateBankAccountAPIRequest,
ExternallyVerifiedCreateBankAccountAPIRequest,
+ UnverifiedCreateBankAccountAPIRequest,
]
diff --git a/src/lithic/types/financial_accounts/statements/statement_line_items.py b/src/lithic/types/financial_accounts/statements/statement_line_items.py
index 069b1881..7e5e4c38 100644
--- a/src/lithic/types/financial_accounts/statements/statement_line_items.py
+++ b/src/lithic/types/financial_accounts/statements/statement_line_items.py
@@ -67,6 +67,7 @@ class Data(BaseModel):
"CASH_BACK",
"CASH_BACK_REVERSAL",
"CLEARING",
+ "COLLECTION",
"CORRECTION_CREDIT",
"CORRECTION_DEBIT",
"CREDIT_AUTHORIZATION",
diff --git a/src/lithic/types/financial_transaction.py b/src/lithic/types/financial_transaction.py
index 0865928d..07249cb9 100644
--- a/src/lithic/types/financial_transaction.py
+++ b/src/lithic/types/financial_transaction.py
@@ -52,6 +52,7 @@ class Event(BaseModel):
"CASH_BACK",
"CASH_BACK_REVERSAL",
"CLEARING",
+ "COLLECTION",
"CORRECTION_CREDIT",
"CORRECTION_DEBIT",
"CREDIT_AUTHORIZATION",
diff --git a/src/lithic/types/fraud/__init__.py b/src/lithic/types/fraud/__init__.py
new file mode 100644
index 00000000..17325491
--- /dev/null
+++ b/src/lithic/types/fraud/__init__.py
@@ -0,0 +1,7 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from .transaction_report_params import TransactionReportParams as TransactionReportParams
+from .transaction_report_response import TransactionReportResponse as TransactionReportResponse
+from .transaction_retrieve_response import TransactionRetrieveResponse as TransactionRetrieveResponse
diff --git a/src/lithic/types/fraud/transaction_report_params.py b/src/lithic/types/fraud/transaction_report_params.py
new file mode 100644
index 00000000..997d066e
--- /dev/null
+++ b/src/lithic/types/fraud/transaction_report_params.py
@@ -0,0 +1,57 @@
+# 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__ = ["TransactionReportParams"]
+
+
+class TransactionReportParams(TypedDict, total=False):
+ fraud_status: Required[Literal["SUSPECTED_FRAUD", "FRAUDULENT", "NOT_FRAUDULENT"]]
+ """
+ The fraud status of the transaction, string (enum) supporting the following
+ values:
+
+ - `SUSPECTED_FRAUD`: The transaction is suspected to be fraudulent, but this
+ hasn’t been confirmed.
+ - `FRAUDULENT`: The transaction is confirmed to be fraudulent. A transaction may
+ immediately be moved into this state, or be graduated into this state from the
+ `SUSPECTED_FRAUD` state.
+ - `NOT_FRAUDULENT`: The transaction is (explicitly) marked as not fraudulent. A
+ transaction may immediately be moved into this state, or be graduated into
+ this state from the `SUSPECTED_FRAUD` state.
+ """
+
+ comment: str
+ """
+ Optional field providing additional information or context about why the
+ transaction is considered fraudulent.
+ """
+
+ fraud_type: Literal[
+ "FIRST_PARTY_FRAUD", "ACCOUNT_TAKEOVER", "CARD_COMPROMISED", "IDENTITY_THEFT", "CARDHOLDER_MANIPULATION"
+ ]
+ """
+ Specifies the type or category of fraud that the transaction is suspected or
+ confirmed to involve, string (enum) supporting the following values:
+
+ - `FIRST_PARTY_FRAUD`: First-party fraud occurs when a legitimate account or
+ cardholder intentionally misuses financial services for personal gain. This
+ includes actions such as disputing legitimate transactions to obtain a refund,
+ abusing return policies, or defaulting on credit obligations without intent to
+ repay.
+ - `ACCOUNT_TAKEOVER`: Account takeover fraud occurs when a fraudster gains
+ unauthorized access to an existing account, modifies account settings, and
+ carries out fraudulent transactions.
+ - `CARD_COMPROMISED`: Card compromised fraud occurs when a fraudster gains
+ access to card details without taking over the account, such as through
+ physical card theft, cloning, or online data breaches.
+ - `IDENTITY_THEFT`: Identity theft fraud occurs when a fraudster uses stolen
+ personal information, such as Social Security numbers or addresses, to open
+ accounts, apply for loans, or conduct financial transactions in someone's
+ name.
+ - `CARDHOLDER_MANIPULATION`: This type of fraud occurs when a fraudster
+ manipulates or coerces a legitimate cardholder into unauthorized transactions,
+ often through social engineering tactics.
+ """
diff --git a/src/lithic/types/fraud/transaction_report_response.py b/src/lithic/types/fraud/transaction_report_response.py
new file mode 100644
index 00000000..e0ec20f2
--- /dev/null
+++ b/src/lithic/types/fraud/transaction_report_response.py
@@ -0,0 +1,73 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+from datetime import datetime
+from typing_extensions import Literal
+
+from ..._models import BaseModel
+
+__all__ = ["TransactionReportResponse"]
+
+
+class TransactionReportResponse(BaseModel):
+ fraud_status: Literal["SUSPECTED_FRAUD", "FRAUDULENT", "NOT_FRAUDULENT", "NO_REPORTED_FRAUD"]
+ """
+ The fraud status of the transaction, string (enum) supporting the following
+ values:
+
+ - `SUSPECTED_FRAUD`: The transaction is suspected to be fraudulent, but this
+ hasn’t been confirmed.
+ - `FRAUDULENT`: The transaction is confirmed to be fraudulent. A transaction may
+ immediately be moved into this state, or be graduated into this state from the
+ `SUSPECTED_FRAUD` state.
+ - `NOT_FRAUDULENT`: The transaction is (explicitly) marked as not fraudulent. A
+ transaction may immediately be moved into this state, or be graduated into
+ this state from the `SUSPECTED_FRAUD` state.
+ - `NO_REPORTED_FRAUD`: Indicates that no fraud report exists for the
+ transaction. It is the default state for transactions that have not been
+ analyzed or associated with any known fraudulent activity.
+ """
+
+ transaction_token: str
+ """
+ The universally unique identifier (UUID) associated with the transaction being
+ reported.
+ """
+
+ comment: Optional[str] = None
+ """Provides additional context or details about the fraud report."""
+
+ created_at: Optional[datetime] = None
+ """Timestamp representing when the fraud report was created."""
+
+ fraud_type: Optional[
+ Literal[
+ "FIRST_PARTY_FRAUD", "ACCOUNT_TAKEOVER", "CARD_COMPROMISED", "IDENTITY_THEFT", "CARDHOLDER_MANIPULATION"
+ ]
+ ] = None
+ """
+ Specifies the type or category of fraud that the transaction is suspected or
+ confirmed to involve, string (enum) supporting the following values:
+
+ - `FIRST_PARTY_FRAUD`: First-party fraud occurs when a legitimate account or
+ cardholder intentionally misuses financial services for personal gain. This
+ includes actions such as disputing legitimate transactions to obtain a refund,
+ abusing return policies, or defaulting on credit obligations without intent to
+ repay.
+ - `ACCOUNT_TAKEOVER`: Account takeover fraud occurs when a fraudster gains
+ unauthorized access to an existing account, modifies account settings, and
+ carries out fraudulent transactions.
+ - `CARD_COMPROMISED`: Card compromised fraud occurs when a fraudster gains
+ access to card details without taking over the account, such as through
+ physical card theft, cloning, or online data breaches.
+ - `IDENTITY_THEFT`: Identity theft fraud occurs when a fraudster uses stolen
+ personal information, such as Social Security numbers or addresses, to open
+ accounts, apply for loans, or conduct financial transactions in someone's
+ name.
+ - `CARDHOLDER_MANIPULATION`: This type of fraud occurs when a fraudster
+ manipulates or coerces a legitimate cardholder into unauthorized transactions,
+ often through social engineering tactics.
+ """
+
+ updated_at: Optional[datetime] = None
+ """Timestamp representing the last update to the fraud report."""
diff --git a/src/lithic/types/fraud/transaction_retrieve_response.py b/src/lithic/types/fraud/transaction_retrieve_response.py
new file mode 100644
index 00000000..9e740279
--- /dev/null
+++ b/src/lithic/types/fraud/transaction_retrieve_response.py
@@ -0,0 +1,73 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+from datetime import datetime
+from typing_extensions import Literal
+
+from ..._models import BaseModel
+
+__all__ = ["TransactionRetrieveResponse"]
+
+
+class TransactionRetrieveResponse(BaseModel):
+ fraud_status: Literal["SUSPECTED_FRAUD", "FRAUDULENT", "NOT_FRAUDULENT", "NO_REPORTED_FRAUD"]
+ """
+ The fraud status of the transaction, string (enum) supporting the following
+ values:
+
+ - `SUSPECTED_FRAUD`: The transaction is suspected to be fraudulent, but this
+ hasn’t been confirmed.
+ - `FRAUDULENT`: The transaction is confirmed to be fraudulent. A transaction may
+ immediately be moved into this state, or be graduated into this state from the
+ `SUSPECTED_FRAUD` state.
+ - `NOT_FRAUDULENT`: The transaction is (explicitly) marked as not fraudulent. A
+ transaction may immediately be moved into this state, or be graduated into
+ this state from the `SUSPECTED_FRAUD` state.
+ - `NO_REPORTED_FRAUD`: Indicates that no fraud report exists for the
+ transaction. It is the default state for transactions that have not been
+ analyzed or associated with any known fraudulent activity.
+ """
+
+ transaction_token: str
+ """
+ The universally unique identifier (UUID) associated with the transaction being
+ reported.
+ """
+
+ comment: Optional[str] = None
+ """Provides additional context or details about the fraud report."""
+
+ created_at: Optional[datetime] = None
+ """Timestamp representing when the fraud report was created."""
+
+ fraud_type: Optional[
+ Literal[
+ "FIRST_PARTY_FRAUD", "ACCOUNT_TAKEOVER", "CARD_COMPROMISED", "IDENTITY_THEFT", "CARDHOLDER_MANIPULATION"
+ ]
+ ] = None
+ """
+ Specifies the type or category of fraud that the transaction is suspected or
+ confirmed to involve, string (enum) supporting the following values:
+
+ - `FIRST_PARTY_FRAUD`: First-party fraud occurs when a legitimate account or
+ cardholder intentionally misuses financial services for personal gain. This
+ includes actions such as disputing legitimate transactions to obtain a refund,
+ abusing return policies, or defaulting on credit obligations without intent to
+ repay.
+ - `ACCOUNT_TAKEOVER`: Account takeover fraud occurs when a fraudster gains
+ unauthorized access to an existing account, modifies account settings, and
+ carries out fraudulent transactions.
+ - `CARD_COMPROMISED`: Card compromised fraud occurs when a fraudster gains
+ access to card details without taking over the account, such as through
+ physical card theft, cloning, or online data breaches.
+ - `IDENTITY_THEFT`: Identity theft fraud occurs when a fraudster uses stolen
+ personal information, such as Social Security numbers or addresses, to open
+ accounts, apply for loans, or conduct financial transactions in someone's
+ name.
+ - `CARDHOLDER_MANIPULATION`: This type of fraud occurs when a fraudster
+ manipulates or coerces a legitimate cardholder into unauthorized transactions,
+ often through social engineering tactics.
+ """
+
+ updated_at: Optional[datetime] = None
+ """Timestamp representing the last update to the fraud report."""
diff --git a/src/lithic/types/payment.py b/src/lithic/types/payment.py
index 37171345..644537e5 100644
--- a/src/lithic/types/payment.py
+++ b/src/lithic/types/payment.py
@@ -91,6 +91,8 @@ class MethodAttributes(BaseModel):
trace_numbers: List[Optional[str]]
+ addenda: Optional[str] = None
+
class Payment(BaseModel):
token: str
diff --git a/src/lithic/types/payment_create_params.py b/src/lithic/types/payment_create_params.py
index 97e65835..33bd7c7f 100644
--- a/src/lithic/types/payment_create_params.py
+++ b/src/lithic/types/payment_create_params.py
@@ -2,6 +2,7 @@
from __future__ import annotations
+from typing import Optional
from typing_extensions import Literal, Required, TypedDict
__all__ = ["PaymentCreateParams", "MethodAttributes"]
@@ -33,3 +34,5 @@ class PaymentCreateParams(TypedDict, total=False):
class MethodAttributes(TypedDict, total=False):
sec_code: Required[Literal["CCD", "PPD", "WEB"]]
+
+ addenda: Optional[str]
diff --git a/src/lithic/types/three_ds/authentication_retrieve_response.py b/src/lithic/types/three_ds/authentication_retrieve_response.py
index 6662cafd..98e22a19 100644
--- a/src/lithic/types/three_ds/authentication_retrieve_response.py
+++ b/src/lithic/types/three_ds/authentication_retrieve_response.py
@@ -73,7 +73,7 @@ class Cardholder(BaseModel):
Indicates whether the shipping address and billing address provided by the
cardholder are the same. This value - and assessment of whether the addresses
match - is provided directly in the 3DS request and is not determined by Lithic.
- Maps to EMV 3DS field addrMatch.
+ Maps to EMV 3DS field `addrMatch`.
"""
billing_address: Optional[CardholderBillingAddress] = None
@@ -82,28 +82,28 @@ class Cardholder(BaseModel):
email: Optional[str] = None
"""
Email address that is either provided by the cardholder or is on file with the
- merchant in a 3RI request. Maps to EMV 3DS field email.
+ merchant in a 3RI request. Maps to EMV 3DS field `email`.
"""
name: Optional[str] = None
- """Name of the cardholder. Maps to EMV 3DS field cardholderName."""
+ """Name of the cardholder. Maps to EMV 3DS field `cardholderName`."""
phone_number_home: Optional[str] = None
"""Home phone number provided by the cardholder.
- Maps to EMV 3DS fields homePhone.cc and homePhone.subscriber.
+ Maps to EMV 3DS fields `homePhone.cc` and `homePhone.subscriber`.
"""
phone_number_mobile: Optional[str] = None
"""Mobile/cell phone number provided by the cardholder.
- Maps to EMV 3DS fields mobilePhone.cc and mobilePhone.subscriber.
+ Maps to EMV 3DS fields `mobilePhone.cc` and `mobilePhone.subscriber`.
"""
phone_number_work: Optional[str] = None
"""Work phone number provided by the cardholder.
- Maps to EMV 3DS fields workPhone.cc and workPhone.subscriber.
+ Maps to EMV 3DS fields `workPhone.cc` and `workPhone.subscriber`.
"""
shipping_address: Optional[CardholderShippingAddress] = None
@@ -114,7 +114,7 @@ class MerchantRiskIndicator(BaseModel):
delivery_email_address: Optional[str] = None
"""
In transactions with electronic delivery, email address to which merchandise is
- delivered. Maps to EMV 3DS field deliveryEmailAddress.
+ delivered. Maps to EMV 3DS field `deliveryEmailAddress`.
"""
delivery_time_frame: Optional[
@@ -122,44 +122,46 @@ class MerchantRiskIndicator(BaseModel):
] = None
"""The delivery time frame for the merchandise.
- Maps to EMV 3DS field deliveryTimeframe.
+ Maps to EMV 3DS field `deliveryTimeframe`.
"""
gift_card_amount: Optional[int] = None
"""
In prepaid or gift card purchase transactions, purchase amount total in major
units (e.g., a purchase of USD $205.10 would be 205). Maps to EMV 3DS field
- giftCardAmount.
+ `giftCardAmount`.
"""
gift_card_count: Optional[int] = None
"""
In prepaid or gift card purchase transactions, count of individual prepaid or
- gift cards/codes purchased. Maps to EMV 3DS field giftCardCount.
+ gift cards/codes purchased. Maps to EMV 3DS field `giftCardCount`.
"""
gift_card_currency: Optional[str] = None
"""In prepaid or gift card purchase transactions, currency code of the gift card.
- Maps to EMV 3DS field giftCardCurr.
+ Maps to EMV 3DS field `giftCardCurr`. Permitted values: ISO 4217 three-character
+ currency code (e.g., USD).
"""
order_availability: Optional[Literal["FUTURE_AVAILABILITY", "MERCHANDISE_AVAILABLE"]] = None
"""
Indicates whether the purchase is for merchandise that is available now or at a
- future date. Maps to EMV 3DS field preOrderPurchaseInd.
+ future date. Maps to EMV 3DS field `preOrderPurchaseInd`.
"""
pre_order_available_date: Optional[datetime] = None
"""
In pre-order purchase transactions, the expected date that the merchandise will
- be available. Maps to EMV 3DS field preOrderDate.
+ be available. Maps to EMV 3DS field `preOrderDate`. Permitted values: Date
+ string in the ISO 8601 format yyyy-MM-dd'T'hh:mm:ssZ
"""
reorder_items: Optional[Literal["FIRST_TIME_ORDERED", "REORDERED"]] = None
"""Indicates whether the cardholder is reordering previously purchased merchandise.
- Maps to EMV 3DS field reorderItemsInd.
+ Maps to EMV 3DS field `reorderItemsInd`.
"""
shipping_method: Optional[
@@ -179,7 +181,8 @@ class MerchantRiskIndicator(BaseModel):
If purchase includes one or more item, this indicator is used for the physical
goods; if the purchase only includes digital goods, this indicator is used to
- describe the most expensive item purchased. Maps to EMV 3DS field shipIndicator.
+ describe the most expensive item purchased. Maps to EMV 3DS field
+ `shipIndicator`.
"""
@@ -187,23 +190,24 @@ class Merchant(BaseModel):
id: str
"""Merchant identifier as assigned by the acquirer.
- Maps to EMV 3DS field acquirerMerchantId.
+ Maps to EMV 3DS field `acquirerMerchantId`.
"""
country: str
"""Country code of the merchant requesting 3DS authentication.
- Maps to EMV 3DS field merchantCountryCode.
+ Maps to EMV 3DS field `merchantCountryCode`. Permitted values: ISO 3166-1
+ alpha-3 country code (e.g., USA).
"""
mcc: str
"""
Merchant category code assigned to the merchant that describes its business
- activity type. Maps to EMV 3DS field mcc.
+ activity type. Maps to EMV 3DS field `mcc`.
"""
name: str
- """Name of the merchant. Maps to EMV 3DS field merchantName."""
+ """Name of the merchant. Maps to EMV 3DS field `merchantName`."""
risk_indicator: MerchantRiskIndicator
"""
@@ -222,7 +226,8 @@ class AdditionalData(BaseModel):
network_risk_score: Optional[int] = None
"""
Mastercard only: Assessment by the network of the authentication risk level,
- with a higher value indicating a higher amount of risk.
+ with a higher value indicating a higher amount of risk. Permitted values:
+ Integer between 0-950, in increments of 50.
"""
@@ -230,51 +235,60 @@ class App(BaseModel):
device_info: Optional[str] = None
"""
Device information gathered from the cardholder's device - JSON name/value pairs
- that is Base64url encoded. Maps to EMV 3DS field deviceInfo.
+ that is Base64url encoded. Maps to EMV 3DS field `deviceInfo`.
"""
ip: Optional[str] = None
"""External IP address used by the app generating the 3DS authentication request.
- Maps to EMV 3DS field appIp.
+ Maps to EMV 3DS field `appIp`.
"""
class Browser(BaseModel):
+ accept_header: Optional[str] = None
+ """
+ Content of the HTTP accept headers as sent from the cardholder's browser to the
+ 3DS requestor (e.g., merchant or digital wallet).
+ """
+
ip: Optional[str] = None
"""
IP address of the browser as returned by the HTTP headers to the 3DS requestor
- (e.g., merchant or digital wallet). Maps to EMV 3DS field browserIP.
+ (e.g., merchant or digital wallet). Maps to EMV 3DS field `browserIP`.
"""
java_enabled: Optional[bool] = None
"""Indicates whether the cardholder's browser has the ability to execute Java.
- Maps to EMV 3DS field browserJavaEnabled.
+ Maps to EMV 3DS field `browserJavaEnabled`.
"""
javascript_enabled: Optional[bool] = None
"""Indicates whether the cardholder's browser has the ability to execute
JavaScript.
- Maps to EMV 3DS field browserJavascriptEnabled.
+ Maps to EMV 3DS field `browserJavascriptEnabled`.
"""
language: Optional[str] = None
"""Language of the cardholder's browser as defined in IETF BCP47.
- Maps to EMV 3DS field browserLanguage.
+ Maps to EMV 3DS field `browserLanguage`.
"""
time_zone: Optional[str] = None
"""
Time zone of the cardholder's browser offset in minutes between UTC and the
cardholder browser's local time. The offset is positive if the local time is
- behind UTC and negative if it is ahead. Maps to EMV 3DS field browserTz.
+ behind UTC and negative if it is ahead. Maps to EMV 3DS field `browserTz`.
"""
user_agent: Optional[str] = None
- """Content of the HTTP user-agent header. Maps to EMV 3DS field browserUserAgent."""
+ """Content of the HTTP user-agent header.
+
+ Maps to EMV 3DS field `browserUserAgent`.
+ """
class ChallengeMetadata(BaseModel):
@@ -289,7 +303,7 @@ class Transaction(BaseModel):
amount: float
"""Amount of the purchase in minor units of currency with all punctuation removed.
- Maps to EMV 3DS field purchaseAmount.
+ Maps to EMV 3DS field `purchaseAmount`.
"""
cardholder_amount: Optional[float] = None
@@ -299,18 +313,23 @@ class Transaction(BaseModel):
"""
currency: str
- """Currency of the purchase. Maps to EMV 3DS field purchaseCurrency."""
+ """Currency of the purchase.
+
+ Maps to EMV 3DS field `purchaseCurrency`. Permitted values: ISO 4217
+ three-character currency code (e.g., USD).
+ """
currency_exponent: float
"""Minor units of currency, as specified in ISO 4217 currency exponent.
- Maps to EMV 3DS field purchaseExponent.
+ Maps to EMV 3DS field `purchaseExponent`.
"""
date_time: datetime
"""
Date and time when the authentication was generated by the merchant/acquirer's
- 3DS server. Maps to EMV 3DS field purchaseDate.
+ 3DS server. Maps to EMV 3DS field `purchaseDate`. Permitted values: Date string
+ in the ISO 8601 format yyyy-MM-dd'T'hh:mm:ssZ.
"""
type: Optional[
@@ -324,13 +343,16 @@ class Transaction(BaseModel):
] = None
"""Type of the transaction for which a 3DS authentication request is occurring.
- Maps to EMV 3DS field transType.
+ Maps to EMV 3DS field `transType`.
"""
class AuthenticationRetrieveResponse(BaseModel):
token: str
- """Globally unique identifier for the 3DS authentication."""
+ """Globally unique identifier for the 3DS authentication.
+
+ Permitted values: 36-digit version 4 UUID (including hyphens).
+ """
account_type: Optional[Literal["CREDIT", "DEBIT", "NOT_APPLICABLE"]] = None
"""Type of account/card that is being used for the transaction.
@@ -350,7 +372,7 @@ class AuthenticationRetrieveResponse(BaseModel):
card_token: str
"""
Globally unique identifier for the card on which the 3DS authentication has
- occurred.
+ occurred. Permitted values: 36-digit version 4 UUID (including hyphens).
"""
cardholder: Cardholder
@@ -359,11 +381,14 @@ class AuthenticationRetrieveResponse(BaseModel):
channel: Literal["APP_BASED", "BROWSER", "THREE_DS_REQUESTOR_INITIATED"]
"""Channel in which the authentication occurs.
- Maps to EMV 3DS field deviceChannel.
+ Maps to EMV 3DS field `deviceChannel`.
"""
created: datetime
- """Date and time when the authentication was created in Lithic's system."""
+ """Date and time when the authentication was created in Lithic's system.
+
+ Permitted values: Date string in the ISO 8601 format yyyy-MM-dd'T'hh:mm:ssZ.
+ """
merchant: Merchant
"""
@@ -429,7 +454,7 @@ class AuthenticationRetrieveResponse(BaseModel):
"""
Type of authentication request - i.e., the type of transaction or interaction is
causing the merchant to request an authentication. Maps to EMV 3DS field
- threeDSRequestorAuthenticationInd.
+ `threeDSRequestorAuthenticationInd`.
"""
browser: Optional[Browser] = None
@@ -439,15 +464,26 @@ class AuthenticationRetrieveResponse(BaseModel):
"""
challenge_metadata: Optional[ChallengeMetadata] = None
- """Metadata about the challenge method and delivery."""
+ """Metadata about the challenge method and delivery.
+
+ Only present when a challenge is triggered.
+ """
challenge_orchestrated_by: Optional[Literal["LITHIC", "CUSTOMER", "NO_CHALLENGE"]] = None
- """Entity that orchestrates the challenge."""
+ """Entity that orchestrates the challenge.
- decision_made_by: Optional[Literal["CUSTOMER_ENDPOINT", "LITHIC_DEFAULT", "LITHIC_RULES", "NETWORK", "UNKNOWN"]] = (
- None
- )
- """Entity that made the authentication decision."""
+ This won't be set for authentications for which a decision has not yet been made
+ (e.g. in-flight customer decisioning request).
+ """
+
+ decision_made_by: Optional[
+ Literal["LITHIC_RULES", "LITHIC_DEFAULT", "CUSTOMER_RULES", "CUSTOMER_ENDPOINT", "NETWORK", "UNKNOWN"]
+ ] = None
+ """Entity that made the authentication decision.
+
+ This won't be set for authentications for which a decision has not yet been made
+ (e.g. in-flight customer decisioning request).
+ """
three_ri_request_type: Optional[
Literal[
@@ -470,11 +506,11 @@ class AuthenticationRetrieveResponse(BaseModel):
]
] = None
"""
- Type of 3DS Requestor Initiated (3RI) request i.e., a 3DS authentication that
+ Type of 3DS Requestor Initiated (3RI) request — i.e., a 3DS authentication that
takes place at the initiation of the merchant rather than the cardholder. The
most common example of this is where a merchant is authenticating before billing
for a recurring transaction such as a pay TV subscription or a utility bill.
- Maps to EMV 3DS field threeRIInd.
+ Maps to EMV 3DS field `threeRIInd`.
"""
transaction: Optional[Transaction] = None
diff --git a/src/lithic/types/three_ds/authentication_simulate_params.py b/src/lithic/types/three_ds/authentication_simulate_params.py
index 67030433..da9488ef 100644
--- a/src/lithic/types/three_ds/authentication_simulate_params.py
+++ b/src/lithic/types/three_ds/authentication_simulate_params.py
@@ -9,11 +9,13 @@
class AuthenticationSimulateParams(TypedDict, total=False):
merchant: Required[Merchant]
+ """Merchant information for the simulated transaction"""
pan: Required[str]
"""Sixteen digit card number."""
transaction: Required[Transaction]
+ """Transaction details for the simulation"""
card_expiry_check: Literal["MATCH", "MISMATCH", "NOT_PRESENT"]
"""When set will use the following values as part of the Simulated Authentication.
diff --git a/src/lithic/types/three_ds/authentication_simulate_response.py b/src/lithic/types/three_ds/authentication_simulate_response.py
index 3eeeae26..2c376db6 100644
--- a/src/lithic/types/three_ds/authentication_simulate_response.py
+++ b/src/lithic/types/three_ds/authentication_simulate_response.py
@@ -9,7 +9,4 @@
class AuthenticationSimulateResponse(BaseModel):
token: Optional[str] = None
- """
- A unique token to reference this transaction with later calls to void or clear
- the authorization.
- """
+ """Globally unique identifier for the 3DS authentication."""
diff --git a/src/lithic/types/three_ds/decisioning_challenge_response_params.py b/src/lithic/types/three_ds/decisioning_challenge_response_params.py
index b68305a5..f6ba5df5 100644
--- a/src/lithic/types/three_ds/decisioning_challenge_response_params.py
+++ b/src/lithic/types/three_ds/decisioning_challenge_response_params.py
@@ -11,12 +11,10 @@
class DecisioningChallengeResponseParams(TypedDict, total=False):
token: Required[str]
- """Globally unique identifier for the 3DS authentication.
-
- This token is sent as part of the initial 3DS Decisioning Request and as part of
- the 3DS Challenge Event in the
- [ThreeDSAuthentication](#/components/schemas/ThreeDSAuthentication) object
+ """
+ Globally unique identifier for 3DS Authentication that resulted in
+ PENDING_CHALLENGE authentication result.
"""
challenge_response: Required[ChallengeResult]
- """Whether the Cardholder has Approved or Declined the issued Challenge"""
+ """Whether the Cardholder has approved or declined the issued Challenge"""
diff --git a/tests/api_resources/auth_rules/test_v2.py b/tests/api_resources/auth_rules/test_v2.py
index 00505421..92fe418a 100644
--- a/tests/api_resources/auth_rules/test_v2.py
+++ b/tests/api_resources/auth_rules/test_v2.py
@@ -9,6 +9,7 @@
from lithic import Lithic, AsyncLithic
from tests.utils import assert_matches_type
+from lithic._utils import parse_date
from lithic.pagination import SyncCursorPage, AsyncCursorPage
from lithic.types.auth_rules import (
V2ListResponse,
@@ -19,6 +20,7 @@
V2UpdateResponse,
V2PromoteResponse,
V2RetrieveResponse,
+ V2RetrieveReportResponse,
)
# pyright: reportDeprecated=false
@@ -682,16 +684,19 @@ def test_path_params_promote(self, client: Lithic) -> None:
@parametrize
def test_method_report(self, client: Lithic) -> None:
- v2 = client.auth_rules.v2.report(
- "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- )
+ with pytest.warns(DeprecationWarning):
+ v2 = client.auth_rules.v2.report(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
assert_matches_type(V2ReportResponse, v2, path=["response"])
@parametrize
def test_raw_response_report(self, client: Lithic) -> None:
- response = client.auth_rules.v2.with_raw_response.report(
- "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- )
+ with pytest.warns(DeprecationWarning):
+ response = client.auth_rules.v2.with_raw_response.report(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -700,22 +705,70 @@ def test_raw_response_report(self, client: Lithic) -> None:
@parametrize
def test_streaming_response_report(self, client: Lithic) -> None:
- with client.auth_rules.v2.with_streaming_response.report(
- "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ with pytest.warns(DeprecationWarning):
+ with client.auth_rules.v2.with_streaming_response.report(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ v2 = response.parse()
+ assert_matches_type(V2ReportResponse, v2, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_report(self, client: Lithic) -> None:
+ with pytest.warns(DeprecationWarning):
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `auth_rule_token` but received ''"):
+ client.auth_rules.v2.with_raw_response.report(
+ "",
+ )
+
+ @parametrize
+ def test_method_retrieve_report(self, client: Lithic) -> None:
+ v2 = client.auth_rules.v2.retrieve_report(
+ auth_rule_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ begin=parse_date("2019-12-27"),
+ end=parse_date("2019-12-27"),
+ )
+ assert_matches_type(V2RetrieveReportResponse, v2, path=["response"])
+
+ @parametrize
+ def test_raw_response_retrieve_report(self, client: Lithic) -> None:
+ response = client.auth_rules.v2.with_raw_response.retrieve_report(
+ auth_rule_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ begin=parse_date("2019-12-27"),
+ end=parse_date("2019-12-27"),
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ v2 = response.parse()
+ assert_matches_type(V2RetrieveReportResponse, v2, path=["response"])
+
+ @parametrize
+ def test_streaming_response_retrieve_report(self, client: Lithic) -> None:
+ with client.auth_rules.v2.with_streaming_response.retrieve_report(
+ auth_rule_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ begin=parse_date("2019-12-27"),
+ end=parse_date("2019-12-27"),
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
v2 = response.parse()
- assert_matches_type(V2ReportResponse, v2, path=["response"])
+ assert_matches_type(V2RetrieveReportResponse, v2, path=["response"])
assert cast(Any, response.is_closed) is True
@parametrize
- def test_path_params_report(self, client: Lithic) -> None:
+ def test_path_params_retrieve_report(self, client: Lithic) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `auth_rule_token` but received ''"):
- client.auth_rules.v2.with_raw_response.report(
- "",
+ client.auth_rules.v2.with_raw_response.retrieve_report(
+ auth_rule_token="",
+ begin=parse_date("2019-12-27"),
+ end=parse_date("2019-12-27"),
)
@@ -1377,16 +1430,19 @@ async def test_path_params_promote(self, async_client: AsyncLithic) -> None:
@parametrize
async def test_method_report(self, async_client: AsyncLithic) -> None:
- v2 = await async_client.auth_rules.v2.report(
- "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- )
+ with pytest.warns(DeprecationWarning):
+ v2 = await async_client.auth_rules.v2.report(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
assert_matches_type(V2ReportResponse, v2, path=["response"])
@parametrize
async def test_raw_response_report(self, async_client: AsyncLithic) -> None:
- response = await async_client.auth_rules.v2.with_raw_response.report(
- "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- )
+ with pytest.warns(DeprecationWarning):
+ response = await async_client.auth_rules.v2.with_raw_response.report(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -1395,20 +1451,68 @@ async def test_raw_response_report(self, async_client: AsyncLithic) -> None:
@parametrize
async def test_streaming_response_report(self, async_client: AsyncLithic) -> None:
- async with async_client.auth_rules.v2.with_streaming_response.report(
- "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ with pytest.warns(DeprecationWarning):
+ async with async_client.auth_rules.v2.with_streaming_response.report(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ v2 = await response.parse()
+ assert_matches_type(V2ReportResponse, v2, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_report(self, async_client: AsyncLithic) -> None:
+ with pytest.warns(DeprecationWarning):
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `auth_rule_token` but received ''"):
+ await async_client.auth_rules.v2.with_raw_response.report(
+ "",
+ )
+
+ @parametrize
+ async def test_method_retrieve_report(self, async_client: AsyncLithic) -> None:
+ v2 = await async_client.auth_rules.v2.retrieve_report(
+ auth_rule_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ begin=parse_date("2019-12-27"),
+ end=parse_date("2019-12-27"),
+ )
+ assert_matches_type(V2RetrieveReportResponse, v2, path=["response"])
+
+ @parametrize
+ async def test_raw_response_retrieve_report(self, async_client: AsyncLithic) -> None:
+ response = await async_client.auth_rules.v2.with_raw_response.retrieve_report(
+ auth_rule_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ begin=parse_date("2019-12-27"),
+ end=parse_date("2019-12-27"),
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ v2 = response.parse()
+ assert_matches_type(V2RetrieveReportResponse, v2, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_retrieve_report(self, async_client: AsyncLithic) -> None:
+ async with async_client.auth_rules.v2.with_streaming_response.retrieve_report(
+ auth_rule_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ begin=parse_date("2019-12-27"),
+ end=parse_date("2019-12-27"),
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
v2 = await response.parse()
- assert_matches_type(V2ReportResponse, v2, path=["response"])
+ assert_matches_type(V2RetrieveReportResponse, v2, path=["response"])
assert cast(Any, response.is_closed) is True
@parametrize
- async def test_path_params_report(self, async_client: AsyncLithic) -> None:
+ async def test_path_params_retrieve_report(self, async_client: AsyncLithic) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `auth_rule_token` but received ''"):
- await async_client.auth_rules.v2.with_raw_response.report(
- "",
+ await async_client.auth_rules.v2.with_raw_response.retrieve_report(
+ auth_rule_token="",
+ begin=parse_date("2019-12-27"),
+ end=parse_date("2019-12-27"),
)
diff --git a/tests/api_resources/fraud/__init__.py b/tests/api_resources/fraud/__init__.py
new file mode 100644
index 00000000..fd8019a9
--- /dev/null
+++ b/tests/api_resources/fraud/__init__.py
@@ -0,0 +1 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
diff --git a/tests/api_resources/fraud/test_transactions.py b/tests/api_resources/fraud/test_transactions.py
new file mode 100644
index 00000000..6bd76dc0
--- /dev/null
+++ b/tests/api_resources/fraud/test_transactions.py
@@ -0,0 +1,204 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+import os
+from typing import Any, cast
+
+import pytest
+
+from lithic import Lithic, AsyncLithic
+from tests.utils import assert_matches_type
+from lithic.types.fraud import TransactionReportResponse, TransactionRetrieveResponse
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestTransactions:
+ parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @parametrize
+ def test_method_retrieve(self, client: Lithic) -> None:
+ transaction = client.fraud.transactions.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(TransactionRetrieveResponse, transaction, path=["response"])
+
+ @parametrize
+ def test_raw_response_retrieve(self, client: Lithic) -> None:
+ response = client.fraud.transactions.with_raw_response.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ transaction = response.parse()
+ assert_matches_type(TransactionRetrieveResponse, transaction, path=["response"])
+
+ @parametrize
+ def test_streaming_response_retrieve(self, client: Lithic) -> None:
+ with client.fraud.transactions.with_streaming_response.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ transaction = response.parse()
+ assert_matches_type(TransactionRetrieveResponse, transaction, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_retrieve(self, client: Lithic) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `transaction_token` but received ''"):
+ client.fraud.transactions.with_raw_response.retrieve(
+ "",
+ )
+
+ @parametrize
+ def test_method_report(self, client: Lithic) -> None:
+ transaction = client.fraud.transactions.report(
+ transaction_token="00000000-0000-0000-0000-000000000000",
+ fraud_status="SUSPECTED_FRAUD",
+ )
+ assert_matches_type(TransactionReportResponse, transaction, path=["response"])
+
+ @parametrize
+ def test_method_report_with_all_params(self, client: Lithic) -> None:
+ transaction = client.fraud.transactions.report(
+ transaction_token="00000000-0000-0000-0000-000000000000",
+ fraud_status="SUSPECTED_FRAUD",
+ comment="comment",
+ fraud_type="FIRST_PARTY_FRAUD",
+ )
+ assert_matches_type(TransactionReportResponse, transaction, path=["response"])
+
+ @parametrize
+ def test_raw_response_report(self, client: Lithic) -> None:
+ response = client.fraud.transactions.with_raw_response.report(
+ transaction_token="00000000-0000-0000-0000-000000000000",
+ fraud_status="SUSPECTED_FRAUD",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ transaction = response.parse()
+ assert_matches_type(TransactionReportResponse, transaction, path=["response"])
+
+ @parametrize
+ def test_streaming_response_report(self, client: Lithic) -> None:
+ with client.fraud.transactions.with_streaming_response.report(
+ transaction_token="00000000-0000-0000-0000-000000000000",
+ fraud_status="SUSPECTED_FRAUD",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ transaction = response.parse()
+ assert_matches_type(TransactionReportResponse, transaction, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_report(self, client: Lithic) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `transaction_token` but received ''"):
+ client.fraud.transactions.with_raw_response.report(
+ transaction_token="",
+ fraud_status="SUSPECTED_FRAUD",
+ )
+
+
+class TestAsyncTransactions:
+ parametrize = pytest.mark.parametrize(
+ "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
+ )
+
+ @parametrize
+ async def test_method_retrieve(self, async_client: AsyncLithic) -> None:
+ transaction = await async_client.fraud.transactions.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(TransactionRetrieveResponse, transaction, path=["response"])
+
+ @parametrize
+ async def test_raw_response_retrieve(self, async_client: AsyncLithic) -> None:
+ response = await async_client.fraud.transactions.with_raw_response.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ transaction = response.parse()
+ assert_matches_type(TransactionRetrieveResponse, transaction, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_retrieve(self, async_client: AsyncLithic) -> None:
+ async with async_client.fraud.transactions.with_streaming_response.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ transaction = await response.parse()
+ assert_matches_type(TransactionRetrieveResponse, transaction, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_retrieve(self, async_client: AsyncLithic) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `transaction_token` but received ''"):
+ await async_client.fraud.transactions.with_raw_response.retrieve(
+ "",
+ )
+
+ @parametrize
+ async def test_method_report(self, async_client: AsyncLithic) -> None:
+ transaction = await async_client.fraud.transactions.report(
+ transaction_token="00000000-0000-0000-0000-000000000000",
+ fraud_status="SUSPECTED_FRAUD",
+ )
+ assert_matches_type(TransactionReportResponse, transaction, path=["response"])
+
+ @parametrize
+ async def test_method_report_with_all_params(self, async_client: AsyncLithic) -> None:
+ transaction = await async_client.fraud.transactions.report(
+ transaction_token="00000000-0000-0000-0000-000000000000",
+ fraud_status="SUSPECTED_FRAUD",
+ comment="comment",
+ fraud_type="FIRST_PARTY_FRAUD",
+ )
+ assert_matches_type(TransactionReportResponse, transaction, path=["response"])
+
+ @parametrize
+ async def test_raw_response_report(self, async_client: AsyncLithic) -> None:
+ response = await async_client.fraud.transactions.with_raw_response.report(
+ transaction_token="00000000-0000-0000-0000-000000000000",
+ fraud_status="SUSPECTED_FRAUD",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ transaction = response.parse()
+ assert_matches_type(TransactionReportResponse, transaction, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_report(self, async_client: AsyncLithic) -> None:
+ async with async_client.fraud.transactions.with_streaming_response.report(
+ transaction_token="00000000-0000-0000-0000-000000000000",
+ fraud_status="SUSPECTED_FRAUD",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ transaction = await response.parse()
+ assert_matches_type(TransactionReportResponse, transaction, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_report(self, async_client: AsyncLithic) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `transaction_token` but received ''"):
+ await async_client.fraud.transactions.with_raw_response.report(
+ transaction_token="",
+ fraud_status="SUSPECTED_FRAUD",
+ )
diff --git a/tests/api_resources/test_account_holders.py b/tests/api_resources/test_account_holders.py
index ccd60ff8..9b4c89b2 100644
--- a/tests/api_resources/test_account_holders.py
+++ b/tests/api_resources/test_account_holders.py
@@ -870,7 +870,7 @@ def test_path_params_retrieve_document(self, client: Lithic) -> None:
@parametrize
def test_method_simulate_enrollment_document_review(self, client: Lithic) -> None:
account_holder = client.account_holders.simulate_enrollment_document_review(
- document_upload_token="document_upload_token",
+ document_upload_token="b11cd67b-0a52-4180-8365-314f3def5426",
status="UPLOADED",
)
assert_matches_type(Document, account_holder, path=["response"])
@@ -878,7 +878,7 @@ def test_method_simulate_enrollment_document_review(self, client: Lithic) -> Non
@parametrize
def test_method_simulate_enrollment_document_review_with_all_params(self, client: Lithic) -> None:
account_holder = client.account_holders.simulate_enrollment_document_review(
- document_upload_token="document_upload_token",
+ document_upload_token="b11cd67b-0a52-4180-8365-314f3def5426",
status="UPLOADED",
accepted_entity_status_reasons=["string"],
status_reason="DOCUMENT_MISSING_REQUIRED_DATA",
@@ -888,7 +888,7 @@ def test_method_simulate_enrollment_document_review_with_all_params(self, client
@parametrize
def test_raw_response_simulate_enrollment_document_review(self, client: Lithic) -> None:
response = client.account_holders.with_raw_response.simulate_enrollment_document_review(
- document_upload_token="document_upload_token",
+ document_upload_token="b11cd67b-0a52-4180-8365-314f3def5426",
status="UPLOADED",
)
@@ -900,7 +900,7 @@ def test_raw_response_simulate_enrollment_document_review(self, client: Lithic)
@parametrize
def test_streaming_response_simulate_enrollment_document_review(self, client: Lithic) -> None:
with client.account_holders.with_streaming_response.simulate_enrollment_document_review(
- document_upload_token="document_upload_token",
+ document_upload_token="b11cd67b-0a52-4180-8365-314f3def5426",
status="UPLOADED",
) as response:
assert not response.is_closed
@@ -1841,7 +1841,7 @@ async def test_path_params_retrieve_document(self, async_client: AsyncLithic) ->
@parametrize
async def test_method_simulate_enrollment_document_review(self, async_client: AsyncLithic) -> None:
account_holder = await async_client.account_holders.simulate_enrollment_document_review(
- document_upload_token="document_upload_token",
+ document_upload_token="b11cd67b-0a52-4180-8365-314f3def5426",
status="UPLOADED",
)
assert_matches_type(Document, account_holder, path=["response"])
@@ -1849,7 +1849,7 @@ async def test_method_simulate_enrollment_document_review(self, async_client: As
@parametrize
async def test_method_simulate_enrollment_document_review_with_all_params(self, async_client: AsyncLithic) -> None:
account_holder = await async_client.account_holders.simulate_enrollment_document_review(
- document_upload_token="document_upload_token",
+ document_upload_token="b11cd67b-0a52-4180-8365-314f3def5426",
status="UPLOADED",
accepted_entity_status_reasons=["string"],
status_reason="DOCUMENT_MISSING_REQUIRED_DATA",
@@ -1859,7 +1859,7 @@ async def test_method_simulate_enrollment_document_review_with_all_params(self,
@parametrize
async def test_raw_response_simulate_enrollment_document_review(self, async_client: AsyncLithic) -> None:
response = await async_client.account_holders.with_raw_response.simulate_enrollment_document_review(
- document_upload_token="document_upload_token",
+ document_upload_token="b11cd67b-0a52-4180-8365-314f3def5426",
status="UPLOADED",
)
@@ -1871,7 +1871,7 @@ async def test_raw_response_simulate_enrollment_document_review(self, async_clie
@parametrize
async def test_streaming_response_simulate_enrollment_document_review(self, async_client: AsyncLithic) -> None:
async with async_client.account_holders.with_streaming_response.simulate_enrollment_document_review(
- document_upload_token="document_upload_token",
+ document_upload_token="b11cd67b-0a52-4180-8365-314f3def5426",
status="UPLOADED",
) as response:
assert not response.is_closed
diff --git a/tests/api_resources/test_cards.py b/tests/api_resources/test_cards.py
index 56149df3..b1e6026a 100644
--- a/tests/api_resources/test_cards.py
+++ b/tests/api_resources/test_cards.py
@@ -37,16 +37,16 @@ def test_method_create_with_all_params(self, client: Lithic) -> None:
card = client.cards.create(
type="VIRTUAL",
account_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- card_program_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ card_program_token="00000000-0000-0000-1000-000000000000",
carrier={"qr_code_url": "qr_code_url"},
- digital_card_art_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ digital_card_art_token="00000000-0000-0000-1000-000000000000",
exp_month="06",
exp_year="2027",
memo="New Card",
pin="pin",
product_id="1",
- replacement_account_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- replacement_for="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ replacement_account_token="00000000-0000-0000-2000-000000000000",
+ replacement_for="00000000-0000-0000-1000-000000000000",
shipping_address={
"address1": "5 Broad Street",
"city": "NEW YORK",
@@ -140,7 +140,7 @@ def test_method_update(self, client: Lithic) -> None:
def test_method_update_with_all_params(self, client: Lithic) -> None:
card = client.cards.update(
card_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- digital_card_art_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ digital_card_art_token="00000000-0000-0000-1000-000000000000",
memo="Updated Name",
pin="pin",
pin_status="OK",
@@ -707,16 +707,16 @@ async def test_method_create_with_all_params(self, async_client: AsyncLithic) ->
card = await async_client.cards.create(
type="VIRTUAL",
account_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- card_program_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ card_program_token="00000000-0000-0000-1000-000000000000",
carrier={"qr_code_url": "qr_code_url"},
- digital_card_art_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ digital_card_art_token="00000000-0000-0000-1000-000000000000",
exp_month="06",
exp_year="2027",
memo="New Card",
pin="pin",
product_id="1",
- replacement_account_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- replacement_for="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ replacement_account_token="00000000-0000-0000-2000-000000000000",
+ replacement_for="00000000-0000-0000-1000-000000000000",
shipping_address={
"address1": "5 Broad Street",
"city": "NEW YORK",
@@ -810,7 +810,7 @@ async def test_method_update(self, async_client: AsyncLithic) -> None:
async def test_method_update_with_all_params(self, async_client: AsyncLithic) -> None:
card = await async_client.cards.update(
card_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- digital_card_art_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ digital_card_art_token="00000000-0000-0000-1000-000000000000",
memo="Updated Name",
pin="pin",
pin_status="OK",
diff --git a/tests/api_resources/test_external_bank_accounts.py b/tests/api_resources/test_external_bank_accounts.py
index 172ab15a..0d2a7650 100644
--- a/tests/api_resources/test_external_bank_accounts.py
+++ b/tests/api_resources/test_external_bank_accounts.py
@@ -246,6 +246,86 @@ def test_streaming_response_create_overload_3(self, client: Lithic) -> None:
assert cast(Any, response.is_closed) is True
+ @parametrize
+ def test_method_create_overload_4(self, client: Lithic) -> None:
+ external_bank_account = client.external_bank_accounts.create(
+ account_number="12345678901234567",
+ country="USD",
+ currency="USD",
+ owner="owner",
+ owner_type="INDIVIDUAL",
+ routing_number="123456789",
+ type="CHECKING",
+ verification_method="UNVERIFIED",
+ )
+ assert_matches_type(ExternalBankAccountCreateResponse, external_bank_account, path=["response"])
+
+ @parametrize
+ def test_method_create_with_all_params_overload_4(self, client: Lithic) -> None:
+ external_bank_account = client.external_bank_accounts.create(
+ account_number="12345678901234567",
+ country="USD",
+ currency="USD",
+ owner="owner",
+ owner_type="INDIVIDUAL",
+ routing_number="123456789",
+ type="CHECKING",
+ verification_method="UNVERIFIED",
+ account_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ address={
+ "address1": "x",
+ "city": "x",
+ "country": "USD",
+ "postal_code": "11201",
+ "state": "xx",
+ "address2": "x",
+ },
+ company_id="sq",
+ dob=parse_date("2019-12-27"),
+ doing_business_as="x",
+ name="name",
+ user_defined_id="x",
+ )
+ assert_matches_type(ExternalBankAccountCreateResponse, external_bank_account, path=["response"])
+
+ @parametrize
+ def test_raw_response_create_overload_4(self, client: Lithic) -> None:
+ response = client.external_bank_accounts.with_raw_response.create(
+ account_number="12345678901234567",
+ country="USD",
+ currency="USD",
+ owner="owner",
+ owner_type="INDIVIDUAL",
+ routing_number="123456789",
+ type="CHECKING",
+ verification_method="UNVERIFIED",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ external_bank_account = response.parse()
+ assert_matches_type(ExternalBankAccountCreateResponse, external_bank_account, path=["response"])
+
+ @parametrize
+ def test_streaming_response_create_overload_4(self, client: Lithic) -> None:
+ with client.external_bank_accounts.with_streaming_response.create(
+ account_number="12345678901234567",
+ country="USD",
+ currency="USD",
+ owner="owner",
+ owner_type="INDIVIDUAL",
+ routing_number="123456789",
+ type="CHECKING",
+ verification_method="UNVERIFIED",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ external_bank_account = response.parse()
+ assert_matches_type(ExternalBankAccountCreateResponse, external_bank_account, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
@parametrize
def test_method_retrieve(self, client: Lithic) -> None:
external_bank_account = client.external_bank_accounts.retrieve(
@@ -713,6 +793,86 @@ async def test_streaming_response_create_overload_3(self, async_client: AsyncLit
assert cast(Any, response.is_closed) is True
+ @parametrize
+ async def test_method_create_overload_4(self, async_client: AsyncLithic) -> None:
+ external_bank_account = await async_client.external_bank_accounts.create(
+ account_number="12345678901234567",
+ country="USD",
+ currency="USD",
+ owner="owner",
+ owner_type="INDIVIDUAL",
+ routing_number="123456789",
+ type="CHECKING",
+ verification_method="UNVERIFIED",
+ )
+ assert_matches_type(ExternalBankAccountCreateResponse, external_bank_account, path=["response"])
+
+ @parametrize
+ async def test_method_create_with_all_params_overload_4(self, async_client: AsyncLithic) -> None:
+ external_bank_account = await async_client.external_bank_accounts.create(
+ account_number="12345678901234567",
+ country="USD",
+ currency="USD",
+ owner="owner",
+ owner_type="INDIVIDUAL",
+ routing_number="123456789",
+ type="CHECKING",
+ verification_method="UNVERIFIED",
+ account_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ address={
+ "address1": "x",
+ "city": "x",
+ "country": "USD",
+ "postal_code": "11201",
+ "state": "xx",
+ "address2": "x",
+ },
+ company_id="sq",
+ dob=parse_date("2019-12-27"),
+ doing_business_as="x",
+ name="name",
+ user_defined_id="x",
+ )
+ assert_matches_type(ExternalBankAccountCreateResponse, external_bank_account, path=["response"])
+
+ @parametrize
+ async def test_raw_response_create_overload_4(self, async_client: AsyncLithic) -> None:
+ response = await async_client.external_bank_accounts.with_raw_response.create(
+ account_number="12345678901234567",
+ country="USD",
+ currency="USD",
+ owner="owner",
+ owner_type="INDIVIDUAL",
+ routing_number="123456789",
+ type="CHECKING",
+ verification_method="UNVERIFIED",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ external_bank_account = response.parse()
+ assert_matches_type(ExternalBankAccountCreateResponse, external_bank_account, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_create_overload_4(self, async_client: AsyncLithic) -> None:
+ async with async_client.external_bank_accounts.with_streaming_response.create(
+ account_number="12345678901234567",
+ country="USD",
+ currency="USD",
+ owner="owner",
+ owner_type="INDIVIDUAL",
+ routing_number="123456789",
+ type="CHECKING",
+ verification_method="UNVERIFIED",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ external_bank_account = await response.parse()
+ assert_matches_type(ExternalBankAccountCreateResponse, external_bank_account, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
@parametrize
async def test_method_retrieve(self, async_client: AsyncLithic) -> None:
external_bank_account = await async_client.external_bank_accounts.retrieve(
diff --git a/tests/api_resources/test_payments.py b/tests/api_resources/test_payments.py
index f409a78f..5857f51f 100644
--- a/tests/api_resources/test_payments.py
+++ b/tests/api_resources/test_payments.py
@@ -46,7 +46,10 @@ def test_method_create_with_all_params(self, client: Lithic) -> None:
external_bank_account_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
financial_account_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
method="ACH_NEXT_DAY",
- method_attributes={"sec_code": "CCD"},
+ method_attributes={
+ "sec_code": "CCD",
+ "addenda": "addenda",
+ },
type="COLLECTION",
token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
memo="memo",
@@ -404,7 +407,10 @@ async def test_method_create_with_all_params(self, async_client: AsyncLithic) ->
external_bank_account_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
financial_account_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
method="ACH_NEXT_DAY",
- method_attributes={"sec_code": "CCD"},
+ method_attributes={
+ "sec_code": "CCD",
+ "addenda": "addenda",
+ },
type="COLLECTION",
token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
memo="memo",
diff --git a/tests/api_resources/test_tokenizations.py b/tests/api_resources/test_tokenizations.py
index b69a1d58..b0c16426 100644
--- a/tests/api_resources/test_tokenizations.py
+++ b/tests/api_resources/test_tokenizations.py
@@ -364,7 +364,7 @@ def test_method_update_digital_card_art(self, client: Lithic) -> None:
def test_method_update_digital_card_art_with_all_params(self, client: Lithic) -> None:
tokenization = client.tokenizations.update_digital_card_art(
tokenization_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- digital_card_art_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ digital_card_art_token="00000000-0000-0000-1000-000000000000",
)
assert_matches_type(TokenizationUpdateDigitalCardArtResponse, tokenization, path=["response"])
@@ -745,7 +745,7 @@ async def test_method_update_digital_card_art(self, async_client: AsyncLithic) -
async def test_method_update_digital_card_art_with_all_params(self, async_client: AsyncLithic) -> None:
tokenization = await async_client.tokenizations.update_digital_card_art(
tokenization_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- digital_card_art_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ digital_card_art_token="00000000-0000-0000-1000-000000000000",
)
assert_matches_type(TokenizationUpdateDigitalCardArtResponse, tokenization, path=["response"])
diff --git a/tests/api_resources/three_ds/test_authentication.py b/tests/api_resources/three_ds/test_authentication.py
index afc195f1..05d603ca 100644
--- a/tests/api_resources/three_ds/test_authentication.py
+++ b/tests/api_resources/three_ds/test_authentication.py
@@ -71,8 +71,8 @@ def test_method_simulate(self, client: Lithic) -> None:
},
pan="4111111289144142",
transaction={
- "amount": 100,
- "currency": "USD",
+ "amount": 0,
+ "currency": "GBP",
},
)
assert_matches_type(AuthenticationSimulateResponse, authentication, path=["response"])
@@ -88,8 +88,8 @@ def test_method_simulate_with_all_params(self, client: Lithic) -> None:
},
pan="4111111289144142",
transaction={
- "amount": 100,
- "currency": "USD",
+ "amount": 0,
+ "currency": "GBP",
},
card_expiry_check="MATCH",
)
@@ -106,8 +106,8 @@ def test_raw_response_simulate(self, client: Lithic) -> None:
},
pan="4111111289144142",
transaction={
- "amount": 100,
- "currency": "USD",
+ "amount": 0,
+ "currency": "GBP",
},
)
@@ -127,8 +127,8 @@ def test_streaming_response_simulate(self, client: Lithic) -> None:
},
pan="4111111289144142",
transaction={
- "amount": 100,
- "currency": "USD",
+ "amount": 0,
+ "currency": "GBP",
},
) as response:
assert not response.is_closed
@@ -230,8 +230,8 @@ async def test_method_simulate(self, async_client: AsyncLithic) -> None:
},
pan="4111111289144142",
transaction={
- "amount": 100,
- "currency": "USD",
+ "amount": 0,
+ "currency": "GBP",
},
)
assert_matches_type(AuthenticationSimulateResponse, authentication, path=["response"])
@@ -247,8 +247,8 @@ async def test_method_simulate_with_all_params(self, async_client: AsyncLithic)
},
pan="4111111289144142",
transaction={
- "amount": 100,
- "currency": "USD",
+ "amount": 0,
+ "currency": "GBP",
},
card_expiry_check="MATCH",
)
@@ -265,8 +265,8 @@ async def test_raw_response_simulate(self, async_client: AsyncLithic) -> None:
},
pan="4111111289144142",
transaction={
- "amount": 100,
- "currency": "USD",
+ "amount": 0,
+ "currency": "GBP",
},
)
@@ -286,8 +286,8 @@ async def test_streaming_response_simulate(self, async_client: AsyncLithic) -> N
},
pan="4111111289144142",
transaction={
- "amount": 100,
- "currency": "USD",
+ "amount": 0,
+ "currency": "GBP",
},
) as response:
assert not response.is_closed
From 59781ebf072b0b0839d0ad4ab27a79bfa045db59 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 26 Jun 2025 14:08:19 +0000
Subject: [PATCH 2/7] =?UTF-8?q?fix(ci):=20release-doctor=20=E2=80=94=20rep?=
=?UTF-8?q?ort=20correct=20token=20name?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
bin/check-release-environment | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/bin/check-release-environment b/bin/check-release-environment
index 075f33e3..b845b0f4 100644
--- a/bin/check-release-environment
+++ b/bin/check-release-environment
@@ -3,7 +3,7 @@
errors=()
if [ -z "${PYPI_TOKEN}" ]; then
- errors+=("The LITHIC_PYPI_TOKEN secret has not been set. Please set it in either this repository's secrets or your organization secrets.")
+ errors+=("The PYPI_TOKEN secret has not been set. Please set it in either this repository's secrets or your organization secrets.")
fi
lenErrors=${#errors[@]}
From 1e1fb237a754aeb2a3d9cc5b751ef5d4c51d11e9 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 27 Jun 2025 14:24:12 +0000
Subject: [PATCH 3/7] feat(api): introduce dedicated model for
SpendLimitDuration
---
.stats.yml | 6 +++---
src/lithic/types/non_pci_card.py | 17 +++++++++++++++--
2 files changed, 18 insertions(+), 5 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 93eec907..6c4399ea 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 164
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic%2Flithic-a0d3bcd9c54616729a7e43847e3134205e0695d78f357cc7a25c2775b588dbbd.yml
-openapi_spec_hash: 36c423c286ca426f7510b27fadbdd66f
-config_hash: 56632a1c934324aa46c1e5c610c2de85
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic%2Flithic-cf48017e61eb3ac8aeaaa9d933186532f476b2f3c7e12fa9c962d52e5a9a272b.yml
+openapi_spec_hash: b58989fdc04768fc1eb758e180c5f128
+config_hash: e4d87bd83b304f6ab3f032db994e0093
diff --git a/src/lithic/types/non_pci_card.py b/src/lithic/types/non_pci_card.py
index cdaf8d6e..8175e27d 100644
--- a/src/lithic/types/non_pci_card.py
+++ b/src/lithic/types/non_pci_card.py
@@ -5,6 +5,7 @@
from typing_extensions import Literal
from .._models import BaseModel
+from .spend_limit_duration import SpendLimitDuration
__all__ = ["NonPCICard", "Funding"]
@@ -79,8 +80,20 @@ class NonPCICard(BaseModel):
be declined.
"""
- spend_limit_duration: Literal["ANNUALLY", "FOREVER", "MONTHLY", "TRANSACTION", "DAILY"]
- """Spend limit duration"""
+ spend_limit_duration: SpendLimitDuration
+ """Spend limit duration values:
+
+ - `ANNUALLY` - Card will authorize transactions up to spend limit for the
+ trailing year.
+ - `FOREVER` - Card will authorize only up to spend limit for the entire lifetime
+ of the card.
+ - `MONTHLY` - Card will authorize transactions up to spend limit for the
+ trailing month. 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.
+ - `TRANSACTION` - Card will authorize multiple transactions if each individual
+ transaction is under the spend limit.
+ """
state: Literal["CLOSED", "OPEN", "PAUSED", "PENDING_ACTIVATION", "PENDING_FULFILLMENT"]
"""Card state values: \\** `CLOSED` - Card will no longer approve authorizations.
From 0c5bbdb7e2bff6f7588b06b5ef3ed40db06b412b Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 27 Jun 2025 16:57:33 +0000
Subject: [PATCH 4/7] chore(internal): manual updates
---
.stats.yml | 4 ++--
tests/api_resources/test_account_holders.py | 16 ++++++++--------
tests/api_resources/test_cards.py | 20 ++++++++++----------
tests/api_resources/test_tokenizations.py | 4 ++--
4 files changed, 22 insertions(+), 22 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 6c4399ea..ba657b97 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 164
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic%2Flithic-cf48017e61eb3ac8aeaaa9d933186532f476b2f3c7e12fa9c962d52e5a9a272b.yml
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic%2Flithic-aa684ff2a2af585fe502a6e44520ddd883f5141a1113fc9dbe7830027842aa09.yml
openapi_spec_hash: b58989fdc04768fc1eb758e180c5f128
-config_hash: e4d87bd83b304f6ab3f032db994e0093
+config_hash: 1a83dceb58f6f525b19a5775018db7e8
diff --git a/tests/api_resources/test_account_holders.py b/tests/api_resources/test_account_holders.py
index 9b4c89b2..ccd60ff8 100644
--- a/tests/api_resources/test_account_holders.py
+++ b/tests/api_resources/test_account_holders.py
@@ -870,7 +870,7 @@ def test_path_params_retrieve_document(self, client: Lithic) -> None:
@parametrize
def test_method_simulate_enrollment_document_review(self, client: Lithic) -> None:
account_holder = client.account_holders.simulate_enrollment_document_review(
- document_upload_token="b11cd67b-0a52-4180-8365-314f3def5426",
+ document_upload_token="document_upload_token",
status="UPLOADED",
)
assert_matches_type(Document, account_holder, path=["response"])
@@ -878,7 +878,7 @@ def test_method_simulate_enrollment_document_review(self, client: Lithic) -> Non
@parametrize
def test_method_simulate_enrollment_document_review_with_all_params(self, client: Lithic) -> None:
account_holder = client.account_holders.simulate_enrollment_document_review(
- document_upload_token="b11cd67b-0a52-4180-8365-314f3def5426",
+ document_upload_token="document_upload_token",
status="UPLOADED",
accepted_entity_status_reasons=["string"],
status_reason="DOCUMENT_MISSING_REQUIRED_DATA",
@@ -888,7 +888,7 @@ def test_method_simulate_enrollment_document_review_with_all_params(self, client
@parametrize
def test_raw_response_simulate_enrollment_document_review(self, client: Lithic) -> None:
response = client.account_holders.with_raw_response.simulate_enrollment_document_review(
- document_upload_token="b11cd67b-0a52-4180-8365-314f3def5426",
+ document_upload_token="document_upload_token",
status="UPLOADED",
)
@@ -900,7 +900,7 @@ def test_raw_response_simulate_enrollment_document_review(self, client: Lithic)
@parametrize
def test_streaming_response_simulate_enrollment_document_review(self, client: Lithic) -> None:
with client.account_holders.with_streaming_response.simulate_enrollment_document_review(
- document_upload_token="b11cd67b-0a52-4180-8365-314f3def5426",
+ document_upload_token="document_upload_token",
status="UPLOADED",
) as response:
assert not response.is_closed
@@ -1841,7 +1841,7 @@ async def test_path_params_retrieve_document(self, async_client: AsyncLithic) ->
@parametrize
async def test_method_simulate_enrollment_document_review(self, async_client: AsyncLithic) -> None:
account_holder = await async_client.account_holders.simulate_enrollment_document_review(
- document_upload_token="b11cd67b-0a52-4180-8365-314f3def5426",
+ document_upload_token="document_upload_token",
status="UPLOADED",
)
assert_matches_type(Document, account_holder, path=["response"])
@@ -1849,7 +1849,7 @@ async def test_method_simulate_enrollment_document_review(self, async_client: As
@parametrize
async def test_method_simulate_enrollment_document_review_with_all_params(self, async_client: AsyncLithic) -> None:
account_holder = await async_client.account_holders.simulate_enrollment_document_review(
- document_upload_token="b11cd67b-0a52-4180-8365-314f3def5426",
+ document_upload_token="document_upload_token",
status="UPLOADED",
accepted_entity_status_reasons=["string"],
status_reason="DOCUMENT_MISSING_REQUIRED_DATA",
@@ -1859,7 +1859,7 @@ async def test_method_simulate_enrollment_document_review_with_all_params(self,
@parametrize
async def test_raw_response_simulate_enrollment_document_review(self, async_client: AsyncLithic) -> None:
response = await async_client.account_holders.with_raw_response.simulate_enrollment_document_review(
- document_upload_token="b11cd67b-0a52-4180-8365-314f3def5426",
+ document_upload_token="document_upload_token",
status="UPLOADED",
)
@@ -1871,7 +1871,7 @@ async def test_raw_response_simulate_enrollment_document_review(self, async_clie
@parametrize
async def test_streaming_response_simulate_enrollment_document_review(self, async_client: AsyncLithic) -> None:
async with async_client.account_holders.with_streaming_response.simulate_enrollment_document_review(
- document_upload_token="b11cd67b-0a52-4180-8365-314f3def5426",
+ document_upload_token="document_upload_token",
status="UPLOADED",
) as response:
assert not response.is_closed
diff --git a/tests/api_resources/test_cards.py b/tests/api_resources/test_cards.py
index b1e6026a..56149df3 100644
--- a/tests/api_resources/test_cards.py
+++ b/tests/api_resources/test_cards.py
@@ -37,16 +37,16 @@ def test_method_create_with_all_params(self, client: Lithic) -> None:
card = client.cards.create(
type="VIRTUAL",
account_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- card_program_token="00000000-0000-0000-1000-000000000000",
+ card_program_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
carrier={"qr_code_url": "qr_code_url"},
- digital_card_art_token="00000000-0000-0000-1000-000000000000",
+ digital_card_art_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
exp_month="06",
exp_year="2027",
memo="New Card",
pin="pin",
product_id="1",
- replacement_account_token="00000000-0000-0000-2000-000000000000",
- replacement_for="00000000-0000-0000-1000-000000000000",
+ replacement_account_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ replacement_for="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
shipping_address={
"address1": "5 Broad Street",
"city": "NEW YORK",
@@ -140,7 +140,7 @@ def test_method_update(self, client: Lithic) -> None:
def test_method_update_with_all_params(self, client: Lithic) -> None:
card = client.cards.update(
card_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- digital_card_art_token="00000000-0000-0000-1000-000000000000",
+ digital_card_art_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
memo="Updated Name",
pin="pin",
pin_status="OK",
@@ -707,16 +707,16 @@ async def test_method_create_with_all_params(self, async_client: AsyncLithic) ->
card = await async_client.cards.create(
type="VIRTUAL",
account_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- card_program_token="00000000-0000-0000-1000-000000000000",
+ card_program_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
carrier={"qr_code_url": "qr_code_url"},
- digital_card_art_token="00000000-0000-0000-1000-000000000000",
+ digital_card_art_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
exp_month="06",
exp_year="2027",
memo="New Card",
pin="pin",
product_id="1",
- replacement_account_token="00000000-0000-0000-2000-000000000000",
- replacement_for="00000000-0000-0000-1000-000000000000",
+ replacement_account_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ replacement_for="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
shipping_address={
"address1": "5 Broad Street",
"city": "NEW YORK",
@@ -810,7 +810,7 @@ async def test_method_update(self, async_client: AsyncLithic) -> None:
async def test_method_update_with_all_params(self, async_client: AsyncLithic) -> None:
card = await async_client.cards.update(
card_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- digital_card_art_token="00000000-0000-0000-1000-000000000000",
+ digital_card_art_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
memo="Updated Name",
pin="pin",
pin_status="OK",
diff --git a/tests/api_resources/test_tokenizations.py b/tests/api_resources/test_tokenizations.py
index b0c16426..b69a1d58 100644
--- a/tests/api_resources/test_tokenizations.py
+++ b/tests/api_resources/test_tokenizations.py
@@ -364,7 +364,7 @@ def test_method_update_digital_card_art(self, client: Lithic) -> None:
def test_method_update_digital_card_art_with_all_params(self, client: Lithic) -> None:
tokenization = client.tokenizations.update_digital_card_art(
tokenization_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- digital_card_art_token="00000000-0000-0000-1000-000000000000",
+ digital_card_art_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert_matches_type(TokenizationUpdateDigitalCardArtResponse, tokenization, path=["response"])
@@ -745,7 +745,7 @@ async def test_method_update_digital_card_art(self, async_client: AsyncLithic) -
async def test_method_update_digital_card_art_with_all_params(self, async_client: AsyncLithic) -> None:
tokenization = await async_client.tokenizations.update_digital_card_art(
tokenization_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- digital_card_art_token="00000000-0000-0000-1000-000000000000",
+ digital_card_art_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert_matches_type(TokenizationUpdateDigitalCardArtResponse, tokenization, path=["response"])
From 954c7f0f1bea593b30d71d15a8c626ffadf30c6b Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 27 Jun 2025 22:41:47 +0000
Subject: [PATCH 5/7] chore(ci): only run for pushes and fork pull requests
---
.github/workflows/ci.yml | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index b6a32348..b193977c 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -17,6 +17,7 @@ jobs:
timeout-minutes: 10
name: lint
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@v4
@@ -42,6 +43,7 @@ jobs:
contents: read
id-token: write
runs-on: depot-ubuntu-24.04
+ if: github.event_name == 'push' || github.event.pull_request.head.repo.fork
steps:
- uses: actions/checkout@v4
@@ -62,6 +64,7 @@ jobs:
timeout-minutes: 10
name: test
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@v4
@@ -83,7 +86,7 @@ jobs:
timeout-minutes: 10
name: examples
runs-on: ${{ github.repository == 'stainless-sdks/lithic-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
- if: github.repository == 'lithic-com/lithic-python'
+ if: github.repository == 'lithic-com/lithic-python && (github.event_name == 'push' || github.event.pull_request.head.repo.fork)'
steps:
- uses: actions/checkout@v4
From 9422f2ec8393447429219af34bda88c581984fa3 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Sun, 29 Jun 2025 06:21:07 +0000
Subject: [PATCH 6/7] fix(ci): correct conditional
---
.github/workflows/ci.yml | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index b193977c..1219cf77 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -36,14 +36,13 @@ jobs:
run: ./scripts/lint
upload:
- if: github.repository == 'stainless-sdks/lithic-python'
+ if: github.repository == 'stainless-sdks/lithic-python' && (github.event_name == 'push' || github.event.pull_request.head.repo.fork)
timeout-minutes: 10
name: upload
permissions:
contents: read
id-token: write
runs-on: depot-ubuntu-24.04
- if: github.event_name == 'push' || github.event.pull_request.head.repo.fork
steps:
- uses: actions/checkout@v4
@@ -86,7 +85,7 @@ jobs:
timeout-minutes: 10
name: examples
runs-on: ${{ github.repository == 'stainless-sdks/lithic-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
- if: github.repository == 'lithic-com/lithic-python && (github.event_name == 'push' || github.event.pull_request.head.repo.fork)'
+ if: github.repository == 'lithic-com/lithic-python' && (github.event_name == 'push' || github.event.pull_request.head.repo.fork)
steps:
- uses: actions/checkout@v4
From 0b364a72b374ecbd5f86cb22d5e073e7675a7ede Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Sun, 29 Jun 2025 06:21:36 +0000
Subject: [PATCH 7/7] release: 0.95.0
---
.release-please-manifest.json | 2 +-
CHANGELOG.md | 21 +++++++++++++++++++++
pyproject.toml | 2 +-
src/lithic/_version.py | 2 +-
4 files changed, 24 insertions(+), 3 deletions(-)
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 91393ed8..2292ca70 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.94.0"
+ ".": "0.95.0"
}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e7085981..dd41ec7b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,26 @@
# Changelog
+## 0.95.0 (2025-06-29)
+
+Full Changelog: [v0.94.0...v0.95.0](https://github.com/lithic-com/lithic-python/compare/v0.94.0...v0.95.0)
+
+### Features
+
+* **api:** introduce dedicated model for SpendLimitDuration ([1e1fb23](https://github.com/lithic-com/lithic-python/commit/1e1fb237a754aeb2a3d9cc5b751ef5d4c51d11e9))
+* **client:** adds support for on-demand Auth Rule Performance Reports ([81c2860](https://github.com/lithic-com/lithic-python/commit/81c2860a37078364b3f4c1876f407b60bdb88bec))
+
+
+### Bug Fixes
+
+* **ci:** correct conditional ([9422f2e](https://github.com/lithic-com/lithic-python/commit/9422f2ec8393447429219af34bda88c581984fa3))
+* **ci:** release-doctor — report correct token name ([59781eb](https://github.com/lithic-com/lithic-python/commit/59781ebf072b0b0839d0ad4ab27a79bfa045db59))
+
+
+### Chores
+
+* **ci:** only run for pushes and fork pull requests ([954c7f0](https://github.com/lithic-com/lithic-python/commit/954c7f0f1bea593b30d71d15a8c626ffadf30c6b))
+* **internal:** manual updates ([0c5bbdb](https://github.com/lithic-com/lithic-python/commit/0c5bbdb7e2bff6f7588b06b5ef3ed40db06b412b))
+
## 0.94.0 (2025-06-23)
Full Changelog: [v0.93.0...v0.94.0](https://github.com/lithic-com/lithic-python/compare/v0.93.0...v0.94.0)
diff --git a/pyproject.toml b/pyproject.toml
index 71756fe2..7a00f8d6 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "lithic"
-version = "0.94.0"
+version = "0.95.0"
description = "The official Python library for the lithic API"
dynamic = ["readme"]
license = "Apache-2.0"
diff --git a/src/lithic/_version.py b/src/lithic/_version.py
index 7cfff106..6dbf48d0 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.94.0" # x-release-please-version
+__version__ = "0.95.0" # x-release-please-version