From 324431e3c83e7d89f93306900efb800ce1d9a594 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 15 May 2025 17:06:23 +0000 Subject: [PATCH 1/4] feat(api): new Funding Events and Card Web Provision API's - Card Web Provisioning API allows your cardholders to directly add payment cards to the device's digital wallet from a browser on the web. Currently only supported for Apple Pay. - new Funding Events API and Webhooks --- .stats.yml | 8 +- api.md | 20 + src/lithic/_client.py | 38 ++ src/lithic/resources/__init__.py | 14 + src/lithic/resources/cards/cards.py | 100 +++++ src/lithic/resources/funding_events.py | 368 ++++++++++++++++++ src/lithic/types/__init__.py | 8 + src/lithic/types/card_web_provision_params.py | 12 + .../types/card_web_provision_response.py | 40 ++ src/lithic/types/funding_event_list_params.py | 25 ++ .../types/funding_event_list_response.py | 41 ++ ...funding_event_retrieve_details_response.py | 16 + .../types/funding_event_retrieve_response.py | 41 ++ tests/api_resources/test_cards.py | 93 +++++ tests/api_resources/test_funding_events.py | 247 ++++++++++++ 15 files changed, 1067 insertions(+), 4 deletions(-) create mode 100644 src/lithic/resources/funding_events.py create mode 100644 src/lithic/types/card_web_provision_params.py create mode 100644 src/lithic/types/card_web_provision_response.py create mode 100644 src/lithic/types/funding_event_list_params.py create mode 100644 src/lithic/types/funding_event_list_response.py create mode 100644 src/lithic/types/funding_event_retrieve_details_response.py create mode 100644 src/lithic/types/funding_event_retrieve_response.py create mode 100644 tests/api_resources/test_funding_events.py diff --git a/.stats.yml b/.stats.yml index 2b14f03c..054543bd 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 156 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic%2Flithic-9580d7ed7ee603cba3dd0db9bb1ee48094dfe2a90c1ca13a7f10ab8deaa73e2c.yml -openapi_spec_hash: 6f707e3df699aec761f20db720fb3a32 -config_hash: dc221a354631e360e545ebb7435ecd35 +configured_endpoints: 160 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic%2Flithic-025f40c854a9485cf316c9058f9cc5fa37f069add30e409d49ab93f2e166f4fb.yml +openapi_spec_hash: a9391f3a54b8db5d5df40169de8c645c +config_hash: fa3481d1d8505e4157f6cebe93211bd0 diff --git a/api.md b/api.md index 702d84dc..12536aa0 100644 --- a/api.md +++ b/api.md @@ -184,6 +184,7 @@ from lithic.types import ( SpendLimitDuration, CardEmbedResponse, CardProvisionResponse, + CardWebProvisionResponse, ) ``` @@ -200,6 +201,7 @@ Methods: - client.cards.renew(card_token, \*\*params) -> Card - client.cards.retrieve_spend_limits(card_token) -> CardSpendLimits - client.cards.search_by_pan(\*\*params) -> Card +- client.cards.web_provision(card_token, \*\*params) -> CardWebProvisionResponse - client.cards.get_embed_html(\*args) -> str - client.cards.get_embed_url(\*args) -> URL @@ -713,3 +715,21 @@ Methods: - client.management_operations.retrieve(management_operation_token) -> ManagementOperationTransaction - client.management_operations.list(\*\*params) -> SyncCursorPage[ManagementOperationTransaction] - client.management_operations.reverse(management_operation_token, \*\*params) -> ManagementOperationTransaction + +# FundingEvents + +Types: + +```python +from lithic.types import ( + FundingEventRetrieveResponse, + FundingEventListResponse, + FundingEventRetrieveDetailsResponse, +) +``` + +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 diff --git a/src/lithic/_client.py b/src/lithic/_client.py index 2738033e..1e97d5c2 100644 --- a/src/lithic/_client.py +++ b/src/lithic/_client.py @@ -52,6 +52,7 @@ card_programs, tokenizations, book_transfers, + funding_events, account_holders, credit_products, digital_card_art, @@ -73,6 +74,7 @@ from .resources.events.events import Events, AsyncEvents from .resources.tokenizations import Tokenizations, AsyncTokenizations from .resources.book_transfers import BookTransfers, AsyncBookTransfers + from .resources.funding_events import FundingEvents, AsyncFundingEvents from .resources.account_holders import AccountHolders, AsyncAccountHolders from .resources.reports.reports import Reports, AsyncReports from .resources.digital_card_art import DigitalCardArtResource, AsyncDigitalCardArtResource @@ -338,6 +340,12 @@ def management_operations(self) -> ManagementOperations: return ManagementOperations(self) + @cached_property + def funding_events(self) -> FundingEvents: + from .resources.funding_events import FundingEvents + + return FundingEvents(self) + @cached_property def webhooks(self) -> webhooks.Webhooks: from .resources.webhooks import Webhooks @@ -712,6 +720,12 @@ def management_operations(self) -> AsyncManagementOperations: return AsyncManagementOperations(self) + @cached_property + def funding_events(self) -> AsyncFundingEvents: + from .resources.funding_events import AsyncFundingEvents + + return AsyncFundingEvents(self) + @cached_property def webhooks(self) -> webhooks.AsyncWebhooks: from .resources.webhooks import AsyncWebhooks @@ -1009,6 +1023,12 @@ def management_operations(self) -> management_operations.ManagementOperationsWit return ManagementOperationsWithRawResponse(self._client.management_operations) + @cached_property + def funding_events(self) -> funding_events.FundingEventsWithRawResponse: + from .resources.funding_events import FundingEventsWithRawResponse + + return FundingEventsWithRawResponse(self._client.funding_events) + class AsyncLithicWithRawResponse: _client: AsyncLithic @@ -1164,6 +1184,12 @@ def management_operations(self) -> management_operations.AsyncManagementOperatio return AsyncManagementOperationsWithRawResponse(self._client.management_operations) + @cached_property + def funding_events(self) -> funding_events.AsyncFundingEventsWithRawResponse: + from .resources.funding_events import AsyncFundingEventsWithRawResponse + + return AsyncFundingEventsWithRawResponse(self._client.funding_events) + class LithicWithStreamedResponse: _client: Lithic @@ -1319,6 +1345,12 @@ def management_operations(self) -> management_operations.ManagementOperationsWit return ManagementOperationsWithStreamingResponse(self._client.management_operations) + @cached_property + def funding_events(self) -> funding_events.FundingEventsWithStreamingResponse: + from .resources.funding_events import FundingEventsWithStreamingResponse + + return FundingEventsWithStreamingResponse(self._client.funding_events) + class AsyncLithicWithStreamedResponse: _client: AsyncLithic @@ -1474,6 +1506,12 @@ def management_operations(self) -> management_operations.AsyncManagementOperatio return AsyncManagementOperationsWithStreamingResponse(self._client.management_operations) + @cached_property + def funding_events(self) -> funding_events.AsyncFundingEventsWithStreamingResponse: + from .resources.funding_events import AsyncFundingEventsWithStreamingResponse + + return AsyncFundingEventsWithStreamingResponse(self._client.funding_events) + Client = Lithic diff --git a/src/lithic/resources/__init__.py b/src/lithic/resources/__init__.py index e3745acb..6186ee94 100644 --- a/src/lithic/resources/__init__.py +++ b/src/lithic/resources/__init__.py @@ -105,6 +105,14 @@ BookTransfersWithStreamingResponse, AsyncBookTransfersWithStreamingResponse, ) +from .funding_events import ( + FundingEvents, + AsyncFundingEvents, + FundingEventsWithRawResponse, + AsyncFundingEventsWithRawResponse, + FundingEventsWithStreamingResponse, + AsyncFundingEventsWithStreamingResponse, +) from .account_holders import ( AccountHolders, AsyncAccountHolders, @@ -341,4 +349,10 @@ "AsyncManagementOperationsWithRawResponse", "ManagementOperationsWithStreamingResponse", "AsyncManagementOperationsWithStreamingResponse", + "FundingEvents", + "AsyncFundingEvents", + "FundingEventsWithRawResponse", + "AsyncFundingEventsWithRawResponse", + "FundingEventsWithStreamingResponse", + "AsyncFundingEventsWithStreamingResponse", ] diff --git a/src/lithic/resources/cards/cards.py b/src/lithic/resources/cards/cards.py index caba9a30..231704c7 100644 --- a/src/lithic/resources/cards/cards.py +++ b/src/lithic/resources/cards/cards.py @@ -25,6 +25,7 @@ card_provision_params, card_get_embed_url_params, card_search_by_pan_params, + card_web_provision_params, card_convert_physical_params, ) from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven, Base64FileInput @@ -64,6 +65,7 @@ from ...types.spend_limit_duration import SpendLimitDuration from ...types.shared_params.carrier import Carrier from ...types.card_provision_response import CardProvisionResponse +from ...types.card_web_provision_response import CardWebProvisionResponse from ...types.shared_params.shipping_address import ShippingAddress __all__ = ["Cards", "AsyncCards"] @@ -1059,6 +1061,48 @@ def search_by_pan( cast_to=Card, ) + def web_provision( + self, + card_token: str, + *, + digital_wallet: Literal["APPLE_PAY"] | 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, + ) -> CardWebProvisionResponse: + """ + Allow your cardholders to directly add payment cards to the device's digital + wallet from a browser on the web. Currently only suported for Apple Pay. + + This requires some additional setup and configuration. Please + [Contact Us](https://lithic.com/contact) or your Customer Success representative + for more information. + + Args: + digital_wallet: Name of digital wallet provider. + + 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 card_token: + raise ValueError(f"Expected a non-empty value for `card_token` but received {card_token!r}") + return self._post( + f"/v1/cards/{card_token}/web_provision", + body=maybe_transform({"digital_wallet": digital_wallet}, card_web_provision_params.CardWebProvisionParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=CardWebProvisionResponse, + ) + class AsyncCards(AsyncAPIResource): @cached_property @@ -2050,6 +2094,50 @@ async def search_by_pan( cast_to=Card, ) + async def web_provision( + self, + card_token: str, + *, + digital_wallet: Literal["APPLE_PAY"] | 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, + ) -> CardWebProvisionResponse: + """ + Allow your cardholders to directly add payment cards to the device's digital + wallet from a browser on the web. Currently only suported for Apple Pay. + + This requires some additional setup and configuration. Please + [Contact Us](https://lithic.com/contact) or your Customer Success representative + for more information. + + Args: + digital_wallet: Name of digital wallet provider. + + 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 card_token: + raise ValueError(f"Expected a non-empty value for `card_token` but received {card_token!r}") + return await self._post( + f"/v1/cards/{card_token}/web_provision", + body=await async_maybe_transform( + {"digital_wallet": digital_wallet}, card_web_provision_params.CardWebProvisionParams + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=CardWebProvisionResponse, + ) + class CardsWithRawResponse: def __init__(self, cards: Cards) -> None: @@ -2088,6 +2176,9 @@ def __init__(self, cards: Cards) -> None: self.search_by_pan = _legacy_response.to_raw_response_wrapper( cards.search_by_pan, ) + self.web_provision = _legacy_response.to_raw_response_wrapper( + cards.web_provision, + ) @cached_property def aggregate_balances(self) -> AggregateBalancesWithRawResponse: @@ -2139,6 +2230,9 @@ def __init__(self, cards: AsyncCards) -> None: self.search_by_pan = _legacy_response.async_to_raw_response_wrapper( cards.search_by_pan, ) + self.web_provision = _legacy_response.async_to_raw_response_wrapper( + cards.web_provision, + ) @cached_property def aggregate_balances(self) -> AsyncAggregateBalancesWithRawResponse: @@ -2190,6 +2284,9 @@ def __init__(self, cards: Cards) -> None: self.search_by_pan = to_streamed_response_wrapper( cards.search_by_pan, ) + self.web_provision = to_streamed_response_wrapper( + cards.web_provision, + ) @cached_property def aggregate_balances(self) -> AggregateBalancesWithStreamingResponse: @@ -2241,6 +2338,9 @@ def __init__(self, cards: AsyncCards) -> None: self.search_by_pan = async_to_streamed_response_wrapper( cards.search_by_pan, ) + self.web_provision = async_to_streamed_response_wrapper( + cards.web_provision, + ) @cached_property def aggregate_balances(self) -> AsyncAggregateBalancesWithStreamingResponse: diff --git a/src/lithic/resources/funding_events.py b/src/lithic/resources/funding_events.py new file mode 100644 index 00000000..1785d641 --- /dev/null +++ b/src/lithic/resources/funding_events.py @@ -0,0 +1,368 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import httpx + +from .. import _legacy_response +from ..types import funding_event_list_params +from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from .._utils import maybe_transform +from .._compat import cached_property +from .._resource import SyncAPIResource, AsyncAPIResource +from .._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper +from ..pagination import SyncCursorPage, AsyncCursorPage +from .._base_client import AsyncPaginator, make_request_options +from ..types.funding_event_list_response import FundingEventListResponse +from ..types.funding_event_retrieve_response import FundingEventRetrieveResponse +from ..types.funding_event_retrieve_details_response import FundingEventRetrieveDetailsResponse + +__all__ = ["FundingEvents", "AsyncFundingEvents"] + + +class FundingEvents(SyncAPIResource): + @cached_property + def with_raw_response(self) -> FundingEventsWithRawResponse: + """ + 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 FundingEventsWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> FundingEventsWithStreamingResponse: + """ + 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 FundingEventsWithStreamingResponse(self) + + def retrieve( + self, + funding_event_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, + ) -> FundingEventRetrieveResponse: + """ + Get funding event for program by id + + 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 funding_event_token: + raise ValueError( + f"Expected a non-empty value for `funding_event_token` but received {funding_event_token!r}" + ) + return self._get( + f"/v1/funding_events/{funding_event_token}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=FundingEventRetrieveResponse, + ) + + def list( + self, + *, + ending_before: str | NotGiven = NOT_GIVEN, + page_size: int | NotGiven = NOT_GIVEN, + starting_after: 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, + ) -> SyncCursorPage[FundingEventListResponse]: + """ + Get all funding events for program + + Args: + ending_before: A cursor representing an item's token before which a page of results should end. + Used to retrieve the previous page of results before this item. + + page_size: Page size (for pagination). + + starting_after: A cursor representing an item's token after which a page of results should + begin. Used to retrieve the next page of results after this item. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._get_api_list( + "/v1/funding_events", + page=SyncCursorPage[FundingEventListResponse], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "ending_before": ending_before, + "page_size": page_size, + "starting_after": starting_after, + }, + funding_event_list_params.FundingEventListParams, + ), + ), + model=FundingEventListResponse, + ) + + def retrieve_details( + self, + funding_event_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, + ) -> FundingEventRetrieveDetailsResponse: + """ + Get funding event details by id + + 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 funding_event_token: + raise ValueError( + f"Expected a non-empty value for `funding_event_token` but received {funding_event_token!r}" + ) + return self._get( + f"/v1/funding_events/{funding_event_token}/details", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=FundingEventRetrieveDetailsResponse, + ) + + +class AsyncFundingEvents(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncFundingEventsWithRawResponse: + """ + 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 AsyncFundingEventsWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncFundingEventsWithStreamingResponse: + """ + 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 AsyncFundingEventsWithStreamingResponse(self) + + async def retrieve( + self, + funding_event_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, + ) -> FundingEventRetrieveResponse: + """ + Get funding event for program by id + + 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 funding_event_token: + raise ValueError( + f"Expected a non-empty value for `funding_event_token` but received {funding_event_token!r}" + ) + return await self._get( + f"/v1/funding_events/{funding_event_token}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=FundingEventRetrieveResponse, + ) + + def list( + self, + *, + ending_before: str | NotGiven = NOT_GIVEN, + page_size: int | NotGiven = NOT_GIVEN, + starting_after: 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, + ) -> AsyncPaginator[FundingEventListResponse, AsyncCursorPage[FundingEventListResponse]]: + """ + Get all funding events for program + + Args: + ending_before: A cursor representing an item's token before which a page of results should end. + Used to retrieve the previous page of results before this item. + + page_size: Page size (for pagination). + + starting_after: A cursor representing an item's token after which a page of results should + begin. Used to retrieve the next page of results after this item. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._get_api_list( + "/v1/funding_events", + page=AsyncCursorPage[FundingEventListResponse], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "ending_before": ending_before, + "page_size": page_size, + "starting_after": starting_after, + }, + funding_event_list_params.FundingEventListParams, + ), + ), + model=FundingEventListResponse, + ) + + async def retrieve_details( + self, + funding_event_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, + ) -> FundingEventRetrieveDetailsResponse: + """ + Get funding event details by id + + 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 funding_event_token: + raise ValueError( + f"Expected a non-empty value for `funding_event_token` but received {funding_event_token!r}" + ) + return await self._get( + f"/v1/funding_events/{funding_event_token}/details", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=FundingEventRetrieveDetailsResponse, + ) + + +class FundingEventsWithRawResponse: + def __init__(self, funding_events: FundingEvents) -> None: + self._funding_events = funding_events + + self.retrieve = _legacy_response.to_raw_response_wrapper( + funding_events.retrieve, + ) + self.list = _legacy_response.to_raw_response_wrapper( + funding_events.list, + ) + self.retrieve_details = _legacy_response.to_raw_response_wrapper( + funding_events.retrieve_details, + ) + + +class AsyncFundingEventsWithRawResponse: + def __init__(self, funding_events: AsyncFundingEvents) -> None: + self._funding_events = funding_events + + self.retrieve = _legacy_response.async_to_raw_response_wrapper( + funding_events.retrieve, + ) + self.list = _legacy_response.async_to_raw_response_wrapper( + funding_events.list, + ) + self.retrieve_details = _legacy_response.async_to_raw_response_wrapper( + funding_events.retrieve_details, + ) + + +class FundingEventsWithStreamingResponse: + def __init__(self, funding_events: FundingEvents) -> None: + self._funding_events = funding_events + + self.retrieve = to_streamed_response_wrapper( + funding_events.retrieve, + ) + self.list = to_streamed_response_wrapper( + funding_events.list, + ) + self.retrieve_details = to_streamed_response_wrapper( + funding_events.retrieve_details, + ) + + +class AsyncFundingEventsWithStreamingResponse: + def __init__(self, funding_events: AsyncFundingEvents) -> None: + self._funding_events = funding_events + + self.retrieve = async_to_streamed_response_wrapper( + funding_events.retrieve, + ) + self.list = async_to_streamed_response_wrapper( + funding_events.list, + ) + self.retrieve_details = async_to_streamed_response_wrapper( + funding_events.retrieve_details, + ) diff --git a/src/lithic/types/__init__.py b/src/lithic/types/__init__.py index f29b77ba..250e25de 100644 --- a/src/lithic/types/__init__.py +++ b/src/lithic/types/__init__.py @@ -74,12 +74,16 @@ from .book_transfer_list_params import BookTransferListParams as BookTransferListParams from .card_get_embed_url_params import CardGetEmbedURLParams as CardGetEmbedURLParams from .card_search_by_pan_params import CardSearchByPanParams as CardSearchByPanParams +from .card_web_provision_params import CardWebProvisionParams as CardWebProvisionParams +from .funding_event_list_params import FundingEventListParams as FundingEventListParams from .responder_endpoint_status import ResponderEndpointStatus as ResponderEndpointStatus from .account_holder_list_params import AccountHolderListParams as AccountHolderListParams from .card_get_embed_html_params import CardGetEmbedHTMLParams as CardGetEmbedHTMLParams from .event_list_attempts_params import EventListAttemptsParams as EventListAttemptsParams from .settlement_summary_details import SettlementSummaryDetails as SettlementSummaryDetails from .book_transfer_create_params import BookTransferCreateParams as BookTransferCreateParams +from .card_web_provision_response import CardWebProvisionResponse as CardWebProvisionResponse +from .funding_event_list_response import FundingEventListResponse as FundingEventListResponse from .account_holder_create_params import AccountHolderCreateParams as AccountHolderCreateParams from .account_holder_update_params import AccountHolderUpdateParams as AccountHolderUpdateParams from .book_transfer_reverse_params import BookTransferReverseParams as BookTransferReverseParams @@ -104,6 +108,7 @@ from .external_payment_reverse_params import ExternalPaymentReverseParams as ExternalPaymentReverseParams from .financial_account_create_params import FinancialAccountCreateParams as FinancialAccountCreateParams from .financial_account_update_params import FinancialAccountUpdateParams as FinancialAccountUpdateParams +from .funding_event_retrieve_response import FundingEventRetrieveResponse as FundingEventRetrieveResponse from .payment_simulate_receipt_params import PaymentSimulateReceiptParams as PaymentSimulateReceiptParams from .payment_simulate_release_params import PaymentSimulateReleaseParams as PaymentSimulateReleaseParams from .management_operation_list_params import ManagementOperationListParams as ManagementOperationListParams @@ -154,6 +159,9 @@ from .external_bank_account_retrieve_response import ( ExternalBankAccountRetrieveResponse as ExternalBankAccountRetrieveResponse, ) +from .funding_event_retrieve_details_response import ( + FundingEventRetrieveDetailsResponse as FundingEventRetrieveDetailsResponse, +) from .transaction_simulate_authorization_params import ( TransactionSimulateAuthorizationParams as TransactionSimulateAuthorizationParams, ) diff --git a/src/lithic/types/card_web_provision_params.py b/src/lithic/types/card_web_provision_params.py new file mode 100644 index 00000000..d294cd3f --- /dev/null +++ b/src/lithic/types/card_web_provision_params.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, TypedDict + +__all__ = ["CardWebProvisionParams"] + + +class CardWebProvisionParams(TypedDict, total=False): + digital_wallet: Literal["APPLE_PAY"] + """Name of digital wallet provider.""" diff --git a/src/lithic/types/card_web_provision_response.py b/src/lithic/types/card_web_provision_response.py new file mode 100644 index 00000000..864d0e64 --- /dev/null +++ b/src/lithic/types/card_web_provision_response.py @@ -0,0 +1,40 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional + +from .._models import BaseModel + +__all__ = ["CardWebProvisionResponse", "Jws", "JwsHeader"] + + +class JwsHeader(BaseModel): + kid: Optional[str] = None + """The ID for the JWS Public Key of the key pair used to generate the signature.""" + + +class Jws(BaseModel): + header: Optional[JwsHeader] = None + """ + JWS unprotected headers containing header parameters that aren't + integrity-protected by the JWS signature. + """ + + payload: Optional[str] = None + """Base64url encoded JSON object containing the provisioning payload.""" + + protected: Optional[str] = None + """ + Base64url encoded JWS protected headers containing the header parameters that + are integrity-protected by the JWS signature. + """ + + signature: Optional[str] = None + """Base64url encoded signature of the JWS object.""" + + +class CardWebProvisionResponse(BaseModel): + jws: Optional[Jws] = None + """JWS object required for handoff to Apple's script.""" + + state: Optional[str] = None + """A unique identifier for the JWS object.""" diff --git a/src/lithic/types/funding_event_list_params.py b/src/lithic/types/funding_event_list_params.py new file mode 100644 index 00000000..4ff35b55 --- /dev/null +++ b/src/lithic/types/funding_event_list_params.py @@ -0,0 +1,25 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import TypedDict + +__all__ = ["FundingEventListParams"] + + +class FundingEventListParams(TypedDict, total=False): + ending_before: str + """A cursor representing an item's token before which a page of results should end. + + Used to retrieve the previous page of results before this item. + """ + + page_size: int + """Page size (for pagination).""" + + starting_after: str + """A cursor representing an item's token after which a page of results should + begin. + + Used to retrieve the next page of results after this item. + """ diff --git a/src/lithic/types/funding_event_list_response.py b/src/lithic/types/funding_event_list_response.py new file mode 100644 index 00000000..83496225 --- /dev/null +++ b/src/lithic/types/funding_event_list_response.py @@ -0,0 +1,41 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List +from datetime import date, datetime +from typing_extensions import Literal + +from .._models import BaseModel + +__all__ = ["FundingEventListResponse", "SettlementBreakdown"] + + +class SettlementBreakdown(BaseModel): + amount: int + + settlement_date: date + + +class FundingEventListResponse(BaseModel): + token: str + """Unique token ID""" + + collection_resource_type: Literal["BOOK_TRANSFER", "PAYMENT"] + """Collection resource type""" + + collection_tokens: List[str] + """IDs of collections""" + + created: datetime + """Time of the creation""" + + high_watermark: datetime + """Time of the high watermark""" + + previous_high_watermark: datetime + """Time of the previous high watermark""" + + settlement_breakdowns: List[SettlementBreakdown] + """List of settlements""" + + updated: datetime + """Time of the update""" diff --git a/src/lithic/types/funding_event_retrieve_details_response.py b/src/lithic/types/funding_event_retrieve_details_response.py new file mode 100644 index 00000000..df71850b --- /dev/null +++ b/src/lithic/types/funding_event_retrieve_details_response.py @@ -0,0 +1,16 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .._models import BaseModel + +__all__ = ["FundingEventRetrieveDetailsResponse"] + + +class FundingEventRetrieveDetailsResponse(BaseModel): + token: str + """Unique token ID""" + + settlement_details_url: str + """URL of the settlement details""" + + settlement_summary_url: str + """URL of the settlement summary""" diff --git a/src/lithic/types/funding_event_retrieve_response.py b/src/lithic/types/funding_event_retrieve_response.py new file mode 100644 index 00000000..bbac458a --- /dev/null +++ b/src/lithic/types/funding_event_retrieve_response.py @@ -0,0 +1,41 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List +from datetime import date, datetime +from typing_extensions import Literal + +from .._models import BaseModel + +__all__ = ["FundingEventRetrieveResponse", "SettlementBreakdown"] + + +class SettlementBreakdown(BaseModel): + amount: int + + settlement_date: date + + +class FundingEventRetrieveResponse(BaseModel): + token: str + """Unique token ID""" + + collection_resource_type: Literal["BOOK_TRANSFER", "PAYMENT"] + """Collection resource type""" + + collection_tokens: List[str] + """IDs of collections""" + + created: datetime + """Time of the creation""" + + high_watermark: datetime + """Time of the high watermark""" + + previous_high_watermark: datetime + """Time of the previous high watermark""" + + settlement_breakdowns: List[SettlementBreakdown] + """List of settlements""" + + updated: datetime + """Time of the update""" diff --git a/tests/api_resources/test_cards.py b/tests/api_resources/test_cards.py index cfc20f69..b537a90a 100644 --- a/tests/api_resources/test_cards.py +++ b/tests/api_resources/test_cards.py @@ -14,6 +14,7 @@ NonPCICard, CardSpendLimits, CardProvisionResponse, + CardWebProvisionResponse, ) from lithic._utils import parse_datetime from lithic.pagination import SyncCursorPage, AsyncCursorPage @@ -642,6 +643,52 @@ def test_streaming_response_search_by_pan(self, client: Lithic) -> None: assert cast(Any, response.is_closed) is True + @parametrize + def test_method_web_provision(self, client: Lithic) -> None: + card = client.cards.web_provision( + card_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert_matches_type(CardWebProvisionResponse, card, path=["response"]) + + @parametrize + def test_method_web_provision_with_all_params(self, client: Lithic) -> None: + card = client.cards.web_provision( + card_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + digital_wallet="APPLE_PAY", + ) + assert_matches_type(CardWebProvisionResponse, card, path=["response"]) + + @parametrize + def test_raw_response_web_provision(self, client: Lithic) -> None: + response = client.cards.with_raw_response.web_provision( + card_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + card = response.parse() + assert_matches_type(CardWebProvisionResponse, card, path=["response"]) + + @parametrize + def test_streaming_response_web_provision(self, client: Lithic) -> None: + with client.cards.with_streaming_response.web_provision( + card_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + card = response.parse() + assert_matches_type(CardWebProvisionResponse, card, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_web_provision(self, client: Lithic) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `card_token` but received ''"): + client.cards.with_raw_response.web_provision( + card_token="", + ) + class TestAsyncCards: parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) @@ -1263,3 +1310,49 @@ async def test_streaming_response_search_by_pan(self, async_client: AsyncLithic) assert_matches_type(Card, card, path=["response"]) assert cast(Any, response.is_closed) is True + + @parametrize + async def test_method_web_provision(self, async_client: AsyncLithic) -> None: + card = await async_client.cards.web_provision( + card_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert_matches_type(CardWebProvisionResponse, card, path=["response"]) + + @parametrize + async def test_method_web_provision_with_all_params(self, async_client: AsyncLithic) -> None: + card = await async_client.cards.web_provision( + card_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + digital_wallet="APPLE_PAY", + ) + assert_matches_type(CardWebProvisionResponse, card, path=["response"]) + + @parametrize + async def test_raw_response_web_provision(self, async_client: AsyncLithic) -> None: + response = await async_client.cards.with_raw_response.web_provision( + card_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + card = response.parse() + assert_matches_type(CardWebProvisionResponse, card, path=["response"]) + + @parametrize + async def test_streaming_response_web_provision(self, async_client: AsyncLithic) -> None: + async with async_client.cards.with_streaming_response.web_provision( + card_token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + card = await response.parse() + assert_matches_type(CardWebProvisionResponse, card, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_web_provision(self, async_client: AsyncLithic) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `card_token` but received ''"): + await async_client.cards.with_raw_response.web_provision( + card_token="", + ) diff --git a/tests/api_resources/test_funding_events.py b/tests/api_resources/test_funding_events.py new file mode 100644 index 00000000..62c547e8 --- /dev/null +++ b/tests/api_resources/test_funding_events.py @@ -0,0 +1,247 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from lithic import Lithic, AsyncLithic +from tests.utils import assert_matches_type +from lithic.types import ( + FundingEventListResponse, + FundingEventRetrieveResponse, + FundingEventRetrieveDetailsResponse, +) +from lithic.pagination import SyncCursorPage, AsyncCursorPage + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestFundingEvents: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_retrieve(self, client: Lithic) -> None: + funding_event = client.funding_events.retrieve( + "funding_event_token", + ) + assert_matches_type(FundingEventRetrieveResponse, funding_event, path=["response"]) + + @parametrize + def test_raw_response_retrieve(self, client: Lithic) -> None: + response = client.funding_events.with_raw_response.retrieve( + "funding_event_token", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + funding_event = response.parse() + assert_matches_type(FundingEventRetrieveResponse, funding_event, path=["response"]) + + @parametrize + def test_streaming_response_retrieve(self, client: Lithic) -> None: + with client.funding_events.with_streaming_response.retrieve( + "funding_event_token", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + funding_event = response.parse() + assert_matches_type(FundingEventRetrieveResponse, funding_event, 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 `funding_event_token` but received ''"): + client.funding_events.with_raw_response.retrieve( + "", + ) + + @parametrize + def test_method_list(self, client: Lithic) -> None: + funding_event = client.funding_events.list() + assert_matches_type(SyncCursorPage[FundingEventListResponse], funding_event, path=["response"]) + + @parametrize + def test_method_list_with_all_params(self, client: Lithic) -> None: + funding_event = client.funding_events.list( + ending_before="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + page_size=1, + starting_after="starting_after", + ) + assert_matches_type(SyncCursorPage[FundingEventListResponse], funding_event, path=["response"]) + + @parametrize + def test_raw_response_list(self, client: Lithic) -> None: + response = client.funding_events.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + funding_event = response.parse() + assert_matches_type(SyncCursorPage[FundingEventListResponse], funding_event, path=["response"]) + + @parametrize + def test_streaming_response_list(self, client: Lithic) -> None: + with client.funding_events.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + funding_event = response.parse() + assert_matches_type(SyncCursorPage[FundingEventListResponse], funding_event, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_method_retrieve_details(self, client: Lithic) -> None: + funding_event = client.funding_events.retrieve_details( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert_matches_type(FundingEventRetrieveDetailsResponse, funding_event, path=["response"]) + + @parametrize + def test_raw_response_retrieve_details(self, client: Lithic) -> None: + response = client.funding_events.with_raw_response.retrieve_details( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + funding_event = response.parse() + assert_matches_type(FundingEventRetrieveDetailsResponse, funding_event, path=["response"]) + + @parametrize + def test_streaming_response_retrieve_details(self, client: Lithic) -> None: + with client.funding_events.with_streaming_response.retrieve_details( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + funding_event = response.parse() + assert_matches_type(FundingEventRetrieveDetailsResponse, funding_event, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_retrieve_details(self, client: Lithic) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `funding_event_token` but received ''"): + client.funding_events.with_raw_response.retrieve_details( + "", + ) + + +class TestAsyncFundingEvents: + parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + async def test_method_retrieve(self, async_client: AsyncLithic) -> None: + funding_event = await async_client.funding_events.retrieve( + "funding_event_token", + ) + assert_matches_type(FundingEventRetrieveResponse, funding_event, path=["response"]) + + @parametrize + async def test_raw_response_retrieve(self, async_client: AsyncLithic) -> None: + response = await async_client.funding_events.with_raw_response.retrieve( + "funding_event_token", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + funding_event = response.parse() + assert_matches_type(FundingEventRetrieveResponse, funding_event, path=["response"]) + + @parametrize + async def test_streaming_response_retrieve(self, async_client: AsyncLithic) -> None: + async with async_client.funding_events.with_streaming_response.retrieve( + "funding_event_token", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + funding_event = await response.parse() + assert_matches_type(FundingEventRetrieveResponse, funding_event, 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 `funding_event_token` but received ''"): + await async_client.funding_events.with_raw_response.retrieve( + "", + ) + + @parametrize + async def test_method_list(self, async_client: AsyncLithic) -> None: + funding_event = await async_client.funding_events.list() + assert_matches_type(AsyncCursorPage[FundingEventListResponse], funding_event, path=["response"]) + + @parametrize + async def test_method_list_with_all_params(self, async_client: AsyncLithic) -> None: + funding_event = await async_client.funding_events.list( + ending_before="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + page_size=1, + starting_after="starting_after", + ) + assert_matches_type(AsyncCursorPage[FundingEventListResponse], funding_event, path=["response"]) + + @parametrize + async def test_raw_response_list(self, async_client: AsyncLithic) -> None: + response = await async_client.funding_events.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + funding_event = response.parse() + assert_matches_type(AsyncCursorPage[FundingEventListResponse], funding_event, path=["response"]) + + @parametrize + async def test_streaming_response_list(self, async_client: AsyncLithic) -> None: + async with async_client.funding_events.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + funding_event = await response.parse() + assert_matches_type(AsyncCursorPage[FundingEventListResponse], funding_event, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_method_retrieve_details(self, async_client: AsyncLithic) -> None: + funding_event = await async_client.funding_events.retrieve_details( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert_matches_type(FundingEventRetrieveDetailsResponse, funding_event, path=["response"]) + + @parametrize + async def test_raw_response_retrieve_details(self, async_client: AsyncLithic) -> None: + response = await async_client.funding_events.with_raw_response.retrieve_details( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + funding_event = response.parse() + assert_matches_type(FundingEventRetrieveDetailsResponse, funding_event, path=["response"]) + + @parametrize + async def test_streaming_response_retrieve_details(self, async_client: AsyncLithic) -> None: + async with async_client.funding_events.with_streaming_response.retrieve_details( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + funding_event = await response.parse() + assert_matches_type(FundingEventRetrieveDetailsResponse, funding_event, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_retrieve_details(self, async_client: AsyncLithic) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `funding_event_token` but received ''"): + await async_client.funding_events.with_raw_response.retrieve_details( + "", + ) From 0882964277d7cf21b177f2088c00e2c79d312b45 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 14 May 2025 23:12:17 +0000 Subject: [PATCH 2/4] chore(ci): upload sdks to package manager --- .github/workflows/ci.yml | 24 ++++++++++++++++++++++++ scripts/utils/upload-artifact.sh | 25 +++++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100755 scripts/utils/upload-artifact.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5933e3b2..55f660df 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,6 +30,30 @@ jobs: - name: Run lints run: ./scripts/lint + upload: + if: github.repository == 'stainless-sdks/lithic-python' + timeout-minutes: 10 + name: upload + permissions: + contents: read + id-token: write + runs-on: depot-ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + + - name: Get GitHub OIDC Token + id: github-oidc + uses: actions/github-script@v6 + with: + script: core.setOutput('github_token', await core.getIDToken()); + + - name: Upload tarball + env: + URL: https://pkg.stainless.com/s + AUTH: ${{ steps.github-oidc.outputs.github_token }} + SHA: ${{ github.sha }} + run: ./scripts/utils/upload-artifact.sh + test: timeout-minutes: 10 name: test diff --git a/scripts/utils/upload-artifact.sh b/scripts/utils/upload-artifact.sh new file mode 100755 index 00000000..696450e6 --- /dev/null +++ b/scripts/utils/upload-artifact.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +set -exuo pipefail + +RESPONSE=$(curl -X POST "$URL" \ + -H "Authorization: Bearer $AUTH" \ + -H "Content-Type: application/json") + +SIGNED_URL=$(echo "$RESPONSE" | jq -r '.url') + +if [[ "$SIGNED_URL" == "null" ]]; then + echo -e "\033[31mFailed to get signed URL.\033[0m" + exit 1 +fi + +UPLOAD_RESPONSE=$(tar -cz . | curl -v -X PUT \ + -H "Content-Type: application/gzip" \ + --data-binary @- "$SIGNED_URL" 2>&1) + +if echo "$UPLOAD_RESPONSE" | grep -q "HTTP/[0-9.]* 200"; then + echo -e "\033[32mUploaded build to Stainless storage.\033[0m" + echo -e "\033[32mInstallation: npm install 'https://pkg.stainless.com/s/lithic-python/$SHA'\033[0m" +else + echo -e "\033[31mFailed to upload artifact.\033[0m" + exit 1 +fi From bd6929642e12a8dac9a208163def5f331a8dc6a9 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 15 May 2025 12:29:15 +0000 Subject: [PATCH 3/4] chore(ci): fix installation instructions --- scripts/utils/upload-artifact.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/utils/upload-artifact.sh b/scripts/utils/upload-artifact.sh index 696450e6..6a927c77 100755 --- a/scripts/utils/upload-artifact.sh +++ b/scripts/utils/upload-artifact.sh @@ -18,7 +18,7 @@ UPLOAD_RESPONSE=$(tar -cz . | curl -v -X PUT \ if echo "$UPLOAD_RESPONSE" | grep -q "HTTP/[0-9.]* 200"; then echo -e "\033[32mUploaded build to Stainless storage.\033[0m" - echo -e "\033[32mInstallation: npm install 'https://pkg.stainless.com/s/lithic-python/$SHA'\033[0m" + echo -e "\033[32mInstallation: pip install 'https://pkg.stainless.com/s/lithic-python/$SHA'\033[0m" else echo -e "\033[31mFailed to upload artifact.\033[0m" exit 1 From 51386171a0df826ab22a26e8ea23ceffb7d0fd36 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 15 May 2025 17:07:11 +0000 Subject: [PATCH 4/4] release: 0.93.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 14 ++++++++++++++ pyproject.toml | 2 +- src/lithic/_version.py | 2 +- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 0114ce37..c486f6de 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.92.0" + ".": "0.93.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d400bcd..1deb08c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +## 0.93.0 (2025-05-15) + +Full Changelog: [v0.92.0...v0.93.0](https://github.com/lithic-com/lithic-python/compare/v0.92.0...v0.93.0) + +### Features + +* **api:** new Funding Events and Card Web Provision API's ([324431e](https://github.com/lithic-com/lithic-python/commit/324431e3c83e7d89f93306900efb800ce1d9a594)) + + +### Chores + +* **ci:** fix installation instructions ([bd69296](https://github.com/lithic-com/lithic-python/commit/bd6929642e12a8dac9a208163def5f331a8dc6a9)) +* **ci:** upload sdks to package manager ([0882964](https://github.com/lithic-com/lithic-python/commit/0882964277d7cf21b177f2088c00e2c79d312b45)) + ## 0.92.0 (2025-05-12) Full Changelog: [v0.91.2...v0.92.0](https://github.com/lithic-com/lithic-python/compare/v0.91.2...v0.92.0) diff --git a/pyproject.toml b/pyproject.toml index 9d650a5f..29217aae 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "lithic" -version = "0.92.0" +version = "0.93.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 b187bc34..284c0a6a 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.92.0" # x-release-please-version +__version__ = "0.93.0" # x-release-please-version