diff --git a/.release-please-manifest.json b/.release-please-manifest.json index bb57c8a49..0c3706a77 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.291.0" + ".": "0.292.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index ebd672bf3..564ef9424 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 214 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/increase%2Fincrease-e37d9eb06122e71071da98a7375420ce776ad9aa05176bed89a232bd6854f26b.yml -openapi_spec_hash: 8ffb1a0fd8523b24113105717c5d85d8 -config_hash: b0b366d8c705ea0efe62093bae953e5a +configured_endpoints: 215 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/increase%2Fincrease-9a5905fe541badfa11ad0641e7aea625c9fb0bc59ba33b1d43d8e88cbbdd71b2.yml +openapi_spec_hash: 4347de40c3142cd56c2185aac9a6739e +config_hash: 0b0a2503208283b283fc5bc6df6a07a5 diff --git a/CHANGELOG.md b/CHANGELOG.md index 1491c5ef3..8f134c73c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 0.292.0 (2025-08-20) + +Full Changelog: [v0.291.0...v0.292.0](https://github.com/Increase/increase-python/compare/v0.291.0...v0.292.0) + +### Features + +* **api:** api update ([77e376d](https://github.com/Increase/increase-python/commit/77e376d9e705be047baf33c2bc3c3b2ba3e4173a)) + ## 0.291.0 (2025-08-20) Full Changelog: [v0.290.0...v0.291.0](https://github.com/Increase/increase-python/compare/v0.290.0...v0.291.0) diff --git a/api.md b/api.md index f9248a7cb..ea2de8e78 100644 --- a/api.md +++ b/api.md @@ -35,7 +35,7 @@ Methods: Types: ```python -from increase.types import Card, CardDetails +from increase.types import Card, CardDetails, CardIframeURL ``` Methods: @@ -44,6 +44,7 @@ Methods: - client.cards.retrieve(card_id) -> Card - client.cards.update(card_id, \*\*params) -> Card - client.cards.list(\*\*params) -> SyncPage[Card] +- client.cards.create_details_iframe(card_id, \*\*params) -> CardIframeURL - client.cards.details(card_id) -> CardDetails # CardPayments diff --git a/pyproject.toml b/pyproject.toml index 7c55e9162..0c9c7af4c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "increase" -version = "0.291.0" +version = "0.292.0" description = "The official Python library for the increase API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/increase/_version.py b/src/increase/_version.py index 22dae204c..d0a7bf6b3 100644 --- a/src/increase/_version.py +++ b/src/increase/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "increase" -__version__ = "0.291.0" # x-release-please-version +__version__ = "0.292.0" # x-release-please-version diff --git a/src/increase/resources/cards.py b/src/increase/resources/cards.py index 5030a9736..5f44c9a85 100644 --- a/src/increase/resources/cards.py +++ b/src/increase/resources/cards.py @@ -6,7 +6,7 @@ import httpx -from ..types import card_list_params, card_create_params, card_update_params +from ..types import card_list_params, card_create_params, card_update_params, card_create_details_iframe_params from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven from .._utils import maybe_transform, async_maybe_transform from .._compat import cached_property @@ -21,6 +21,7 @@ from ..types.card import Card from .._base_client import AsyncPaginator, make_request_options from ..types.card_details import CardDetails +from ..types.card_iframe_url import CardIframeURL __all__ = ["CardsResource", "AsyncCardsResource"] @@ -284,6 +285,57 @@ def list( model=Card, ) + def create_details_iframe( + self, + card_id: str, + *, + physical_card_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, + idempotency_key: str | None = None, + ) -> CardIframeURL: + """Create an iframe URL for a Card to display the card details. + + More details about + styling and usage can be found in the + [documentation](/documentation/embedded-card-component). + + Args: + card_id: The identifier of the Card to retrieve details for. + + physical_card_id: The identifier of the Physical Card to retrieve details for. + + 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 + + idempotency_key: Specify a custom idempotency key for this request + """ + if not card_id: + raise ValueError(f"Expected a non-empty value for `card_id` but received {card_id!r}") + return self._post( + f"/cards/{card_id}/create_details_iframe", + body=maybe_transform( + {"physical_card_id": physical_card_id}, card_create_details_iframe_params.CardCreateDetailsIframeParams + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=CardIframeURL, + ) + def details( self, card_id: str, @@ -296,7 +348,8 @@ def details( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> CardDetails: """ - Retrieve sensitive details for a Card + Sensitive details for a Card include the primary account number, expiry, card + verification code, and PIN. Args: card_id: The identifier of the Card to retrieve details for. @@ -579,6 +632,57 @@ def list( model=Card, ) + async def create_details_iframe( + self, + card_id: str, + *, + physical_card_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, + idempotency_key: str | None = None, + ) -> CardIframeURL: + """Create an iframe URL for a Card to display the card details. + + More details about + styling and usage can be found in the + [documentation](/documentation/embedded-card-component). + + Args: + card_id: The identifier of the Card to retrieve details for. + + physical_card_id: The identifier of the Physical Card to retrieve details for. + + 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 + + idempotency_key: Specify a custom idempotency key for this request + """ + if not card_id: + raise ValueError(f"Expected a non-empty value for `card_id` but received {card_id!r}") + return await self._post( + f"/cards/{card_id}/create_details_iframe", + body=await async_maybe_transform( + {"physical_card_id": physical_card_id}, card_create_details_iframe_params.CardCreateDetailsIframeParams + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=CardIframeURL, + ) + async def details( self, card_id: str, @@ -591,7 +695,8 @@ async def details( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> CardDetails: """ - Retrieve sensitive details for a Card + Sensitive details for a Card include the primary account number, expiry, card + verification code, and PIN. Args: card_id: The identifier of the Card to retrieve details for. @@ -631,6 +736,9 @@ def __init__(self, cards: CardsResource) -> None: self.list = to_raw_response_wrapper( cards.list, ) + self.create_details_iframe = to_raw_response_wrapper( + cards.create_details_iframe, + ) self.details = to_raw_response_wrapper( cards.details, ) @@ -652,6 +760,9 @@ def __init__(self, cards: AsyncCardsResource) -> None: self.list = async_to_raw_response_wrapper( cards.list, ) + self.create_details_iframe = async_to_raw_response_wrapper( + cards.create_details_iframe, + ) self.details = async_to_raw_response_wrapper( cards.details, ) @@ -673,6 +784,9 @@ def __init__(self, cards: CardsResource) -> None: self.list = to_streamed_response_wrapper( cards.list, ) + self.create_details_iframe = to_streamed_response_wrapper( + cards.create_details_iframe, + ) self.details = to_streamed_response_wrapper( cards.details, ) @@ -694,6 +808,9 @@ def __init__(self, cards: AsyncCardsResource) -> None: self.list = async_to_streamed_response_wrapper( cards.list, ) + self.create_details_iframe = async_to_streamed_response_wrapper( + cards.create_details_iframe, + ) self.details = async_to_streamed_response_wrapper( cards.details, ) diff --git a/src/increase/types/__init__.py b/src/increase/types/__init__.py index 3e4272dc6..d84ce1265 100644 --- a/src/increase/types/__init__.py +++ b/src/increase/types/__init__.py @@ -26,6 +26,7 @@ from .account_number import AccountNumber as AccountNumber from .balance_lookup import BalanceLookup as BalanceLookup from .check_transfer import CheckTransfer as CheckTransfer +from .card_iframe_url import CardIframeURL as CardIframeURL from .card_validation import CardValidation as CardValidation from .intrafi_balance import IntrafiBalance as IntrafiBalance from .account_transfer import AccountTransfer as AccountTransfer @@ -134,6 +135,7 @@ from .bookkeeping_account_create_params import BookkeepingAccountCreateParams as BookkeepingAccountCreateParams from .bookkeeping_account_update_params import BookkeepingAccountUpdateParams as BookkeepingAccountUpdateParams from .bookkeeping_entry_set_list_params import BookkeepingEntrySetListParams as BookkeepingEntrySetListParams +from .card_create_details_iframe_params import CardCreateDetailsIframeParams as CardCreateDetailsIframeParams from .digital_card_profile_clone_params import DigitalCardProfileCloneParams as DigitalCardProfileCloneParams from .inbound_check_deposit_list_params import InboundCheckDepositListParams as InboundCheckDepositListParams from .inbound_wire_transfer_list_params import InboundWireTransferListParams as InboundWireTransferListParams diff --git a/src/increase/types/card_create_details_iframe_params.py b/src/increase/types/card_create_details_iframe_params.py new file mode 100644 index 000000000..9af571640 --- /dev/null +++ b/src/increase/types/card_create_details_iframe_params.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import TypedDict + +__all__ = ["CardCreateDetailsIframeParams"] + + +class CardCreateDetailsIframeParams(TypedDict, total=False): + physical_card_id: str + """The identifier of the Physical Card to retrieve details for.""" diff --git a/src/increase/types/card_iframe_url.py b/src/increase/types/card_iframe_url.py new file mode 100644 index 000000000..e4da2319c --- /dev/null +++ b/src/increase/types/card_iframe_url.py @@ -0,0 +1,22 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from datetime import datetime +from typing_extensions import Literal + +from .._models import BaseModel + +__all__ = ["CardIframeURL"] + + +class CardIframeURL(BaseModel): + expires_at: datetime + """The time the iframe URL will expire.""" + + iframe_url: str + """The iframe URL for the Card. Treat this as an opaque URL.""" + + type: Literal["card_iframe_url"] + """A constant representing the object's type. + + For this resource it will always be `card_iframe_url`. + """ diff --git a/tests/api_resources/test_cards.py b/tests/api_resources/test_cards.py index c93eab95e..9be877a70 100644 --- a/tests/api_resources/test_cards.py +++ b/tests/api_resources/test_cards.py @@ -9,7 +9,11 @@ from increase import Increase, AsyncIncrease from tests.utils import assert_matches_type -from increase.types import Card, CardDetails +from increase.types import ( + Card, + CardDetails, + CardIframeURL, +) from increase._utils import parse_datetime from increase.pagination import SyncPage, AsyncPage @@ -211,6 +215,52 @@ def test_streaming_response_list(self, client: Increase) -> None: assert cast(Any, response.is_closed) is True + @parametrize + def test_method_create_details_iframe(self, client: Increase) -> None: + card = client.cards.create_details_iframe( + card_id="card_oubs0hwk5rn6knuecxg2", + ) + assert_matches_type(CardIframeURL, card, path=["response"]) + + @parametrize + def test_method_create_details_iframe_with_all_params(self, client: Increase) -> None: + card = client.cards.create_details_iframe( + card_id="card_oubs0hwk5rn6knuecxg2", + physical_card_id="physical_card_id", + ) + assert_matches_type(CardIframeURL, card, path=["response"]) + + @parametrize + def test_raw_response_create_details_iframe(self, client: Increase) -> None: + response = client.cards.with_raw_response.create_details_iframe( + card_id="card_oubs0hwk5rn6knuecxg2", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + card = response.parse() + assert_matches_type(CardIframeURL, card, path=["response"]) + + @parametrize + def test_streaming_response_create_details_iframe(self, client: Increase) -> None: + with client.cards.with_streaming_response.create_details_iframe( + card_id="card_oubs0hwk5rn6knuecxg2", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + card = response.parse() + assert_matches_type(CardIframeURL, card, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_create_details_iframe(self, client: Increase) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `card_id` but received ''"): + client.cards.with_raw_response.create_details_iframe( + card_id="", + ) + @parametrize def test_method_details(self, client: Increase) -> None: card = client.cards.details( @@ -447,6 +497,52 @@ async def test_streaming_response_list(self, async_client: AsyncIncrease) -> Non assert cast(Any, response.is_closed) is True + @parametrize + async def test_method_create_details_iframe(self, async_client: AsyncIncrease) -> None: + card = await async_client.cards.create_details_iframe( + card_id="card_oubs0hwk5rn6knuecxg2", + ) + assert_matches_type(CardIframeURL, card, path=["response"]) + + @parametrize + async def test_method_create_details_iframe_with_all_params(self, async_client: AsyncIncrease) -> None: + card = await async_client.cards.create_details_iframe( + card_id="card_oubs0hwk5rn6knuecxg2", + physical_card_id="physical_card_id", + ) + assert_matches_type(CardIframeURL, card, path=["response"]) + + @parametrize + async def test_raw_response_create_details_iframe(self, async_client: AsyncIncrease) -> None: + response = await async_client.cards.with_raw_response.create_details_iframe( + card_id="card_oubs0hwk5rn6knuecxg2", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + card = await response.parse() + assert_matches_type(CardIframeURL, card, path=["response"]) + + @parametrize + async def test_streaming_response_create_details_iframe(self, async_client: AsyncIncrease) -> None: + async with async_client.cards.with_streaming_response.create_details_iframe( + card_id="card_oubs0hwk5rn6knuecxg2", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + card = await response.parse() + assert_matches_type(CardIframeURL, card, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_create_details_iframe(self, async_client: AsyncIncrease) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `card_id` but received ''"): + await async_client.cards.with_raw_response.create_details_iframe( + card_id="", + ) + @parametrize async def test_method_details(self, async_client: AsyncIncrease) -> None: card = await async_client.cards.details(