diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 35197252..1e57fdcd 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.427.0" + ".": "0.428.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 40873533..9d5bfb4e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 234 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/increase%2Fincrease-b42ffa447aa14da70d972676b1d5ad0c2720ff4e33a483037b2b1bb51190a69f.yml -openapi_spec_hash: f2a5c5e804880a8e8d13f5f32ca264a1 -config_hash: b7ec7f54fa76c1f8bde7a548710a1d38 +configured_endpoints: 236 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/increase%2Fincrease-f46fe8b546ee1a4ad24918ef0803f48e6586e061d5445ae1aeb6abc7b8cf64a3.yml +openapi_spec_hash: 440b743a615d5ecc832affd6c3154809 +config_hash: dda988c5565c2f15cc708122984d7691 diff --git a/CHANGELOG.md b/CHANGELOG.md index 13ee7286..34623956 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 0.428.0 (2026-03-10) + +Full Changelog: [v0.427.0...v0.428.0](https://github.com/Increase/increase-python/compare/v0.427.0...v0.428.0) + +### Features + +* **api:** api update ([ef46427](https://github.com/Increase/increase-python/commit/ef46427b26488ea1d2d9d25c441611d816ece3cb)) + ## 0.427.0 (2026-03-09) Full Changelog: [v0.426.0...v0.427.0](https://github.com/Increase/increase-python/compare/v0.426.0...v0.427.0) diff --git a/api.md b/api.md index 89352d53..19a49271 100644 --- a/api.md +++ b/api.md @@ -505,6 +505,19 @@ Methods: - client.entities.create_beneficial_owner(entity_id, \*\*params) -> Entity - client.entities.update_beneficial_owner_address(entity_id, \*\*params) -> Entity +# BeneficialOwners + +Types: + +```python +from increase.types import EntityBeneficialOwner +``` + +Methods: + +- client.beneficial_owners.retrieve(entity_beneficial_owner_id) -> EntityBeneficialOwner +- client.beneficial_owners.list(\*\*params) -> SyncPage[EntityBeneficialOwner] + # SupplementalDocuments Types: diff --git a/pyproject.toml b/pyproject.toml index 1d3d70e9..f122fca6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "increase" -version = "0.427.0" +version = "0.428.0" description = "The official Python library for the increase API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/increase/_client.py b/src/increase/_client.py index 78729401..e6b53fe2 100644 --- a/src/increase/_client.py +++ b/src/increase/_client.py @@ -64,6 +64,7 @@ fednow_transfers, intrafi_balances, account_transfers, + beneficial_owners, external_accounts, oauth_connections, account_statements, @@ -121,6 +122,7 @@ from .resources.fednow_transfers import FednowTransfersResource, AsyncFednowTransfersResource from .resources.intrafi_balances import IntrafiBalancesResource, AsyncIntrafiBalancesResource from .resources.account_transfers import AccountTransfersResource, AsyncAccountTransfersResource + from .resources.beneficial_owners import BeneficialOwnersResource, AsyncBeneficialOwnersResource from .resources.external_accounts import ExternalAccountsResource, AsyncExternalAccountsResource from .resources.oauth_connections import OAuthConnectionsResource, AsyncOAuthConnectionsResource from .resources.account_statements import AccountStatementsResource, AsyncAccountStatementsResource @@ -478,6 +480,12 @@ def entities(self) -> EntitiesResource: return EntitiesResource(self) + @cached_property + def beneficial_owners(self) -> BeneficialOwnersResource: + from .resources.beneficial_owners import BeneficialOwnersResource + + return BeneficialOwnersResource(self) + @cached_property def supplemental_documents(self) -> SupplementalDocumentsResource: from .resources.supplemental_documents import SupplementalDocumentsResource @@ -1071,6 +1079,12 @@ def entities(self) -> AsyncEntitiesResource: return AsyncEntitiesResource(self) + @cached_property + def beneficial_owners(self) -> AsyncBeneficialOwnersResource: + from .resources.beneficial_owners import AsyncBeneficialOwnersResource + + return AsyncBeneficialOwnersResource(self) + @cached_property def supplemental_documents(self) -> AsyncSupplementalDocumentsResource: from .resources.supplemental_documents import AsyncSupplementalDocumentsResource @@ -1591,6 +1605,12 @@ def entities(self) -> entities.EntitiesResourceWithRawResponse: return EntitiesResourceWithRawResponse(self._client.entities) + @cached_property + def beneficial_owners(self) -> beneficial_owners.BeneficialOwnersResourceWithRawResponse: + from .resources.beneficial_owners import BeneficialOwnersResourceWithRawResponse + + return BeneficialOwnersResourceWithRawResponse(self._client.beneficial_owners) + @cached_property def supplemental_documents(self) -> supplemental_documents.SupplementalDocumentsResourceWithRawResponse: from .resources.supplemental_documents import SupplementalDocumentsResourceWithRawResponse @@ -1954,6 +1974,12 @@ def entities(self) -> entities.AsyncEntitiesResourceWithRawResponse: return AsyncEntitiesResourceWithRawResponse(self._client.entities) + @cached_property + def beneficial_owners(self) -> beneficial_owners.AsyncBeneficialOwnersResourceWithRawResponse: + from .resources.beneficial_owners import AsyncBeneficialOwnersResourceWithRawResponse + + return AsyncBeneficialOwnersResourceWithRawResponse(self._client.beneficial_owners) + @cached_property def supplemental_documents(self) -> supplemental_documents.AsyncSupplementalDocumentsResourceWithRawResponse: from .resources.supplemental_documents import AsyncSupplementalDocumentsResourceWithRawResponse @@ -2317,6 +2343,12 @@ def entities(self) -> entities.EntitiesResourceWithStreamingResponse: return EntitiesResourceWithStreamingResponse(self._client.entities) + @cached_property + def beneficial_owners(self) -> beneficial_owners.BeneficialOwnersResourceWithStreamingResponse: + from .resources.beneficial_owners import BeneficialOwnersResourceWithStreamingResponse + + return BeneficialOwnersResourceWithStreamingResponse(self._client.beneficial_owners) + @cached_property def supplemental_documents(self) -> supplemental_documents.SupplementalDocumentsResourceWithStreamingResponse: from .resources.supplemental_documents import SupplementalDocumentsResourceWithStreamingResponse @@ -2686,6 +2718,12 @@ def entities(self) -> entities.AsyncEntitiesResourceWithStreamingResponse: return AsyncEntitiesResourceWithStreamingResponse(self._client.entities) + @cached_property + def beneficial_owners(self) -> beneficial_owners.AsyncBeneficialOwnersResourceWithStreamingResponse: + from .resources.beneficial_owners import AsyncBeneficialOwnersResourceWithStreamingResponse + + return AsyncBeneficialOwnersResourceWithStreamingResponse(self._client.beneficial_owners) + @cached_property def supplemental_documents(self) -> supplemental_documents.AsyncSupplementalDocumentsResourceWithStreamingResponse: from .resources.supplemental_documents import AsyncSupplementalDocumentsResourceWithStreamingResponse diff --git a/src/increase/_version.py b/src/increase/_version.py index 2a0086a3..0a300c97 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.427.0" # x-release-please-version +__version__ = "0.428.0" # x-release-please-version diff --git a/src/increase/resources/__init__.py b/src/increase/resources/__init__.py index 7cc7c62c..d62d8ae4 100644 --- a/src/increase/resources/__init__.py +++ b/src/increase/resources/__init__.py @@ -224,6 +224,14 @@ AccountTransfersResourceWithStreamingResponse, AsyncAccountTransfersResourceWithStreamingResponse, ) +from .beneficial_owners import ( + BeneficialOwnersResource, + AsyncBeneficialOwnersResource, + BeneficialOwnersResourceWithRawResponse, + AsyncBeneficialOwnersResourceWithRawResponse, + BeneficialOwnersResourceWithStreamingResponse, + AsyncBeneficialOwnersResourceWithStreamingResponse, +) from .external_accounts import ( ExternalAccountsResource, AsyncExternalAccountsResource, @@ -662,6 +670,12 @@ "AsyncEntitiesResourceWithRawResponse", "EntitiesResourceWithStreamingResponse", "AsyncEntitiesResourceWithStreamingResponse", + "BeneficialOwnersResource", + "AsyncBeneficialOwnersResource", + "BeneficialOwnersResourceWithRawResponse", + "AsyncBeneficialOwnersResourceWithRawResponse", + "BeneficialOwnersResourceWithStreamingResponse", + "AsyncBeneficialOwnersResourceWithStreamingResponse", "SupplementalDocumentsResource", "AsyncSupplementalDocumentsResource", "SupplementalDocumentsResourceWithRawResponse", diff --git a/src/increase/resources/beneficial_owners.py b/src/increase/resources/beneficial_owners.py new file mode 100644 index 00000000..37f6eb07 --- /dev/null +++ b/src/increase/resources/beneficial_owners.py @@ -0,0 +1,306 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import httpx + +from ..types import beneficial_owner_list_params +from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given +from .._utils import 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 ..pagination import SyncPage, AsyncPage +from .._base_client import AsyncPaginator, make_request_options +from ..types.entity_beneficial_owner import EntityBeneficialOwner + +__all__ = ["BeneficialOwnersResource", "AsyncBeneficialOwnersResource"] + + +class BeneficialOwnersResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> BeneficialOwnersResourceWithRawResponse: + """ + 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 BeneficialOwnersResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> BeneficialOwnersResourceWithStreamingResponse: + """ + 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 BeneficialOwnersResourceWithStreamingResponse(self) + + def retrieve( + self, + entity_beneficial_owner_id: 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, + ) -> EntityBeneficialOwner: + """ + Retrieve a Beneficial Owner + + Args: + entity_beneficial_owner_id: The identifier of the Beneficial Owner to retrieve. + + 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 entity_beneficial_owner_id: + raise ValueError( + f"Expected a non-empty value for `entity_beneficial_owner_id` but received {entity_beneficial_owner_id!r}" + ) + return self._get( + f"/entity_beneficial_owners/{entity_beneficial_owner_id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=EntityBeneficialOwner, + ) + + def list( + self, + *, + entity_id: str, + cursor: str | Omit = omit, + idempotency_key: str | Omit = omit, + limit: int | Omit = omit, + # 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, + ) -> SyncPage[EntityBeneficialOwner]: + """ + List Beneficial Owners + + Args: + entity_id: The identifier of the Entity to list beneficial owners for. Only `corporation` + entities have beneficial owners. + + cursor: Return the page of entries after this one. + + idempotency_key: Filter records to the one with the specified `idempotency_key` you chose for + that object. This value is unique across Increase and is used to ensure that a + request is only processed once. Learn more about + [idempotency](https://increase.com/documentation/idempotency-keys). + + limit: Limit the size of the list that is returned. The default (and maximum) is 100 + objects. + + 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( + "/entity_beneficial_owners", + page=SyncPage[EntityBeneficialOwner], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "entity_id": entity_id, + "cursor": cursor, + "idempotency_key": idempotency_key, + "limit": limit, + }, + beneficial_owner_list_params.BeneficialOwnerListParams, + ), + ), + model=EntityBeneficialOwner, + ) + + +class AsyncBeneficialOwnersResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncBeneficialOwnersResourceWithRawResponse: + """ + 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 AsyncBeneficialOwnersResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncBeneficialOwnersResourceWithStreamingResponse: + """ + 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 AsyncBeneficialOwnersResourceWithStreamingResponse(self) + + async def retrieve( + self, + entity_beneficial_owner_id: 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, + ) -> EntityBeneficialOwner: + """ + Retrieve a Beneficial Owner + + Args: + entity_beneficial_owner_id: The identifier of the Beneficial Owner to retrieve. + + 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 entity_beneficial_owner_id: + raise ValueError( + f"Expected a non-empty value for `entity_beneficial_owner_id` but received {entity_beneficial_owner_id!r}" + ) + return await self._get( + f"/entity_beneficial_owners/{entity_beneficial_owner_id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=EntityBeneficialOwner, + ) + + def list( + self, + *, + entity_id: str, + cursor: str | Omit = omit, + idempotency_key: str | Omit = omit, + limit: int | Omit = omit, + # 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[EntityBeneficialOwner, AsyncPage[EntityBeneficialOwner]]: + """ + List Beneficial Owners + + Args: + entity_id: The identifier of the Entity to list beneficial owners for. Only `corporation` + entities have beneficial owners. + + cursor: Return the page of entries after this one. + + idempotency_key: Filter records to the one with the specified `idempotency_key` you chose for + that object. This value is unique across Increase and is used to ensure that a + request is only processed once. Learn more about + [idempotency](https://increase.com/documentation/idempotency-keys). + + limit: Limit the size of the list that is returned. The default (and maximum) is 100 + objects. + + 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( + "/entity_beneficial_owners", + page=AsyncPage[EntityBeneficialOwner], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "entity_id": entity_id, + "cursor": cursor, + "idempotency_key": idempotency_key, + "limit": limit, + }, + beneficial_owner_list_params.BeneficialOwnerListParams, + ), + ), + model=EntityBeneficialOwner, + ) + + +class BeneficialOwnersResourceWithRawResponse: + def __init__(self, beneficial_owners: BeneficialOwnersResource) -> None: + self._beneficial_owners = beneficial_owners + + self.retrieve = to_raw_response_wrapper( + beneficial_owners.retrieve, + ) + self.list = to_raw_response_wrapper( + beneficial_owners.list, + ) + + +class AsyncBeneficialOwnersResourceWithRawResponse: + def __init__(self, beneficial_owners: AsyncBeneficialOwnersResource) -> None: + self._beneficial_owners = beneficial_owners + + self.retrieve = async_to_raw_response_wrapper( + beneficial_owners.retrieve, + ) + self.list = async_to_raw_response_wrapper( + beneficial_owners.list, + ) + + +class BeneficialOwnersResourceWithStreamingResponse: + def __init__(self, beneficial_owners: BeneficialOwnersResource) -> None: + self._beneficial_owners = beneficial_owners + + self.retrieve = to_streamed_response_wrapper( + beneficial_owners.retrieve, + ) + self.list = to_streamed_response_wrapper( + beneficial_owners.list, + ) + + +class AsyncBeneficialOwnersResourceWithStreamingResponse: + def __init__(self, beneficial_owners: AsyncBeneficialOwnersResource) -> None: + self._beneficial_owners = beneficial_owners + + self.retrieve = async_to_streamed_response_wrapper( + beneficial_owners.retrieve, + ) + self.list = async_to_streamed_response_wrapper( + beneficial_owners.list, + ) diff --git a/src/increase/types/__init__.py b/src/increase/types/__init__.py index 3088a44b..8fa2797b 100644 --- a/src/increase/types/__init__.py +++ b/src/increase/types/__init__.py @@ -76,6 +76,7 @@ from .card_token_list_params import CardTokenListParams as CardTokenListParams from .card_update_pin_params import CardUpdatePinParams as CardUpdatePinParams from .card_token_capabilities import CardTokenCapabilities as CardTokenCapabilities +from .entity_beneficial_owner import EntityBeneficialOwner as EntityBeneficialOwner from .file_link_create_params import FileLinkCreateParams as FileLinkCreateParams from .inbound_fednow_transfer import InboundFednowTransfer as InboundFednowTransfer from .transaction_list_params import TransactionListParams as TransactionListParams @@ -105,6 +106,7 @@ from .account_number_create_params import AccountNumberCreateParams as AccountNumberCreateParams from .account_number_update_params import AccountNumberUpdateParams as AccountNumberUpdateParams from .account_transfer_list_params import AccountTransferListParams as AccountTransferListParams +from .beneficial_owner_list_params import BeneficialOwnerListParams as BeneficialOwnerListParams from .card_dispute_withdraw_params import CardDisputeWithdrawParams as CardDisputeWithdrawParams from .check_transfer_create_params import CheckTransferCreateParams as CheckTransferCreateParams from .entity_supplemental_document import EntitySupplementalDocument as EntitySupplementalDocument diff --git a/src/increase/types/beneficial_owner_list_params.py b/src/increase/types/beneficial_owner_list_params.py new file mode 100644 index 00000000..36267763 --- /dev/null +++ b/src/increase/types/beneficial_owner_list_params.py @@ -0,0 +1,32 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["BeneficialOwnerListParams"] + + +class BeneficialOwnerListParams(TypedDict, total=False): + entity_id: Required[str] + """The identifier of the Entity to list beneficial owners for. + + Only `corporation` entities have beneficial owners. + """ + + cursor: str + """Return the page of entries after this one.""" + + idempotency_key: str + """ + Filter records to the one with the specified `idempotency_key` you chose for + that object. This value is unique across Increase and is used to ensure that a + request is only processed once. Learn more about + [idempotency](https://increase.com/documentation/idempotency-keys). + """ + + limit: int + """Limit the size of the list that is returned. + + The default (and maximum) is 100 objects. + """ diff --git a/src/increase/types/entity.py b/src/increase/types/entity.py index 4d4ff37d..6d02ce99 100644 --- a/src/increase/types/entity.py +++ b/src/increase/types/entity.py @@ -7,16 +7,13 @@ from pydantic import Field as FieldInfo from .._models import BaseModel +from .entity_beneficial_owner import EntityBeneficialOwner from .entity_supplemental_document import EntitySupplementalDocument __all__ = [ "Entity", "Corporation", "CorporationAddress", - "CorporationBeneficialOwner", - "CorporationBeneficialOwnerIndividual", - "CorporationBeneficialOwnerIndividualAddress", - "CorporationBeneficialOwnerIndividualIdentification", "GovernmentAuthority", "GovernmentAuthorityAddress", "GovernmentAuthorityAuthorizedPerson", @@ -64,108 +61,6 @@ class CorporationAddress(BaseModel): """The ZIP code of the address.""" -class CorporationBeneficialOwnerIndividualAddress(BaseModel): - """The person's address.""" - - city: Optional[str] = None - """The city, district, town, or village of the address.""" - - country: str - """The two-letter ISO 3166-1 alpha-2 code for the country of the address.""" - - line1: str - """The first line of the address.""" - - line2: Optional[str] = None - """The second line of the address.""" - - state: Optional[str] = None - """ - The two-letter United States Postal Service (USPS) abbreviation for the US - state, province, or region of the address. - """ - - zip: Optional[str] = None - """The ZIP or postal code of the address.""" - - -class CorporationBeneficialOwnerIndividualIdentification(BaseModel): - """A means of verifying the person's identity.""" - - method: Literal[ - "social_security_number", "individual_taxpayer_identification_number", "passport", "drivers_license", "other" - ] - """A method that can be used to verify the individual's identity. - - - `social_security_number` - A social security number. - - `individual_taxpayer_identification_number` - An individual taxpayer - identification number (ITIN). - - `passport` - A passport number. - - `drivers_license` - A driver's license number. - - `other` - Another identifying document. - """ - - number_last4: str - """ - The last 4 digits of the identification number that can be used to verify the - individual's identity. - """ - - if TYPE_CHECKING: - # Some versions of Pydantic <2.8.0 have a bug and don’t allow assigning a - # value to this field, so for compatibility we avoid doing it at runtime. - __pydantic_extra__: Dict[str, object] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride] - - # Stub to indicate that arbitrary properties are accepted. - # To access properties that are not valid identifiers you can use `getattr`, e.g. - # `getattr(obj, '$type')` - def __getattr__(self, attr: str) -> object: ... - else: - __pydantic_extra__: Dict[str, object] - - -class CorporationBeneficialOwnerIndividual(BaseModel): - """Personal details for the beneficial owner.""" - - address: CorporationBeneficialOwnerIndividualAddress - """The person's address.""" - - date_of_birth: date - """The person's date of birth in YYYY-MM-DD format.""" - - identification: CorporationBeneficialOwnerIndividualIdentification - """A means of verifying the person's identity.""" - - name: str - """The person's legal name.""" - - -class CorporationBeneficialOwner(BaseModel): - id: str - """The identifier of this beneficial owner.""" - - company_title: Optional[str] = None - """This person's role or title within the entity.""" - - individual: CorporationBeneficialOwnerIndividual - """Personal details for the beneficial owner.""" - - prongs: List[Literal["ownership", "control"]] - """Why this person is considered a beneficial owner of the entity.""" - - if TYPE_CHECKING: - # Some versions of Pydantic <2.8.0 have a bug and don’t allow assigning a - # value to this field, so for compatibility we avoid doing it at runtime. - __pydantic_extra__: Dict[str, object] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride] - - # Stub to indicate that arbitrary properties are accepted. - # To access properties that are not valid identifiers you can use `getattr`, e.g. - # `getattr(obj, '$type')` - def __getattr__(self, attr: str) -> object: ... - else: - __pydantic_extra__: Dict[str, object] - - class Corporation(BaseModel): """Details of the corporation entity. @@ -175,7 +70,7 @@ class Corporation(BaseModel): address: CorporationAddress """The corporation's address.""" - beneficial_owners: List[CorporationBeneficialOwner] + beneficial_owners: List[EntityBeneficialOwner] """ The identifying details of anyone controlling or owning 25% or more of the corporation. diff --git a/src/increase/types/entity_beneficial_owner.py b/src/increase/types/entity_beneficial_owner.py new file mode 100644 index 00000000..86907ad5 --- /dev/null +++ b/src/increase/types/entity_beneficial_owner.py @@ -0,0 +1,125 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import TYPE_CHECKING, Dict, List, Optional +from datetime import date, datetime +from typing_extensions import Literal + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = ["EntityBeneficialOwner", "Individual", "IndividualAddress", "IndividualIdentification"] + + +class IndividualAddress(BaseModel): + """The person's address.""" + + city: Optional[str] = None + """The city, district, town, or village of the address.""" + + country: str + """The two-letter ISO 3166-1 alpha-2 code for the country of the address.""" + + line1: str + """The first line of the address.""" + + line2: Optional[str] = None + """The second line of the address.""" + + state: Optional[str] = None + """ + The two-letter United States Postal Service (USPS) abbreviation for the US + state, province, or region of the address. + """ + + zip: Optional[str] = None + """The ZIP or postal code of the address.""" + + +class IndividualIdentification(BaseModel): + """A means of verifying the person's identity.""" + + method: Literal[ + "social_security_number", "individual_taxpayer_identification_number", "passport", "drivers_license", "other" + ] + """A method that can be used to verify the individual's identity. + + - `social_security_number` - A social security number. + - `individual_taxpayer_identification_number` - An individual taxpayer + identification number (ITIN). + - `passport` - A passport number. + - `drivers_license` - A driver's license number. + - `other` - Another identifying document. + """ + + number_last4: str + """ + The last 4 digits of the identification number that can be used to verify the + individual's identity. + """ + + if TYPE_CHECKING: + # Some versions of Pydantic <2.8.0 have a bug and don’t allow assigning a + # value to this field, so for compatibility we avoid doing it at runtime. + __pydantic_extra__: Dict[str, object] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride] + + # Stub to indicate that arbitrary properties are accepted. + # To access properties that are not valid identifiers you can use `getattr`, e.g. + # `getattr(obj, '$type')` + def __getattr__(self, attr: str) -> object: ... + else: + __pydantic_extra__: Dict[str, object] + + +class Individual(BaseModel): + """Personal details for the beneficial owner.""" + + address: IndividualAddress + """The person's address.""" + + date_of_birth: date + """The person's date of birth in YYYY-MM-DD format.""" + + identification: IndividualIdentification + """A means of verifying the person's identity.""" + + name: str + """The person's legal name.""" + + +class EntityBeneficialOwner(BaseModel): + id: str + """The identifier of this beneficial owner.""" + + company_title: Optional[str] = None + """This person's role or title within the entity.""" + + created_at: datetime + """ + The [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) time at which the + Beneficial Owner was created. + """ + + individual: Individual + """Personal details for the beneficial owner.""" + + prongs: List[Literal["ownership", "control"]] + """Why this person is considered a beneficial owner of the entity.""" + + type: Literal["entity_beneficial_owner"] + """A constant representing the object's type. + + For this resource it will always be `entity_beneficial_owner`. + """ + + if TYPE_CHECKING: + # Some versions of Pydantic <2.8.0 have a bug and don’t allow assigning a + # value to this field, so for compatibility we avoid doing it at runtime. + __pydantic_extra__: Dict[str, object] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride] + + # Stub to indicate that arbitrary properties are accepted. + # To access properties that are not valid identifiers you can use `getattr`, e.g. + # `getattr(obj, '$type')` + def __getattr__(self, attr: str) -> object: ... + else: + __pydantic_extra__: Dict[str, object] diff --git a/tests/api_resources/test_beneficial_owners.py b/tests/api_resources/test_beneficial_owners.py new file mode 100644 index 00000000..3edaf063 --- /dev/null +++ b/tests/api_resources/test_beneficial_owners.py @@ -0,0 +1,187 @@ +# 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 EntityBeneficialOwner +from increase.pagination import SyncPage, AsyncPage + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestBeneficialOwners: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_retrieve(self, client: Increase) -> None: + beneficial_owner = client.beneficial_owners.retrieve( + "entity_setup_beneficial_owner_submission_vgkyk7dj5eb4sfhdbkx7", + ) + assert_matches_type(EntityBeneficialOwner, beneficial_owner, path=["response"]) + + @parametrize + def test_raw_response_retrieve(self, client: Increase) -> None: + response = client.beneficial_owners.with_raw_response.retrieve( + "entity_setup_beneficial_owner_submission_vgkyk7dj5eb4sfhdbkx7", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + beneficial_owner = response.parse() + assert_matches_type(EntityBeneficialOwner, beneficial_owner, path=["response"]) + + @parametrize + def test_streaming_response_retrieve(self, client: Increase) -> None: + with client.beneficial_owners.with_streaming_response.retrieve( + "entity_setup_beneficial_owner_submission_vgkyk7dj5eb4sfhdbkx7", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + beneficial_owner = response.parse() + assert_matches_type(EntityBeneficialOwner, beneficial_owner, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_retrieve(self, client: Increase) -> None: + with pytest.raises( + ValueError, match=r"Expected a non-empty value for `entity_beneficial_owner_id` but received ''" + ): + client.beneficial_owners.with_raw_response.retrieve( + "", + ) + + @parametrize + def test_method_list(self, client: Increase) -> None: + beneficial_owner = client.beneficial_owners.list( + entity_id="entity_id", + ) + assert_matches_type(SyncPage[EntityBeneficialOwner], beneficial_owner, path=["response"]) + + @parametrize + def test_method_list_with_all_params(self, client: Increase) -> None: + beneficial_owner = client.beneficial_owners.list( + entity_id="entity_id", + cursor="cursor", + idempotency_key="x", + limit=1, + ) + assert_matches_type(SyncPage[EntityBeneficialOwner], beneficial_owner, path=["response"]) + + @parametrize + def test_raw_response_list(self, client: Increase) -> None: + response = client.beneficial_owners.with_raw_response.list( + entity_id="entity_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + beneficial_owner = response.parse() + assert_matches_type(SyncPage[EntityBeneficialOwner], beneficial_owner, path=["response"]) + + @parametrize + def test_streaming_response_list(self, client: Increase) -> None: + with client.beneficial_owners.with_streaming_response.list( + entity_id="entity_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + beneficial_owner = response.parse() + assert_matches_type(SyncPage[EntityBeneficialOwner], beneficial_owner, path=["response"]) + + assert cast(Any, response.is_closed) is True + + +class TestAsyncBeneficialOwners: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @parametrize + async def test_method_retrieve(self, async_client: AsyncIncrease) -> None: + beneficial_owner = await async_client.beneficial_owners.retrieve( + "entity_setup_beneficial_owner_submission_vgkyk7dj5eb4sfhdbkx7", + ) + assert_matches_type(EntityBeneficialOwner, beneficial_owner, path=["response"]) + + @parametrize + async def test_raw_response_retrieve(self, async_client: AsyncIncrease) -> None: + response = await async_client.beneficial_owners.with_raw_response.retrieve( + "entity_setup_beneficial_owner_submission_vgkyk7dj5eb4sfhdbkx7", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + beneficial_owner = await response.parse() + assert_matches_type(EntityBeneficialOwner, beneficial_owner, path=["response"]) + + @parametrize + async def test_streaming_response_retrieve(self, async_client: AsyncIncrease) -> None: + async with async_client.beneficial_owners.with_streaming_response.retrieve( + "entity_setup_beneficial_owner_submission_vgkyk7dj5eb4sfhdbkx7", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + beneficial_owner = await response.parse() + assert_matches_type(EntityBeneficialOwner, beneficial_owner, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_retrieve(self, async_client: AsyncIncrease) -> None: + with pytest.raises( + ValueError, match=r"Expected a non-empty value for `entity_beneficial_owner_id` but received ''" + ): + await async_client.beneficial_owners.with_raw_response.retrieve( + "", + ) + + @parametrize + async def test_method_list(self, async_client: AsyncIncrease) -> None: + beneficial_owner = await async_client.beneficial_owners.list( + entity_id="entity_id", + ) + assert_matches_type(AsyncPage[EntityBeneficialOwner], beneficial_owner, path=["response"]) + + @parametrize + async def test_method_list_with_all_params(self, async_client: AsyncIncrease) -> None: + beneficial_owner = await async_client.beneficial_owners.list( + entity_id="entity_id", + cursor="cursor", + idempotency_key="x", + limit=1, + ) + assert_matches_type(AsyncPage[EntityBeneficialOwner], beneficial_owner, path=["response"]) + + @parametrize + async def test_raw_response_list(self, async_client: AsyncIncrease) -> None: + response = await async_client.beneficial_owners.with_raw_response.list( + entity_id="entity_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + beneficial_owner = await response.parse() + assert_matches_type(AsyncPage[EntityBeneficialOwner], beneficial_owner, path=["response"]) + + @parametrize + async def test_streaming_response_list(self, async_client: AsyncIncrease) -> None: + async with async_client.beneficial_owners.with_streaming_response.list( + entity_id="entity_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + beneficial_owner = await response.parse() + assert_matches_type(AsyncPage[EntityBeneficialOwner], beneficial_owner, path=["response"]) + + assert cast(Any, response.is_closed) is True