diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 12536a15..1eb44122 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.504.0" + ".": "0.505.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 074cbe61..7c192972 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 237 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/increase/increase-bd2f5c49181098955f0dbdee1511e28d4a8b9d2a16433f747defd59430bb961f.yml -openapi_spec_hash: 206afcc5ec5f6294d1f185ee808d675c -config_hash: b4f1725275c973bb61f07d1bdc2b71d5 +configured_endpoints: 238 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/increase/increase-f0841004cde131703a9fc63fec3ae9ce98b63f0e8fe8d4326d1d75142538eda3.yml +openapi_spec_hash: a5a1e052b6e09ba465311f8adfcf9429 +config_hash: 060e036e1db198f2e908364c9df7096e diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e05a8f7..689d0549 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## 0.505.0 (2026-05-01) + +Full Changelog: [v0.504.0...v0.505.0](https://github.com/Increase/increase-python/compare/v0.504.0...v0.505.0) + +### Features + +* **api:** api update ([15fbe34](https://github.com/Increase/increase-python/commit/15fbe340cb30736c7ff9e9fca7f959d479f5585a)) + + +### Chores + +* **internal:** reformat pyproject.toml ([2a79116](https://github.com/Increase/increase-python/commit/2a7911612faff9b184125af63a7b262b9f999070)) + ## 0.504.0 (2026-04-30) Full Changelog: [v0.503.0...v0.504.0](https://github.com/Increase/increase-python/compare/v0.503.0...v0.504.0) diff --git a/api.md b/api.md index f4b83ffa..392bca82 100644 --- a/api.md +++ b/api.md @@ -1005,6 +1005,12 @@ Methods: - client.simulations.inbound_mail_items.create(\*\*params) -> InboundMailItem +## Entities + +Methods: + +- client.simulations.entities.validation(entity_id, \*\*params) -> Entity + ## EntityOnboardingSessions Methods: diff --git a/pyproject.toml b/pyproject.toml index 3047c9dd..9c6b748b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "increase" -version = "0.504.0" +version = "0.505.0" description = "The official Python library for the increase API" dynamic = ["readme"] license = "Apache-2.0" @@ -169,7 +169,7 @@ show_error_codes = true # # We also exclude our `tests` as mypy doesn't always infer # types correctly and Pyright will still catch any type errors. -exclude = ['src/increase/_files.py', '_dev/.*.py', 'tests/.*'] +exclude = ["src/increase/_files.py", "_dev/.*.py", "tests/.*"] strict_equality = true implicit_reexport = true diff --git a/src/increase/_version.py b/src/increase/_version.py index 55065c42..7486f0c2 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.504.0" # x-release-please-version +__version__ = "0.505.0" # x-release-please-version diff --git a/src/increase/resources/simulations/__init__.py b/src/increase/resources/simulations/__init__.py index c50416e6..a5d6bccf 100644 --- a/src/increase/resources/simulations/__init__.py +++ b/src/increase/resources/simulations/__init__.py @@ -8,6 +8,14 @@ ExportsResourceWithStreamingResponse, AsyncExportsResourceWithStreamingResponse, ) +from .entities import ( + EntitiesResource, + AsyncEntitiesResource, + EntitiesResourceWithRawResponse, + AsyncEntitiesResourceWithRawResponse, + EntitiesResourceWithStreamingResponse, + AsyncEntitiesResourceWithStreamingResponse, +) from .programs import ( ProgramsResource, AsyncProgramsResource, @@ -456,6 +464,12 @@ "AsyncInboundMailItemsResourceWithRawResponse", "InboundMailItemsResourceWithStreamingResponse", "AsyncInboundMailItemsResourceWithStreamingResponse", + "EntitiesResource", + "AsyncEntitiesResource", + "EntitiesResourceWithRawResponse", + "AsyncEntitiesResourceWithRawResponse", + "EntitiesResourceWithStreamingResponse", + "AsyncEntitiesResourceWithStreamingResponse", "EntityOnboardingSessionsResource", "AsyncEntityOnboardingSessionsResource", "EntityOnboardingSessionsResourceWithRawResponse", diff --git a/src/increase/resources/simulations/entities.py b/src/increase/resources/simulations/entities.py new file mode 100644 index 00000000..be931078 --- /dev/null +++ b/src/increase/resources/simulations/entities.py @@ -0,0 +1,224 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Iterable +from typing_extensions import Literal + +import httpx + +from ..._types import Body, Query, Headers, NotGiven, not_given +from ..._utils import path_template, maybe_transform, async_maybe_transform +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ..._base_client import make_request_options +from ...types.entity import Entity +from ...types.simulations import entity_validation_params + +__all__ = ["EntitiesResource", "AsyncEntitiesResource"] + + +class EntitiesResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> EntitiesResourceWithRawResponse: + """ + 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/Increase/increase-python#accessing-raw-response-data-eg-headers + """ + return EntitiesResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> EntitiesResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/Increase/increase-python#with_streaming_response + """ + return EntitiesResourceWithStreamingResponse(self) + + def validation( + self, + entity_id: str, + *, + issues: Iterable[entity_validation_params.Issue], + status: Literal["valid", "invalid", "pending"], + # 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, + ) -> Entity: + """ + Simulates setting an [Entity](#entities)'s validation under the managed + compliance regime. Any existing managed compliance validation on the Entity will + be marked as no longer current. + + Args: + entity_id: The identifier of the Entity to set the validation on. + + issues: The issues to attach to the new managed compliance validation. + + status: The status to set on the new managed compliance validation. + + - `valid` - The submitted data is valid. + - `invalid` - Additional information is required to validate the data. + - `pending` - The submitted data is being validated. + + 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 entity_id: + raise ValueError(f"Expected a non-empty value for `entity_id` but received {entity_id!r}") + return self._post( + path_template("/simulations/entities/{entity_id}/validation", entity_id=entity_id), + body=maybe_transform( + { + "issues": issues, + "status": status, + }, + entity_validation_params.EntityValidationParams, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=Entity, + ) + + +class AsyncEntitiesResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncEntitiesResourceWithRawResponse: + """ + 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/Increase/increase-python#accessing-raw-response-data-eg-headers + """ + return AsyncEntitiesResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncEntitiesResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/Increase/increase-python#with_streaming_response + """ + return AsyncEntitiesResourceWithStreamingResponse(self) + + async def validation( + self, + entity_id: str, + *, + issues: Iterable[entity_validation_params.Issue], + status: Literal["valid", "invalid", "pending"], + # 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, + ) -> Entity: + """ + Simulates setting an [Entity](#entities)'s validation under the managed + compliance regime. Any existing managed compliance validation on the Entity will + be marked as no longer current. + + Args: + entity_id: The identifier of the Entity to set the validation on. + + issues: The issues to attach to the new managed compliance validation. + + status: The status to set on the new managed compliance validation. + + - `valid` - The submitted data is valid. + - `invalid` - Additional information is required to validate the data. + - `pending` - The submitted data is being validated. + + 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 entity_id: + raise ValueError(f"Expected a non-empty value for `entity_id` but received {entity_id!r}") + return await self._post( + path_template("/simulations/entities/{entity_id}/validation", entity_id=entity_id), + body=await async_maybe_transform( + { + "issues": issues, + "status": status, + }, + entity_validation_params.EntityValidationParams, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=Entity, + ) + + +class EntitiesResourceWithRawResponse: + def __init__(self, entities: EntitiesResource) -> None: + self._entities = entities + + self.validation = to_raw_response_wrapper( + entities.validation, + ) + + +class AsyncEntitiesResourceWithRawResponse: + def __init__(self, entities: AsyncEntitiesResource) -> None: + self._entities = entities + + self.validation = async_to_raw_response_wrapper( + entities.validation, + ) + + +class EntitiesResourceWithStreamingResponse: + def __init__(self, entities: EntitiesResource) -> None: + self._entities = entities + + self.validation = to_streamed_response_wrapper( + entities.validation, + ) + + +class AsyncEntitiesResourceWithStreamingResponse: + def __init__(self, entities: AsyncEntitiesResource) -> None: + self._entities = entities + + self.validation = async_to_streamed_response_wrapper( + entities.validation, + ) diff --git a/src/increase/resources/simulations/simulations.py b/src/increase/resources/simulations/simulations.py index 3a2a9b76..dfe7848c 100644 --- a/src/increase/resources/simulations/simulations.py +++ b/src/increase/resources/simulations/simulations.py @@ -10,6 +10,14 @@ ExportsResourceWithStreamingResponse, AsyncExportsResourceWithStreamingResponse, ) +from .entities import ( + EntitiesResource, + AsyncEntitiesResource, + EntitiesResourceWithRawResponse, + AsyncEntitiesResourceWithRawResponse, + EntitiesResourceWithStreamingResponse, + AsyncEntitiesResourceWithStreamingResponse, +) from .programs import ( ProgramsResource, AsyncProgramsResource, @@ -397,6 +405,10 @@ def check_deposits(self) -> CheckDepositsResource: def inbound_mail_items(self) -> InboundMailItemsResource: return InboundMailItemsResource(self._client) + @cached_property + def entities(self) -> EntitiesResource: + return EntitiesResource(self._client) + @cached_property def entity_onboarding_sessions(self) -> EntityOnboardingSessionsResource: return EntityOnboardingSessionsResource(self._client) @@ -554,6 +566,10 @@ def check_deposits(self) -> AsyncCheckDepositsResource: def inbound_mail_items(self) -> AsyncInboundMailItemsResource: return AsyncInboundMailItemsResource(self._client) + @cached_property + def entities(self) -> AsyncEntitiesResource: + return AsyncEntitiesResource(self._client) + @cached_property def entity_onboarding_sessions(self) -> AsyncEntityOnboardingSessionsResource: return AsyncEntityOnboardingSessionsResource(self._client) @@ -716,6 +732,10 @@ def check_deposits(self) -> CheckDepositsResourceWithRawResponse: def inbound_mail_items(self) -> InboundMailItemsResourceWithRawResponse: return InboundMailItemsResourceWithRawResponse(self._simulations.inbound_mail_items) + @cached_property + def entities(self) -> EntitiesResourceWithRawResponse: + return EntitiesResourceWithRawResponse(self._simulations.entities) + @cached_property def entity_onboarding_sessions(self) -> EntityOnboardingSessionsResourceWithRawResponse: return EntityOnboardingSessionsResourceWithRawResponse(self._simulations.entity_onboarding_sessions) @@ -861,6 +881,10 @@ def check_deposits(self) -> AsyncCheckDepositsResourceWithRawResponse: def inbound_mail_items(self) -> AsyncInboundMailItemsResourceWithRawResponse: return AsyncInboundMailItemsResourceWithRawResponse(self._simulations.inbound_mail_items) + @cached_property + def entities(self) -> AsyncEntitiesResourceWithRawResponse: + return AsyncEntitiesResourceWithRawResponse(self._simulations.entities) + @cached_property def entity_onboarding_sessions(self) -> AsyncEntityOnboardingSessionsResourceWithRawResponse: return AsyncEntityOnboardingSessionsResourceWithRawResponse(self._simulations.entity_onboarding_sessions) @@ -1008,6 +1032,10 @@ def check_deposits(self) -> CheckDepositsResourceWithStreamingResponse: def inbound_mail_items(self) -> InboundMailItemsResourceWithStreamingResponse: return InboundMailItemsResourceWithStreamingResponse(self._simulations.inbound_mail_items) + @cached_property + def entities(self) -> EntitiesResourceWithStreamingResponse: + return EntitiesResourceWithStreamingResponse(self._simulations.entities) + @cached_property def entity_onboarding_sessions(self) -> EntityOnboardingSessionsResourceWithStreamingResponse: return EntityOnboardingSessionsResourceWithStreamingResponse(self._simulations.entity_onboarding_sessions) @@ -1161,6 +1189,10 @@ def check_deposits(self) -> AsyncCheckDepositsResourceWithStreamingResponse: def inbound_mail_items(self) -> AsyncInboundMailItemsResourceWithStreamingResponse: return AsyncInboundMailItemsResourceWithStreamingResponse(self._simulations.inbound_mail_items) + @cached_property + def entities(self) -> AsyncEntitiesResourceWithStreamingResponse: + return AsyncEntitiesResourceWithStreamingResponse(self._simulations.entities) + @cached_property def entity_onboarding_sessions(self) -> AsyncEntityOnboardingSessionsResourceWithStreamingResponse: return AsyncEntityOnboardingSessionsResourceWithStreamingResponse(self._simulations.entity_onboarding_sessions) diff --git a/src/increase/types/simulations/__init__.py b/src/increase/types/simulations/__init__.py index f1188796..9de45c70 100644 --- a/src/increase/types/simulations/__init__.py +++ b/src/increase/types/simulations/__init__.py @@ -5,6 +5,7 @@ from .export_create_params import ExportCreateParams as ExportCreateParams from .program_create_params import ProgramCreateParams as ProgramCreateParams from .card_token_create_params import CardTokenCreateParams as CardTokenCreateParams +from .entity_validation_params import EntityValidationParams as EntityValidationParams from .card_refund_create_params import CardRefundCreateParams as CardRefundCreateParams from .ach_transfer_return_params import ACHTransferReturnParams as ACHTransferReturnParams from .ach_transfer_settle_params import ACHTransferSettleParams as ACHTransferSettleParams diff --git a/src/increase/types/simulations/entity_validation_params.py b/src/increase/types/simulations/entity_validation_params.py new file mode 100644 index 00000000..c340a374 --- /dev/null +++ b/src/increase/types/simulations/entity_validation_params.py @@ -0,0 +1,42 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Iterable +from typing_extensions import Literal, Required, TypedDict + +__all__ = ["EntityValidationParams", "Issue"] + + +class EntityValidationParams(TypedDict, total=False): + issues: Required[Iterable[Issue]] + """The issues to attach to the new managed compliance validation.""" + + status: Required[Literal["valid", "invalid", "pending"]] + """The status to set on the new managed compliance validation. + + - `valid` - The submitted data is valid. + - `invalid` - Additional information is required to validate the data. + - `pending` - The submitted data is being validated. + """ + + +class Issue(TypedDict, total=False): + category: Required[ + Literal["entity_tax_identifier", "entity_address", "beneficial_owner_identity", "beneficial_owner_address"] + ] + """The category of the issue. + + - `entity_tax_identifier` - The entity's tax identifier could not be validated. + Update the tax ID with the + [update an entity API](/documentation/api/entities#update-an-entity.corporation.legal_identifier). + - `entity_address` - The entity's address could not be validated. Update the + address with the + [update an entity API](/documentation/api/entities#update-an-entity.corporation.address). + - `beneficial_owner_identity` - A beneficial owner's identity could not be + verified. Update the identification with the + [update a beneficial owner API](/documentation/api/beneficial-owners#update-a-beneficial-owner). + - `beneficial_owner_address` - A beneficial owner's address could not be + validated. Update the address with the + [update a beneficial owner API](/documentation/api/beneficial-owners#update-a-beneficial-owner). + """ diff --git a/tests/api_resources/simulations/test_entities.py b/tests/api_resources/simulations/test_entities.py new file mode 100644 index 00000000..4922cb39 --- /dev/null +++ b/tests/api_resources/simulations/test_entities.py @@ -0,0 +1,116 @@ +# 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 increase import Increase, AsyncIncrease +from tests.utils import assert_matches_type +from increase.types import Entity + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestEntities: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_validation(self, client: Increase) -> None: + entity = client.simulations.entities.validation( + entity_id="entity_n8y8tnk2p9339ti393yi", + issues=[{"category": "entity_tax_identifier"}], + status="invalid", + ) + assert_matches_type(Entity, entity, path=["response"]) + + @parametrize + def test_raw_response_validation(self, client: Increase) -> None: + response = client.simulations.entities.with_raw_response.validation( + entity_id="entity_n8y8tnk2p9339ti393yi", + issues=[{"category": "entity_tax_identifier"}], + status="invalid", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + entity = response.parse() + assert_matches_type(Entity, entity, path=["response"]) + + @parametrize + def test_streaming_response_validation(self, client: Increase) -> None: + with client.simulations.entities.with_streaming_response.validation( + entity_id="entity_n8y8tnk2p9339ti393yi", + issues=[{"category": "entity_tax_identifier"}], + status="invalid", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + entity = response.parse() + assert_matches_type(Entity, entity, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_validation(self, client: Increase) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `entity_id` but received ''"): + client.simulations.entities.with_raw_response.validation( + entity_id="", + issues=[{"category": "entity_tax_identifier"}], + status="invalid", + ) + + +class TestAsyncEntities: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @parametrize + async def test_method_validation(self, async_client: AsyncIncrease) -> None: + entity = await async_client.simulations.entities.validation( + entity_id="entity_n8y8tnk2p9339ti393yi", + issues=[{"category": "entity_tax_identifier"}], + status="invalid", + ) + assert_matches_type(Entity, entity, path=["response"]) + + @parametrize + async def test_raw_response_validation(self, async_client: AsyncIncrease) -> None: + response = await async_client.simulations.entities.with_raw_response.validation( + entity_id="entity_n8y8tnk2p9339ti393yi", + issues=[{"category": "entity_tax_identifier"}], + status="invalid", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + entity = await response.parse() + assert_matches_type(Entity, entity, path=["response"]) + + @parametrize + async def test_streaming_response_validation(self, async_client: AsyncIncrease) -> None: + async with async_client.simulations.entities.with_streaming_response.validation( + entity_id="entity_n8y8tnk2p9339ti393yi", + issues=[{"category": "entity_tax_identifier"}], + status="invalid", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + entity = await response.parse() + assert_matches_type(Entity, entity, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_validation(self, async_client: AsyncIncrease) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `entity_id` but received ''"): + await async_client.simulations.entities.with_raw_response.validation( + entity_id="", + issues=[{"category": "entity_tax_identifier"}], + status="invalid", + )