From a05398c6e06119d43cbe124cb2ecf92db24dbe3f Mon Sep 17 00:00:00 2001
From: Stainless Bot <107565488+stainless-bot@users.noreply.github.com>
Date: Tue, 3 Oct 2023 00:23:47 -0400
Subject: [PATCH] feat(api): add `/forward` endpoint and other updates (#115)
---
.stats.yml | 2 +-
api.md | 23 +-
src/finch/_client.py | 141 ++++++
src/finch/resources/__init__.py | 14 +-
src/finch/resources/employer/__init__.py | 6 +
src/finch/resources/employer/benefits.py | 110 +++++
src/finch/resources/employer/employer.py | 29 ++
src/finch/types/__init__.py | 3 +
src/finch/types/benefit_support_type.py | 170 +++++++
src/finch/types/employer/__init__.py | 8 +
.../types/employer/benefit_register_params.py | 19 +
.../register_company_benefits_response.py | 11 +
src/finch/types/forward_response.py | 66 +++
src/finch/types/hris/benefit_frequency.py | 2 +-
src/finch/types/hris/employment_data.py | 17 +-
src/finch/types/hris/individual.py | 14 +
src/finch/types/hris/pay_statement.py | 2 +-
src/finch/types/provider.py | 431 +++++++++++++++++-
src/finch/types/top_level_forward_params.py | 42 ++
tests/api_resources/employer/__init__.py | 1 +
tests/api_resources/employer/test_benefits.py | 54 +++
tests/api_resources/test_top_level.py | 40 ++
22 files changed, 1196 insertions(+), 9 deletions(-)
create mode 100644 src/finch/resources/employer/__init__.py
create mode 100644 src/finch/resources/employer/benefits.py
create mode 100644 src/finch/resources/employer/employer.py
create mode 100644 src/finch/types/benefit_support_type.py
create mode 100644 src/finch/types/employer/__init__.py
create mode 100644 src/finch/types/employer/benefit_register_params.py
create mode 100644 src/finch/types/employer/register_company_benefits_response.py
create mode 100644 src/finch/types/forward_response.py
create mode 100644 src/finch/types/top_level_forward_params.py
create mode 100644 tests/api_resources/employer/__init__.py
create mode 100644 tests/api_resources/employer/test_benefits.py
diff --git a/.stats.yml b/.stats.yml
index 2d2fedb9..6ec2b331 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1 +1 @@
-configured_endpoints: 18
+configured_endpoints: 20
diff --git a/api.md b/api.md
index 24fa1691..d1b897e1 100644
--- a/api.md
+++ b/api.md
@@ -1,7 +1,14 @@
# Finch
+Types:
+
+```python
+from finch.types import ForwardResponse
+```
+
Methods:
+- client.forward(\*\*params) -> ForwardResponse
- client.get_access_token(\*args) -> str
- client.get_auth_url(\*args) -> str
@@ -138,7 +145,7 @@ Methods:
Types:
```python
-from finch.types import Provider
+from finch.types import BenefitSupportType, Provider
```
Methods:
@@ -164,3 +171,17 @@ Methods:
- client.webhooks.unwrap(\*args) -> object
- client.webhooks.verify_signature(\*args) -> None
+
+# Employer
+
+## Benefits
+
+Types:
+
+```python
+from finch.types.employer import RegisterCompanyBenefitsResponse
+```
+
+Methods:
+
+- client.employer.benefits.register(\*\*params) -> RegisterCompanyBenefitsResponse
diff --git a/src/finch/_client.py b/src/finch/_client.py
index 17d3e583..2fd38c5f 100644
--- a/src/finch/_client.py
+++ b/src/finch/_client.py
@@ -10,9 +10,12 @@
from . import resources, _exceptions
from ._qs import Querystring
+from .types import ForwardResponse, top_level_forward_params
from ._types import (
NOT_GIVEN,
+ Body,
Omit,
+ Query,
Headers,
Timeout,
NotGiven,
@@ -20,6 +23,7 @@
ProxiesTypes,
RequestOptions,
)
+from ._utils import maybe_transform
from ._version import __version__
from ._streaming import Stream as Stream
from ._streaming import AsyncStream as AsyncStream
@@ -30,6 +34,7 @@
DEFAULT_MAX_RETRIES,
SyncAPIClient,
AsyncAPIClient,
+ make_request_options,
)
__all__ = [
@@ -50,6 +55,7 @@ class Finch(SyncAPIClient):
providers: resources.Providers
account: resources.Account
webhooks: resources.Webhooks
+ employer: resources.Employer
# client options
access_token: str | None
@@ -123,6 +129,7 @@ def __init__(
self.providers = resources.Providers(self)
self.account = resources.Account(self)
self.webhooks = resources.Webhooks(self)
+ self.employer = resources.Employer(self)
@property
def qs(self) -> Querystring:
@@ -216,6 +223,72 @@ def copy(
def __del__(self) -> None:
self.close()
+ def forward(
+ self,
+ *,
+ method: str,
+ route: str,
+ data: Optional[str] | NotGiven = NOT_GIVEN,
+ headers: Optional[object] | NotGiven = NOT_GIVEN,
+ params: Optional[object] | 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 | None | NotGiven = NOT_GIVEN,
+ ) -> ForwardResponse:
+ """The Forward API allows you to make direct requests to an employment system.
+
+ If
+ Finch’s unified API doesn’t have a data model that cleanly fits your needs, then
+ Forward allows you to push or pull data models directly against an integration’s
+ API.
+
+ Args:
+ method: The HTTP method for the forwarded request. Valid values include: `GET` , `POST`
+ , `PUT` , `DELETE` , and `PATCH`.
+
+ route: The URL route path for the forwarded request. This value must begin with a
+ forward-slash ( / ) and may only contain alphanumeric characters, hyphens, and
+ underscores.
+
+ data: The body for the forwarded request. This value must be specified as either a
+ string or a valid JSON object.
+
+ headers: The HTTP headers to include on the forwarded request. This value must be
+ specified as an object of key-value pairs. Example:
+ `{"Content-Type": "application/xml", "X-API-Version": "v1" }`
+
+ params: The query parameters for the forwarded request. This value must be specified as
+ a valid JSON object rather than a query string.
+
+ 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.post(
+ "/forward",
+ body=maybe_transform(
+ {
+ "method": method,
+ "route": route,
+ "data": data,
+ "headers": headers,
+ "params": params,
+ },
+ top_level_forward_params.TopLevelForwardParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ForwardResponse,
+ )
+
def get_access_token(
self,
code: str,
@@ -313,6 +386,7 @@ class AsyncFinch(AsyncAPIClient):
providers: resources.AsyncProviders
account: resources.AsyncAccount
webhooks: resources.AsyncWebhooks
+ employer: resources.AsyncEmployer
# client options
access_token: str | None
@@ -386,6 +460,7 @@ def __init__(
self.providers = resources.AsyncProviders(self)
self.account = resources.AsyncAccount(self)
self.webhooks = resources.AsyncWebhooks(self)
+ self.employer = resources.AsyncEmployer(self)
@property
def qs(self) -> Querystring:
@@ -482,6 +557,72 @@ def __del__(self) -> None:
except Exception:
pass
+ async def forward(
+ self,
+ *,
+ method: str,
+ route: str,
+ data: Optional[str] | NotGiven = NOT_GIVEN,
+ headers: Optional[object] | NotGiven = NOT_GIVEN,
+ params: Optional[object] | 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 | None | NotGiven = NOT_GIVEN,
+ ) -> ForwardResponse:
+ """The Forward API allows you to make direct requests to an employment system.
+
+ If
+ Finch’s unified API doesn’t have a data model that cleanly fits your needs, then
+ Forward allows you to push or pull data models directly against an integration’s
+ API.
+
+ Args:
+ method: The HTTP method for the forwarded request. Valid values include: `GET` , `POST`
+ , `PUT` , `DELETE` , and `PATCH`.
+
+ route: The URL route path for the forwarded request. This value must begin with a
+ forward-slash ( / ) and may only contain alphanumeric characters, hyphens, and
+ underscores.
+
+ data: The body for the forwarded request. This value must be specified as either a
+ string or a valid JSON object.
+
+ headers: The HTTP headers to include on the forwarded request. This value must be
+ specified as an object of key-value pairs. Example:
+ `{"Content-Type": "application/xml", "X-API-Version": "v1" }`
+
+ params: The query parameters for the forwarded request. This value must be specified as
+ a valid JSON object rather than a query string.
+
+ 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 await self.post(
+ "/forward",
+ body=maybe_transform(
+ {
+ "method": method,
+ "route": route,
+ "data": data,
+ "headers": headers,
+ "params": params,
+ },
+ top_level_forward_params.TopLevelForwardParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ForwardResponse,
+ )
+
async def get_access_token(
self,
code: str,
diff --git a/src/finch/resources/__init__.py b/src/finch/resources/__init__.py
index 1a47fea5..17d2aa49 100644
--- a/src/finch/resources/__init__.py
+++ b/src/finch/resources/__init__.py
@@ -2,7 +2,19 @@
from .hris import HRIS, AsyncHRIS
from .account import Account, AsyncAccount
+from .employer import Employer, AsyncEmployer
from .webhooks import Webhooks, AsyncWebhooks
from .providers import Providers, AsyncProviders
-__all__ = ["HRIS", "AsyncHRIS", "Providers", "AsyncProviders", "Account", "AsyncAccount", "Webhooks", "AsyncWebhooks"]
+__all__ = [
+ "HRIS",
+ "AsyncHRIS",
+ "Providers",
+ "AsyncProviders",
+ "Account",
+ "AsyncAccount",
+ "Webhooks",
+ "AsyncWebhooks",
+ "Employer",
+ "AsyncEmployer",
+]
diff --git a/src/finch/resources/employer/__init__.py b/src/finch/resources/employer/__init__.py
new file mode 100644
index 00000000..bc5b5a4a
--- /dev/null
+++ b/src/finch/resources/employer/__init__.py
@@ -0,0 +1,6 @@
+# File generated from our OpenAPI spec by Stainless.
+
+from .benefits import Benefits, AsyncBenefits
+from .employer import Employer, AsyncEmployer
+
+__all__ = ["Benefits", "AsyncBenefits", "Employer", "AsyncEmployer"]
diff --git a/src/finch/resources/employer/benefits.py b/src/finch/resources/employer/benefits.py
new file mode 100644
index 00000000..e60e045d
--- /dev/null
+++ b/src/finch/resources/employer/benefits.py
@@ -0,0 +1,110 @@
+# File generated from our OpenAPI spec by Stainless.
+
+from __future__ import annotations
+
+from typing import Optional
+
+from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven
+from ..._utils import maybe_transform
+from ..._resource import SyncAPIResource, AsyncAPIResource
+from ...types.hris import BenefitType, BenefitFrequency
+from ..._base_client import make_request_options
+from ...types.employer import RegisterCompanyBenefitsResponse, benefit_register_params
+
+__all__ = ["Benefits", "AsyncBenefits"]
+
+
+class Benefits(SyncAPIResource):
+ def register(
+ self,
+ *,
+ description: str | NotGiven = NOT_GIVEN,
+ frequency: Optional[BenefitFrequency] | NotGiven = NOT_GIVEN,
+ type: Optional[BenefitType] | 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 | None | NotGiven = NOT_GIVEN,
+ ) -> RegisterCompanyBenefitsResponse:
+ """
+ **Availability: Assisted Benefits providers only**
+
+ Register existing benefits from the customer on the provider, on Finch's end.
+ Please use the `/provider` endpoint to view available types for each provider.
+
+ Args:
+ type: Type of benefit.
+
+ 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._post(
+ "/employer/benefits/register",
+ body=maybe_transform(
+ {
+ "description": description,
+ "frequency": frequency,
+ "type": type,
+ },
+ benefit_register_params.BenefitRegisterParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=RegisterCompanyBenefitsResponse,
+ )
+
+
+class AsyncBenefits(AsyncAPIResource):
+ async def register(
+ self,
+ *,
+ description: str | NotGiven = NOT_GIVEN,
+ frequency: Optional[BenefitFrequency] | NotGiven = NOT_GIVEN,
+ type: Optional[BenefitType] | 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 | None | NotGiven = NOT_GIVEN,
+ ) -> RegisterCompanyBenefitsResponse:
+ """
+ **Availability: Assisted Benefits providers only**
+
+ Register existing benefits from the customer on the provider, on Finch's end.
+ Please use the `/provider` endpoint to view available types for each provider.
+
+ Args:
+ type: Type of benefit.
+
+ 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 await self._post(
+ "/employer/benefits/register",
+ body=maybe_transform(
+ {
+ "description": description,
+ "frequency": frequency,
+ "type": type,
+ },
+ benefit_register_params.BenefitRegisterParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=RegisterCompanyBenefitsResponse,
+ )
diff --git a/src/finch/resources/employer/employer.py b/src/finch/resources/employer/employer.py
new file mode 100644
index 00000000..e03eddf1
--- /dev/null
+++ b/src/finch/resources/employer/employer.py
@@ -0,0 +1,29 @@
+# File generated from our OpenAPI spec by Stainless.
+
+from __future__ import annotations
+
+from typing import TYPE_CHECKING
+
+from .benefits import Benefits, AsyncBenefits
+from ..._resource import SyncAPIResource, AsyncAPIResource
+
+if TYPE_CHECKING:
+ from ..._client import Finch, AsyncFinch
+
+__all__ = ["Employer", "AsyncEmployer"]
+
+
+class Employer(SyncAPIResource):
+ benefits: Benefits
+
+ def __init__(self, client: Finch) -> None:
+ super().__init__(client)
+ self.benefits = Benefits(client)
+
+
+class AsyncEmployer(AsyncAPIResource):
+ benefits: AsyncBenefits
+
+ def __init__(self, client: AsyncFinch) -> None:
+ super().__init__(client)
+ self.benefits = AsyncBenefits(client)
diff --git a/src/finch/types/__init__.py b/src/finch/types/__init__.py
index dc60674b..dcc1fef5 100644
--- a/src/finch/types/__init__.py
+++ b/src/finch/types/__init__.py
@@ -8,4 +8,7 @@
from .location import Location as Location
from .provider import Provider as Provider
from .introspection import Introspection as Introspection
+from .forward_response import ForwardResponse as ForwardResponse
from .disconnect_response import DisconnectResponse as DisconnectResponse
+from .benefit_support_type import BenefitSupportType as BenefitSupportType
+from .top_level_forward_params import TopLevelForwardParams as TopLevelForwardParams
diff --git a/src/finch/types/benefit_support_type.py b/src/finch/types/benefit_support_type.py
new file mode 100644
index 00000000..6db34dc9
--- /dev/null
+++ b/src/finch/types/benefit_support_type.py
@@ -0,0 +1,170 @@
+# File generated from our OpenAPI spec by Stainless.
+
+from typing import List, Optional
+from typing_extensions import Literal
+
+from .hris import BenefitFrequency
+from .._models import BaseModel
+
+__all__ = [
+ "BenefitSupportType",
+ "SupportedFeatures",
+ "SupportedOperations",
+ "SupportedOperationsCompanyBenefits",
+ "SupportedOperationsIndividualBenefits",
+]
+
+
+class SupportedFeatures(BaseModel):
+ annual_maximum: Optional[bool] = None
+ """Whether the provider supports an annual maximum for this benefit."""
+
+ catch_up: Optional[bool] = None
+ """Whether the provider supports catch up for this benefit.
+
+ This field will only be true for retirement benefits.
+ """
+
+ company_contribution: Optional[List[Literal["fixed", "percent"]]] = None
+ """Supported contribution types.
+
+ An empty array indicates contributions are not supported.
+ """
+
+ description: Optional[str] = None
+
+ employee_deduction: Optional[List[Literal["fixed", "percent"]]] = None
+ """Supported deduction types.
+
+ An empty array indicates deductions are not supported.
+ """
+
+ frequencies: Optional[List[Optional[BenefitFrequency]]] = None
+ """The list of frequencies supported by the provider for this benefit"""
+
+ hsa_contribution_limit: Optional[List[Literal["individual", "family"]]] = None
+ """Whether the provider supports HSA contribution limits.
+
+ Empty if this feature is not supported for the benefit. This array only has
+ values for HSA benefits.
+ """
+
+
+class SupportedOperationsCompanyBenefits(BaseModel):
+ create: Optional[
+ Literal["supported", "not_supported_by_finch", "not_supported_by_provider", "client_access_only"]
+ ] = None
+ """
+ - `supported`: This operation is supported by both the provider and Finch
+ - `not_supported_by_finch`: This operation is not supported by Finch but
+ supported by the provider
+ - `not_supported_by_provider`: This operation is not supported by the provider,
+ so Finch cannot support
+ - `client_access_only`: This behavior is supported by the provider, but only
+ available to the client and not to Finch
+ """
+
+ delete: Optional[
+ Literal["supported", "not_supported_by_finch", "not_supported_by_provider", "client_access_only"]
+ ] = None
+ """
+ - `supported`: This operation is supported by both the provider and Finch
+ - `not_supported_by_finch`: This operation is not supported by Finch but
+ supported by the provider
+ - `not_supported_by_provider`: This operation is not supported by the provider,
+ so Finch cannot support
+ - `client_access_only`: This behavior is supported by the provider, but only
+ available to the client and not to Finch
+ """
+
+ read: Optional[
+ Literal["supported", "not_supported_by_finch", "not_supported_by_provider", "client_access_only"]
+ ] = None
+ """
+ - `supported`: This operation is supported by both the provider and Finch
+ - `not_supported_by_finch`: This operation is not supported by Finch but
+ supported by the provider
+ - `not_supported_by_provider`: This operation is not supported by the provider,
+ so Finch cannot support
+ - `client_access_only`: This behavior is supported by the provider, but only
+ available to the client and not to Finch
+ """
+
+ update: Optional[
+ Literal["supported", "not_supported_by_finch", "not_supported_by_provider", "client_access_only"]
+ ] = None
+ """
+ - `supported`: This operation is supported by both the provider and Finch
+ - `not_supported_by_finch`: This operation is not supported by Finch but
+ supported by the provider
+ - `not_supported_by_provider`: This operation is not supported by the provider,
+ so Finch cannot support
+ - `client_access_only`: This behavior is supported by the provider, but only
+ available to the client and not to Finch
+ """
+
+
+class SupportedOperationsIndividualBenefits(BaseModel):
+ create: Optional[
+ Literal["supported", "not_supported_by_finch", "not_supported_by_provider", "client_access_only"]
+ ] = None
+ """
+ - `supported`: This operation is supported by both the provider and Finch
+ - `not_supported_by_finch`: This operation is not supported by Finch but
+ supported by the provider
+ - `not_supported_by_provider`: This operation is not supported by the provider,
+ so Finch cannot support
+ - `client_access_only`: This behavior is supported by the provider, but only
+ available to the client and not to Finch
+ """
+
+ delete: Optional[
+ Literal["supported", "not_supported_by_finch", "not_supported_by_provider", "client_access_only"]
+ ] = None
+ """
+ - `supported`: This operation is supported by both the provider and Finch
+ - `not_supported_by_finch`: This operation is not supported by Finch but
+ supported by the provider
+ - `not_supported_by_provider`: This operation is not supported by the provider,
+ so Finch cannot support
+ - `client_access_only`: This behavior is supported by the provider, but only
+ available to the client and not to Finch
+ """
+
+ read: Optional[
+ Literal["supported", "not_supported_by_finch", "not_supported_by_provider", "client_access_only"]
+ ] = None
+ """
+ - `supported`: This operation is supported by both the provider and Finch
+ - `not_supported_by_finch`: This operation is not supported by Finch but
+ supported by the provider
+ - `not_supported_by_provider`: This operation is not supported by the provider,
+ so Finch cannot support
+ - `client_access_only`: This behavior is supported by the provider, but only
+ available to the client and not to Finch
+ """
+
+ update: Optional[
+ Literal["supported", "not_supported_by_finch", "not_supported_by_provider", "client_access_only"]
+ ] = None
+ """
+ - `supported`: This operation is supported by both the provider and Finch
+ - `not_supported_by_finch`: This operation is not supported by Finch but
+ supported by the provider
+ - `not_supported_by_provider`: This operation is not supported by the provider,
+ so Finch cannot support
+ - `client_access_only`: This behavior is supported by the provider, but only
+ available to the client and not to Finch
+ """
+
+
+class SupportedOperations(BaseModel):
+ company_benefits: Optional[SupportedOperationsCompanyBenefits] = None
+
+ individual_benefits: Optional[SupportedOperationsIndividualBenefits] = None
+
+
+class BenefitSupportType(BaseModel):
+ supported_features: Optional[SupportedFeatures] = None
+
+ supported_operations: Optional[SupportedOperations] = None
diff --git a/src/finch/types/employer/__init__.py b/src/finch/types/employer/__init__.py
new file mode 100644
index 00000000..60887cf5
--- /dev/null
+++ b/src/finch/types/employer/__init__.py
@@ -0,0 +1,8 @@
+# File generated from our OpenAPI spec by Stainless.
+
+from __future__ import annotations
+
+from .benefit_register_params import BenefitRegisterParams as BenefitRegisterParams
+from .register_company_benefits_response import (
+ RegisterCompanyBenefitsResponse as RegisterCompanyBenefitsResponse,
+)
diff --git a/src/finch/types/employer/benefit_register_params.py b/src/finch/types/employer/benefit_register_params.py
new file mode 100644
index 00000000..cd916ad6
--- /dev/null
+++ b/src/finch/types/employer/benefit_register_params.py
@@ -0,0 +1,19 @@
+# File generated from our OpenAPI spec by Stainless.
+
+from __future__ import annotations
+
+from typing import Optional
+from typing_extensions import TypedDict
+
+from ..hris import BenefitType, BenefitFrequency
+
+__all__ = ["BenefitRegisterParams"]
+
+
+class BenefitRegisterParams(TypedDict, total=False):
+ description: str
+
+ frequency: Optional[BenefitFrequency]
+
+ type: Optional[BenefitType]
+ """Type of benefit."""
diff --git a/src/finch/types/employer/register_company_benefits_response.py b/src/finch/types/employer/register_company_benefits_response.py
new file mode 100644
index 00000000..dd64e3d7
--- /dev/null
+++ b/src/finch/types/employer/register_company_benefits_response.py
@@ -0,0 +1,11 @@
+# File generated from our OpenAPI spec by Stainless.
+
+from ..._models import BaseModel
+
+__all__ = ["RegisterCompanyBenefitsResponse"]
+
+
+class RegisterCompanyBenefitsResponse(BaseModel):
+ benefit_id: str
+
+ job_id: str
diff --git a/src/finch/types/forward_response.py b/src/finch/types/forward_response.py
new file mode 100644
index 00000000..2e33fbfc
--- /dev/null
+++ b/src/finch/types/forward_response.py
@@ -0,0 +1,66 @@
+# File generated from our OpenAPI spec by Stainless.
+
+from typing import Optional
+
+from pydantic import Field as FieldInfo
+
+from .._models import BaseModel
+
+__all__ = ["ForwardResponse", "Request"]
+
+
+class Request(BaseModel):
+ data: Optional[str]
+ """The body that was specified for the forwarded request.
+
+ If a value was not specified in the original request, this value will be
+ returned as null ; otherwise, this value will always be returned as a string.
+ """
+
+ headers: Optional[object]
+ """The specified HTTP headers that were included in the forwarded request.
+
+ If no headers were specified, this will be returned as `null`.
+ """
+
+ method: str
+ """The HTTP method that was specified for the forwarded request.
+
+ Valid values include: `GET` , `POST` , `PUT` , `DELETE` , and `PATCH`.
+ """
+
+ params: Optional[object]
+ """The query parameters that were included in the forwarded request.
+
+ If no query parameters were specified, this will be returned as `null`.
+ """
+
+ route: str
+ """The URL route path that was specified for the forwarded request."""
+
+
+class ForwardResponse(BaseModel):
+ data: Optional[str]
+ """
+ A string representation of the HTTP response body of the forwarded request’s
+ response received from the underlying integration’s API. This field may be null
+ in the case where the upstream system’s response is empty.
+ """
+
+ headers: Optional[object]
+ """
+ The HTTP headers of the forwarded request’s response, exactly as received from
+ the underlying integration’s API.
+ """
+
+ request: Request
+ """
+ An object containing details of your original forwarded request, for your ease
+ of reference.
+ """
+
+ status_code: int = FieldInfo(alias="statusCode")
+ """
+ The HTTP status code of the forwarded request’s response, exactly received from
+ the underlying integration’s API. This value will be returned as an integer.
+ """
diff --git a/src/finch/types/hris/benefit_frequency.py b/src/finch/types/hris/benefit_frequency.py
index b4a7414f..515774fe 100644
--- a/src/finch/types/hris/benefit_frequency.py
+++ b/src/finch/types/hris/benefit_frequency.py
@@ -5,4 +5,4 @@
__all__ = ["BenefitFrequency"]
-BenefitFrequency = Optional[Literal["one_time", "every_paycheck"]]
+BenefitFrequency = Optional[Literal["one_time", "every_paycheck", "monthly"]]
diff --git a/src/finch/types/hris/employment_data.py b/src/finch/types/hris/employment_data.py
index 4ae7d44a..618fe692 100644
--- a/src/finch/types/hris/employment_data.py
+++ b/src/finch/types/hris/employment_data.py
@@ -9,7 +9,13 @@
from ..._models import BaseModel
from ..location import Location
-__all__ = ["EmploymentData", "Department", "Employment", "Manager"]
+__all__ = ["EmploymentData", "CustomField", "Department", "Employment", "Manager"]
+
+
+class CustomField(BaseModel):
+ name: Optional[str] = None
+
+ value: Optional[object] = None
class Department(BaseModel):
@@ -41,6 +47,12 @@ class EmploymentData(BaseModel):
class_code: Optional[str] = None
"""Worker's compensation classification code for this employee"""
+ custom_fields: Optional[List[CustomField]] = None
+ """Custom fields for the individual.
+
+ These are fields which are defined by the employer in the system.
+ """
+
department: Optional[Department] = None
"""The department object."""
@@ -82,6 +94,9 @@ class EmploymentData(BaseModel):
Please reach out to your Finch representative if you would like access.
"""
+ source_id: Optional[str] = None
+ """The source system's unique employment identifier for this individual"""
+
start_date: Optional[str] = None
title: Optional[str] = None
diff --git a/src/finch/types/hris/individual.py b/src/finch/types/hris/individual.py
index 89e3e5bf..8f8ae112 100644
--- a/src/finch/types/hris/individual.py
+++ b/src/finch/types/hris/individual.py
@@ -29,6 +29,20 @@ class Individual(BaseModel):
emails: Optional[List[Email]] = None
+ ethnicity: Optional[
+ Literal[
+ "asian",
+ "white",
+ "black_or_african_american",
+ "native_hawaiian_or_pacific_islander",
+ "american_indian_or_alaska_native",
+ "hispanic_or_latino",
+ "two_or_more_races",
+ "decline_to_specify",
+ ]
+ ] = None
+ """The EEOC-defined ethnicity of the individual."""
+
first_name: Optional[str] = None
"""The legal first name of the individual."""
diff --git a/src/finch/types/hris/pay_statement.py b/src/finch/types/hris/pay_statement.py
index f9d5515e..3d25a99c 100644
--- a/src/finch/types/hris/pay_statement.py
+++ b/src/finch/types/hris/pay_statement.py
@@ -117,7 +117,7 @@ class PayStatement(BaseModel):
taxes: Optional[List[Optional[Tax]]] = None
"""The array of taxes objects associated with this pay statement."""
- total_hours: Optional[int] = None
+ total_hours: Optional[float] = None
"""The number of hours worked for this pay period"""
type: Optional[Literal["regular_payroll", "off_cycle_payroll", "one_time_payment"]] = None
diff --git a/src/finch/types/provider.py b/src/finch/types/provider.py
index 880077a0..73b08fc3 100644
--- a/src/finch/types/provider.py
+++ b/src/finch/types/provider.py
@@ -1,16 +1,440 @@
# File generated from our OpenAPI spec by Stainless.
from typing import List, Optional
+from typing_extensions import Literal
+
+from pydantic import Field as FieldInfo
from .._models import BaseModel
+from .benefit_support_type import BenefitSupportType
+
+__all__ = [
+ "Provider",
+ "AuthenticationMethod",
+ "AuthenticationMethodBenefitsSupport",
+ "AuthenticationMethodSupportedFields",
+ "AuthenticationMethodSupportedFieldsCompany",
+ "AuthenticationMethodSupportedFieldsCompanyAccounts",
+ "AuthenticationMethodSupportedFieldsCompanyDepartments",
+ "AuthenticationMethodSupportedFieldsCompanyDepartmentsParent",
+ "AuthenticationMethodSupportedFieldsCompanyEntity",
+ "AuthenticationMethodSupportedFieldsCompanyLocations",
+ "AuthenticationMethodSupportedFieldsDirectory",
+ "AuthenticationMethodSupportedFieldsDirectoryIndividuals",
+ "AuthenticationMethodSupportedFieldsDirectoryIndividualsManager",
+ "AuthenticationMethodSupportedFieldsDirectoryPaging",
+ "AuthenticationMethodSupportedFieldsEmployment",
+ "AuthenticationMethodSupportedFieldsEmploymentDepartment",
+ "AuthenticationMethodSupportedFieldsEmploymentEmployment",
+ "AuthenticationMethodSupportedFieldsEmploymentIncome",
+ "AuthenticationMethodSupportedFieldsEmploymentLocation",
+ "AuthenticationMethodSupportedFieldsIndividual",
+ "AuthenticationMethodSupportedFieldsIndividualEmails",
+ "AuthenticationMethodSupportedFieldsIndividualPhoneNumbers",
+ "AuthenticationMethodSupportedFieldsIndividualResidence",
+ "AuthenticationMethodSupportedFieldsPayStatement",
+ "AuthenticationMethodSupportedFieldsPayStatementPaging",
+ "AuthenticationMethodSupportedFieldsPayStatementPayStatements",
+ "AuthenticationMethodSupportedFieldsPayStatementPayStatementsEarnings",
+ "AuthenticationMethodSupportedFieldsPayStatementPayStatementsEmployeeDeductions",
+ "AuthenticationMethodSupportedFieldsPayStatementPayStatementsEmployerDeductions",
+ "AuthenticationMethodSupportedFieldsPayStatementPayStatementsTaxes",
+ "AuthenticationMethodSupportedFieldsPayment",
+ "AuthenticationMethodSupportedFieldsPaymentPayPeriod",
+]
+
+
+class AuthenticationMethodBenefitsSupport(BaseModel):
+ retirement_401k: Optional[BenefitSupportType] = FieldInfo(alias="401k", default=None)
+
+ retirement_401k_loan: Optional[BenefitSupportType] = FieldInfo(alias="401k_loan", default=None)
+
+ retirement_401k_roth: Optional[BenefitSupportType] = FieldInfo(alias="401k_roth", default=None)
+
+ retirement_403b: Optional[BenefitSupportType] = FieldInfo(alias="403b", default=None)
+
+ retirement_403b_roth: Optional[BenefitSupportType] = FieldInfo(alias="403b_roth", default=None)
+
+ retirement_457: Optional[BenefitSupportType] = FieldInfo(alias="457", default=None)
+
+ retirement_457_roth: Optional[BenefitSupportType] = FieldInfo(alias="457_roth", default=None)
+
+ commuter: Optional[BenefitSupportType] = None
+
+ custom_post_tax: Optional[BenefitSupportType] = None
+
+ custom_pre_tax: Optional[BenefitSupportType] = None
+
+ fsa_dependent_care: Optional[BenefitSupportType] = None
+
+ fsa_medical: Optional[BenefitSupportType] = None
+
+ hsa_post: Optional[BenefitSupportType] = None
+
+ hsa_pre: Optional[BenefitSupportType] = None
+
+ s125_dental: Optional[BenefitSupportType] = None
+
+ s125_medical: Optional[BenefitSupportType] = None
+
+ s125_vision: Optional[BenefitSupportType] = None
+
+ simple: Optional[BenefitSupportType] = None
+
+ simple_ira: Optional[BenefitSupportType] = None
+
+
+class AuthenticationMethodSupportedFieldsCompanyAccounts(BaseModel):
+ account_name: Optional[bool] = None
+
+ account_number: Optional[bool] = None
+
+ account_type: Optional[bool] = None
+
+ institution_name: Optional[bool] = None
+
+ routing_number: Optional[bool] = None
+
+
+class AuthenticationMethodSupportedFieldsCompanyDepartmentsParent(BaseModel):
+ name: Optional[bool] = None
+
+
+class AuthenticationMethodSupportedFieldsCompanyDepartments(BaseModel):
+ name: Optional[bool] = None
+
+ parent: Optional[AuthenticationMethodSupportedFieldsCompanyDepartmentsParent] = None
+
+
+class AuthenticationMethodSupportedFieldsCompanyEntity(BaseModel):
+ subtype: Optional[bool] = None
+
+ type: Optional[bool] = None
+
+
+class AuthenticationMethodSupportedFieldsCompanyLocations(BaseModel):
+ city: Optional[bool] = None
+
+ country: Optional[bool] = None
+
+ line1: Optional[bool] = None
+
+ line2: Optional[bool] = None
+
+ postal_code: Optional[bool] = None
+
+ state: Optional[bool] = None
+
+
+class AuthenticationMethodSupportedFieldsCompany(BaseModel):
+ id: Optional[bool] = None
+
+ accounts: Optional[AuthenticationMethodSupportedFieldsCompanyAccounts] = None
+
+ departments: Optional[AuthenticationMethodSupportedFieldsCompanyDepartments] = None
+
+ ein: Optional[bool] = None
+
+ entity: Optional[AuthenticationMethodSupportedFieldsCompanyEntity] = None
+
+ legal_name: Optional[bool] = None
+
+ locations: Optional[AuthenticationMethodSupportedFieldsCompanyLocations] = None
+
+ primary_email: Optional[bool] = None
+
+ primary_phone_number: Optional[bool] = None
+
+
+class AuthenticationMethodSupportedFieldsDirectoryIndividualsManager(BaseModel):
+ id: Optional[bool] = None
+
+
+class AuthenticationMethodSupportedFieldsDirectoryIndividuals(BaseModel):
+ id: Optional[bool] = None
+
+ department: Optional[object] = None
+
+ first_name: Optional[bool] = None
+
+ is_active: Optional[bool] = None
+
+ last_name: Optional[bool] = None
+
+ manager: Optional[AuthenticationMethodSupportedFieldsDirectoryIndividualsManager] = None
+
+ middle_name: Optional[bool] = None
+
+
+class AuthenticationMethodSupportedFieldsDirectoryPaging(BaseModel):
+ count: Optional[bool] = None
+
+ offset: Optional[bool] = None
+
+
+class AuthenticationMethodSupportedFieldsDirectory(BaseModel):
+ individuals: Optional[AuthenticationMethodSupportedFieldsDirectoryIndividuals] = None
+
+ paging: Optional[AuthenticationMethodSupportedFieldsDirectoryPaging] = None
+
+
+class AuthenticationMethodSupportedFieldsEmploymentDepartment(BaseModel):
+ name: Optional[bool] = None
+
+
+class AuthenticationMethodSupportedFieldsEmploymentEmployment(BaseModel):
+ subtype: Optional[bool] = None
+
+ type: Optional[bool] = None
+
+
+class AuthenticationMethodSupportedFieldsEmploymentIncome(BaseModel):
+ amount: Optional[bool] = None
+
+ currency: Optional[bool] = None
+
+ unit: Optional[bool] = None
+
+
+class AuthenticationMethodSupportedFieldsEmploymentLocation(BaseModel):
+ city: Optional[bool] = None
+
+ country: Optional[bool] = None
+
+ line1: Optional[bool] = None
+
+ line2: Optional[bool] = None
+
+ postal_code: Optional[bool] = None
+
+ state: Optional[bool] = None
+
+
+class AuthenticationMethodSupportedFieldsEmployment(BaseModel):
+ id: Optional[bool] = None
+
+ class_code: Optional[bool] = None
+
+ custom_fields: Optional[bool] = None
+
+ department: Optional[AuthenticationMethodSupportedFieldsEmploymentDepartment] = None
+
+ employment: Optional[AuthenticationMethodSupportedFieldsEmploymentEmployment] = None
+
+ end_date: Optional[bool] = None
+
+ first_name: Optional[bool] = None
+
+ income_history: Optional[bool] = None
+
+ income: Optional[AuthenticationMethodSupportedFieldsEmploymentIncome] = None
+
+ is_active: Optional[bool] = None
+
+ last_name: Optional[bool] = None
-__all__ = ["Provider"]
+ location: Optional[AuthenticationMethodSupportedFieldsEmploymentLocation] = None
+
+ manager: Optional[object] = None
+
+ middle_name: Optional[bool] = None
+
+ start_date: Optional[bool] = None
+
+ title: Optional[bool] = None
+
+
+class AuthenticationMethodSupportedFieldsIndividualEmails(BaseModel):
+ data: Optional[bool] = None
+
+ type: Optional[bool] = None
+
+
+class AuthenticationMethodSupportedFieldsIndividualPhoneNumbers(BaseModel):
+ data: Optional[bool] = None
+
+ type: Optional[bool] = None
+
+
+class AuthenticationMethodSupportedFieldsIndividualResidence(BaseModel):
+ city: Optional[bool] = None
+
+ country: Optional[bool] = None
+
+ line1: Optional[bool] = None
+
+ line2: Optional[bool] = None
+
+ postal_code: Optional[bool] = None
+
+ state: Optional[bool] = None
+
+
+class AuthenticationMethodSupportedFieldsIndividual(BaseModel):
+ id: Optional[bool] = None
+
+ dob: Optional[bool] = None
+
+ emails: Optional[AuthenticationMethodSupportedFieldsIndividualEmails] = None
+
+ ethnicity: Optional[bool] = None
+
+ first_name: Optional[bool] = None
+
+ gender: Optional[bool] = None
+
+ last_name: Optional[bool] = None
+
+ middle_name: Optional[bool] = None
+
+ phone_numbers: Optional[AuthenticationMethodSupportedFieldsIndividualPhoneNumbers] = None
+
+ preferred_name: Optional[bool] = None
+
+ residence: Optional[AuthenticationMethodSupportedFieldsIndividualResidence] = None
+
+ ssn: Optional[bool] = None
+
+
+class AuthenticationMethodSupportedFieldsPayStatementPaging(BaseModel):
+ count: bool
+
+ offset: bool
+
+
+class AuthenticationMethodSupportedFieldsPayStatementPayStatementsEarnings(BaseModel):
+ amount: Optional[bool] = None
+
+ currency: Optional[bool] = None
+
+ name: Optional[bool] = None
+
+ type: Optional[bool] = None
+
+
+class AuthenticationMethodSupportedFieldsPayStatementPayStatementsEmployeeDeductions(BaseModel):
+ amount: Optional[bool] = None
+
+ currency: Optional[bool] = None
+
+ name: Optional[bool] = None
+
+ pre_tax: Optional[bool] = None
+
+ type: Optional[bool] = None
+
+
+class AuthenticationMethodSupportedFieldsPayStatementPayStatementsEmployerDeductions(BaseModel):
+ amount: Optional[bool] = None
+
+ currency: Optional[bool] = None
+
+ name: Optional[bool] = None
+
+
+class AuthenticationMethodSupportedFieldsPayStatementPayStatementsTaxes(BaseModel):
+ amount: Optional[bool] = None
+
+ currency: Optional[bool] = None
+
+ employer: Optional[bool] = None
+
+ name: Optional[bool] = None
+
+ type: Optional[bool] = None
+
+
+class AuthenticationMethodSupportedFieldsPayStatementPayStatements(BaseModel):
+ earnings: Optional[AuthenticationMethodSupportedFieldsPayStatementPayStatementsEarnings] = None
+
+ employee_deductions: Optional[AuthenticationMethodSupportedFieldsPayStatementPayStatementsEmployeeDeductions] = None
+
+ employer_deductions: Optional[AuthenticationMethodSupportedFieldsPayStatementPayStatementsEmployerDeductions] = None
+
+ gross_pay: Optional[bool] = None
+
+ individual_id: Optional[bool] = None
+
+ net_pay: Optional[bool] = None
+
+ payment_method: Optional[bool] = None
+
+ taxes: Optional[AuthenticationMethodSupportedFieldsPayStatementPayStatementsTaxes] = None
+
+ total_hours: Optional[bool] = None
+
+ type: Optional[bool] = None
+
+
+class AuthenticationMethodSupportedFieldsPayStatement(BaseModel):
+ paging: Optional[AuthenticationMethodSupportedFieldsPayStatementPaging] = None
+
+ pay_statements: Optional[AuthenticationMethodSupportedFieldsPayStatementPayStatements] = None
+
+
+class AuthenticationMethodSupportedFieldsPaymentPayPeriod(BaseModel):
+ end_date: Optional[bool] = None
+
+ start_date: Optional[bool] = None
+
+
+class AuthenticationMethodSupportedFieldsPayment(BaseModel):
+ id: Optional[bool] = None
+
+ company_debit: Optional[bool] = None
+
+ debit_date: Optional[bool] = None
+
+ employee_taxes: Optional[bool] = None
+
+ employer_taxes: Optional[bool] = None
+
+ gross_pay: Optional[bool] = None
+
+ individual_ids: Optional[bool] = None
+
+ net_pay: Optional[bool] = None
+
+ pay_date: Optional[bool] = None
+
+ pay_period: Optional[AuthenticationMethodSupportedFieldsPaymentPayPeriod] = None
+
+
+class AuthenticationMethodSupportedFields(BaseModel):
+ company: Optional[AuthenticationMethodSupportedFieldsCompany] = None
+
+ directory: Optional[AuthenticationMethodSupportedFieldsDirectory] = None
+
+ employment: Optional[AuthenticationMethodSupportedFieldsEmployment] = None
+
+ individual: Optional[AuthenticationMethodSupportedFieldsIndividual] = None
+
+ pay_statement: Optional[AuthenticationMethodSupportedFieldsPayStatement] = None
+
+ payment: Optional[AuthenticationMethodSupportedFieldsPayment] = None
+
+
+class AuthenticationMethod(BaseModel):
+ benefits_support: Optional[AuthenticationMethodBenefitsSupport] = None
+ """Each benefit type and their supported features.
+
+ If the benefit type is not supported, the property will be null
+ """
+
+ supported_fields: Optional[AuthenticationMethodSupportedFields] = None
+ """The supported data fields returned by our HR and payroll endpoints"""
+
+ type: Optional[Literal["assisted", "credential", "api_token", "oauth"]] = None
+ """The type of authentication method."""
class Provider(BaseModel):
id: Optional[str] = None
"""The id of the payroll provider used in Connect."""
+ authentication_methods: Optional[List[AuthenticationMethod]] = None
+ """The list of authentication methods supported by the provider."""
+
display_name: Optional[str] = None
"""The display name of the payroll provider."""
@@ -22,8 +446,9 @@ class Provider(BaseModel):
manual: Optional[bool] = None
"""
- Whether the Finch integration with this provider uses the Assisted Connect Flow
- by default.
+ [DEPRECATED] Whether the Finch integration with this provider uses the Assisted
+ Connect Flow by default. This field is now deprecated. Please check for a `type`
+ of `assisted` in the `authentication_methods` field instead.
"""
mfa_required: Optional[bool] = None
diff --git a/src/finch/types/top_level_forward_params.py b/src/finch/types/top_level_forward_params.py
new file mode 100644
index 00000000..1bd9a58f
--- /dev/null
+++ b/src/finch/types/top_level_forward_params.py
@@ -0,0 +1,42 @@
+# File generated from our OpenAPI spec by Stainless.
+
+from __future__ import annotations
+
+from typing import Optional
+from typing_extensions import Required, TypedDict
+
+__all__ = ["TopLevelForwardParams"]
+
+
+class TopLevelForwardParams(TypedDict, total=False):
+ method: Required[str]
+ """The HTTP method for the forwarded request.
+
+ Valid values include: `GET` , `POST` , `PUT` , `DELETE` , and `PATCH`.
+ """
+
+ route: Required[str]
+ """The URL route path for the forwarded request.
+
+ This value must begin with a forward-slash ( / ) and may only contain
+ alphanumeric characters, hyphens, and underscores.
+ """
+
+ data: Optional[str]
+ """The body for the forwarded request.
+
+ This value must be specified as either a string or a valid JSON object.
+ """
+
+ headers: Optional[object]
+ """The HTTP headers to include on the forwarded request.
+
+ This value must be specified as an object of key-value pairs. Example:
+ `{"Content-Type": "application/xml", "X-API-Version": "v1" }`
+ """
+
+ params: Optional[object]
+ """The query parameters for the forwarded request.
+
+ This value must be specified as a valid JSON object rather than a query string.
+ """
diff --git a/tests/api_resources/employer/__init__.py b/tests/api_resources/employer/__init__.py
new file mode 100644
index 00000000..1016754e
--- /dev/null
+++ b/tests/api_resources/employer/__init__.py
@@ -0,0 +1 @@
+# File generated from our OpenAPI spec by Stainless.
diff --git a/tests/api_resources/employer/test_benefits.py b/tests/api_resources/employer/test_benefits.py
new file mode 100644
index 00000000..8d733f3e
--- /dev/null
+++ b/tests/api_resources/employer/test_benefits.py
@@ -0,0 +1,54 @@
+# File generated from our OpenAPI spec by Stainless.
+
+from __future__ import annotations
+
+import os
+
+import pytest
+
+from finch import Finch, AsyncFinch
+from tests.utils import assert_matches_type
+from finch.types.employer import RegisterCompanyBenefitsResponse
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+access_token = os.environ.get("API_KEY", "something1234")
+
+
+class TestBenefits:
+ strict_client = Finch(base_url=base_url, access_token=access_token, _strict_response_validation=True)
+ loose_client = Finch(base_url=base_url, access_token=access_token, _strict_response_validation=False)
+ parametrize = pytest.mark.parametrize("client", [strict_client, loose_client], ids=["strict", "loose"])
+
+ @parametrize
+ def test_method_register(self, client: Finch) -> None:
+ benefit = client.employer.benefits.register()
+ assert_matches_type(RegisterCompanyBenefitsResponse, benefit, path=["response"])
+
+ @parametrize
+ def test_method_register_with_all_params(self, client: Finch) -> None:
+ benefit = client.employer.benefits.register(
+ description="string",
+ frequency="one_time",
+ type="401k",
+ )
+ assert_matches_type(RegisterCompanyBenefitsResponse, benefit, path=["response"])
+
+
+class TestAsyncBenefits:
+ strict_client = AsyncFinch(base_url=base_url, access_token=access_token, _strict_response_validation=True)
+ loose_client = AsyncFinch(base_url=base_url, access_token=access_token, _strict_response_validation=False)
+ parametrize = pytest.mark.parametrize("client", [strict_client, loose_client], ids=["strict", "loose"])
+
+ @parametrize
+ async def test_method_register(self, client: AsyncFinch) -> None:
+ benefit = await client.employer.benefits.register()
+ assert_matches_type(RegisterCompanyBenefitsResponse, benefit, path=["response"])
+
+ @parametrize
+ async def test_method_register_with_all_params(self, client: AsyncFinch) -> None:
+ benefit = await client.employer.benefits.register(
+ description="string",
+ frequency="one_time",
+ type="401k",
+ )
+ assert_matches_type(RegisterCompanyBenefitsResponse, benefit, path=["response"])
diff --git a/tests/api_resources/test_top_level.py b/tests/api_resources/test_top_level.py
index daf3c42c..92717ab1 100644
--- a/tests/api_resources/test_top_level.py
+++ b/tests/api_resources/test_top_level.py
@@ -7,6 +7,8 @@
import pytest
from finch import Finch, AsyncFinch
+from finch.types import ForwardResponse
+from tests.utils import assert_matches_type
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
access_token = os.environ.get("API_KEY", "something1234")
@@ -17,8 +19,46 @@ class TestTopLevel:
loose_client = Finch(base_url=base_url, access_token=access_token, _strict_response_validation=False)
parametrize = pytest.mark.parametrize("client", [strict_client, loose_client], ids=["strict", "loose"])
+ @parametrize
+ def test_method_forward(self, client: Finch) -> None:
+ top_level = client.forward(
+ method="string",
+ route="string",
+ )
+ assert_matches_type(ForwardResponse, top_level, path=["response"])
+
+ @parametrize
+ def test_method_forward_with_all_params(self, client: Finch) -> None:
+ top_level = client.forward(
+ method="string",
+ route="string",
+ data="string",
+ headers={},
+ params={},
+ )
+ assert_matches_type(ForwardResponse, top_level, path=["response"])
+
class TestAsyncTopLevel:
strict_client = AsyncFinch(base_url=base_url, access_token=access_token, _strict_response_validation=True)
loose_client = AsyncFinch(base_url=base_url, access_token=access_token, _strict_response_validation=False)
parametrize = pytest.mark.parametrize("client", [strict_client, loose_client], ids=["strict", "loose"])
+
+ @parametrize
+ async def test_method_forward(self, client: AsyncFinch) -> None:
+ top_level = await client.forward(
+ method="string",
+ route="string",
+ )
+ assert_matches_type(ForwardResponse, top_level, path=["response"])
+
+ @parametrize
+ async def test_method_forward_with_all_params(self, client: AsyncFinch) -> None:
+ top_level = await client.forward(
+ method="string",
+ route="string",
+ data="string",
+ headers={},
+ params={},
+ )
+ assert_matches_type(ForwardResponse, top_level, path=["response"])