diff --git a/README.md b/README.md
index aba6de0b..1a664411 100644
--- a/README.md
+++ b/README.md
@@ -255,3 +255,4 @@ while response.next is not None:
+
diff --git a/reference.md b/reference.md
index ff937ee4..d46addad 100644
--- a/reference.md
+++ b/reference.md
@@ -57047,6 +57047,4503 @@ client.chat.webhook_receivers.create(
+
+
+
+
+## Email AccountDetails
+client.email.account_details.retrieve()
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Get details for a linked account.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from merge import Merge
+
+client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+)
+client.email.account_details.retrieve()
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+## Email AccountToken
+client.email.account_token.retrieve(...)
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Returns the account token for the end user with the provided public token.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from merge import Merge
+
+client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+)
+client.email.account_token.retrieve(
+ public_token="public_token",
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**public_token:** `str`
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+client.email.account_token.regenerate_create()
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Exchange Linked Account account tokens.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from merge import Merge
+
+client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+)
+client.email.account_token.regenerate_create()
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+## Email AsyncPassthrough
+client.email.async_passthrough.create(...)
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Asynchronously pull data from an endpoint not currently supported by Merge.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from merge import Merge
+from merge.resources.email import DataPassthroughRequest, MethodEnum
+
+client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+)
+client.email.async_passthrough.create(
+ request=DataPassthroughRequest(
+ method=MethodEnum.GET,
+ path="/scooters",
+ ),
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**request:** `DataPassthroughRequest`
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+client.email.async_passthrough.retrieve(...)
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Retrieves data from earlier async-passthrough POST request
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from merge import Merge
+
+client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+)
+client.email.async_passthrough.retrieve(
+ async_passthrough_receipt_id="async_passthrough_receipt_id",
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**async_passthrough_receipt_id:** `str`
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+## Email AuditTrail
+client.email.audit_trail.list(...)
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Gets a list of audit trail events.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from merge import Merge
+
+client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+)
+client.email.audit_trail.list(
+ cursor="cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw",
+ end_date="end_date",
+ event_type="event_type",
+ page_size=1,
+ start_date="start_date",
+ user_email="user_email",
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**cursor:** `typing.Optional[str]` — The pagination cursor value.
+
+
+
+
+
+-
+
+**end_date:** `typing.Optional[str]` — If included, will only include audit trail events that occurred before this time
+
+
+
+
+
+-
+
+**event_type:** `typing.Optional[str]` — If included, will only include events with the given event type. Possible values include: `CREATED_REMOTE_PRODUCTION_API_KEY`, `DELETED_REMOTE_PRODUCTION_API_KEY`, `CREATED_TEST_API_KEY`, `DELETED_TEST_API_KEY`, `REGENERATED_PRODUCTION_API_KEY`, `REGENERATED_WEBHOOK_SIGNATURE`, `INVITED_USER`, `TWO_FACTOR_AUTH_ENABLED`, `TWO_FACTOR_AUTH_DISABLED`, `DELETED_LINKED_ACCOUNT`, `DELETED_ALL_COMMON_MODELS_FOR_LINKED_ACCOUNT`, `CREATED_DESTINATION`, `DELETED_DESTINATION`, `CHANGED_DESTINATION`, `CHANGED_SCOPES`, `CHANGED_PERSONAL_INFORMATION`, `CHANGED_ORGANIZATION_SETTINGS`, `ENABLED_INTEGRATION`, `DISABLED_INTEGRATION`, `ENABLED_CATEGORY`, `DISABLED_CATEGORY`, `CHANGED_PASSWORD`, `RESET_PASSWORD`, `ENABLED_REDACT_UNMAPPED_DATA_FOR_ORGANIZATION`, `ENABLED_REDACT_UNMAPPED_DATA_FOR_LINKED_ACCOUNT`, `DISABLED_REDACT_UNMAPPED_DATA_FOR_ORGANIZATION`, `DISABLED_REDACT_UNMAPPED_DATA_FOR_LINKED_ACCOUNT`, `CREATED_INTEGRATION_WIDE_FIELD_MAPPING`, `CREATED_LINKED_ACCOUNT_FIELD_MAPPING`, `CHANGED_INTEGRATION_WIDE_FIELD_MAPPING`, `CHANGED_LINKED_ACCOUNT_FIELD_MAPPING`, `DELETED_INTEGRATION_WIDE_FIELD_MAPPING`, `DELETED_LINKED_ACCOUNT_FIELD_MAPPING`, `CREATED_LINKED_ACCOUNT_COMMON_MODEL_OVERRIDE`, `CHANGED_LINKED_ACCOUNT_COMMON_MODEL_OVERRIDE`, `DELETED_LINKED_ACCOUNT_COMMON_MODEL_OVERRIDE`, `FORCED_LINKED_ACCOUNT_RESYNC`, `MUTED_ISSUE`, `GENERATED_MAGIC_LINK`, `ENABLED_MERGE_WEBHOOK`, `DISABLED_MERGE_WEBHOOK`, `MERGE_WEBHOOK_TARGET_CHANGED`, `END_USER_CREDENTIALS_ACCESSED`
+
+
+
+
+
+-
+
+**page_size:** `typing.Optional[int]` — Number of results to return per page. The maximum limit is 100.
+
+
+
+
+
+-
+
+**start_date:** `typing.Optional[str]` — If included, will only include audit trail events that occurred after this time
+
+
+
+
+
+-
+
+**user_email:** `typing.Optional[str]` — If provided, this will return events associated with the specified user email. Please note that the email address reflects the user's email at the time of the event, and may not be their current email.
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+## Email AvailableActions
+client.email.available_actions.retrieve()
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Returns a list of models and actions available for an account.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from merge import Merge
+
+client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+)
+client.email.available_actions.retrieve()
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+## Email Scopes
+client.email.scopes.default_scopes_retrieve()
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Get the default permissions for Merge Common Models and fields across all Linked Accounts of a given category. [Learn more](https://help.merge.dev/en/articles/5950052-common-model-and-field-scopes).
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from merge import Merge
+
+client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+)
+client.email.scopes.default_scopes_retrieve()
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+client.email.scopes.linked_account_scopes_retrieve()
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Get all available permissions for Merge Common Models and fields for a single Linked Account. [Learn more](https://help.merge.dev/en/articles/5950052-common-model-and-field-scopes).
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from merge import Merge
+
+client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+)
+client.email.scopes.linked_account_scopes_retrieve()
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+client.email.scopes.linked_account_scopes_create(...)
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Update permissions for any Common Model or field for a single Linked Account. Any Scopes not set in this POST request will inherit the default Scopes. [Learn more](https://help.merge.dev/en/articles/5950052-common-model-and-field-scopes)
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from merge import Merge
+from merge.resources.email import (
+ FieldPermissionDeserializerRequest,
+ IndividualCommonModelScopeDeserializerRequest,
+ ModelPermissionDeserializerRequest,
+)
+
+client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+)
+client.email.scopes.linked_account_scopes_create(
+ common_models=[
+ IndividualCommonModelScopeDeserializerRequest(
+ model_name="Employee",
+ model_permissions={
+ "READ": ModelPermissionDeserializerRequest(
+ is_enabled=True,
+ ),
+ "WRITE": ModelPermissionDeserializerRequest(
+ is_enabled=False,
+ ),
+ },
+ field_permissions=FieldPermissionDeserializerRequest(
+ enabled_fields=["avatar", "home_location"],
+ disabled_fields=["work_location"],
+ ),
+ ),
+ IndividualCommonModelScopeDeserializerRequest(
+ model_name="Benefit",
+ model_permissions={
+ "WRITE": ModelPermissionDeserializerRequest(
+ is_enabled=False,
+ )
+ },
+ ),
+ ],
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**common_models:** `typing.Sequence[IndividualCommonModelScopeDeserializerRequest]` — The common models you want to update the scopes for
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+## Email DeleteAccount
+client.email.delete_account.delete()
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Delete a linked account.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from merge import Merge
+
+client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+)
+client.email.delete_account.delete()
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+## Email EmailAddresses
+client.email.email_addresses.list(...)
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Returns a list of `EmailAddress` objects.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+import datetime
+
+from merge import Merge
+
+client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+)
+client.email.email_addresses.list(
+ created_after=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ created_before=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ cursor="cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw",
+ email_address="email_address",
+ include_deleted_data=True,
+ include_remote_data=True,
+ include_shell_data=True,
+ modified_after=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ modified_before=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ page_size=1,
+ remote_id="remote_id",
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**created_after:** `typing.Optional[dt.datetime]` — If provided, will only return objects created after this datetime.
+
+
+
+
+
+-
+
+**created_before:** `typing.Optional[dt.datetime]` — If provided, will only return objects created before this datetime.
+
+
+
+
+
+-
+
+**cursor:** `typing.Optional[str]` — The pagination cursor value.
+
+
+
+
+
+-
+
+**email_address:** `typing.Optional[str]` — If provided, will only return EmailAddresses matching this value (case insensitive).
+
+
+
+
+
+-
+
+**expand:** `typing.Optional[
+ typing.Union[
+ EmailAddressesListRequestExpandItem,
+ typing.Sequence[EmailAddressesListRequestExpandItem],
+ ]
+]` — Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+
+
+
+
+-
+
+**include_deleted_data:** `typing.Optional[bool]` — Indicates whether or not this object has been deleted in the third party platform. Full coverage deletion detection is a premium add-on. Native deletion detection is offered for free with limited coverage. [Learn more](https://docs.merge.dev/integrations/hris/supported-features/).
+
+
+
+
+
+-
+
+**include_remote_data:** `typing.Optional[bool]` — Whether to include the original data Merge fetched from the third-party to produce these models.
+
+
+
+
+
+-
+
+**include_shell_data:** `typing.Optional[bool]` — Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+
+
+
+
+-
+
+**modified_after:** `typing.Optional[dt.datetime]` — If provided, only objects synced by Merge after this date time will be returned.
+
+
+
+
+
+-
+
+**modified_before:** `typing.Optional[dt.datetime]` — If provided, only objects synced by Merge before this date time will be returned.
+
+
+
+
+
+-
+
+**page_size:** `typing.Optional[int]` — Number of results to return per page. The maximum limit is 100.
+
+
+
+
+
+-
+
+**remote_id:** `typing.Optional[str]` — The API provider's ID for the given object.
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+client.email.email_addresses.retrieve(...)
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Returns an `EmailAddress` object with the given `id`.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from merge import Merge
+
+client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+)
+client.email.email_addresses.retrieve(
+ id="id",
+ include_remote_data=True,
+ include_shell_data=True,
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**id:** `str`
+
+
+
+
+
+-
+
+**expand:** `typing.Optional[
+ typing.Union[
+ EmailAddressesRetrieveRequestExpandItem,
+ typing.Sequence[EmailAddressesRetrieveRequestExpandItem],
+ ]
+]` — Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+
+
+
+
+-
+
+**include_remote_data:** `typing.Optional[bool]` — Whether to include the original data Merge fetched from the third-party to produce these models.
+
+
+
+
+
+-
+
+**include_shell_data:** `typing.Optional[bool]` — Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+## Email FieldMapping
+client.email.field_mapping.field_mappings_retrieve(...)
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Get all Field Mappings for this Linked Account. Field Mappings are mappings between third-party Remote Fields and user defined Merge fields. [Learn more](https://docs.merge.dev/supplemental-data/field-mappings/overview/).
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from merge import Merge
+
+client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+)
+client.email.field_mapping.field_mappings_retrieve(
+ exclude_remote_field_metadata=True,
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**exclude_remote_field_metadata:** `typing.Optional[bool]` — If `true`, remote fields metadata is excluded from each field mapping instance (i.e. `remote_fields.remote_key_name` and `remote_fields.schema` will be null). This will increase the speed of the request since these fields require some calculations.
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+client.email.field_mapping.field_mappings_create(...)
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Create new Field Mappings that will be available after the next scheduled sync. This will cause the next sync for this Linked Account to sync **ALL** data from start.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from merge import Merge
+
+client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+)
+client.email.field_mapping.field_mappings_create(
+ exclude_remote_field_metadata=True,
+ remote_data_iteration_count=1,
+ remote_field_traversal_path=["example_remote_field"],
+ remote_method="GET",
+ remote_url_path="/example-url-path",
+ common_model_name="ExampleCommonModel",
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**remote_field_traversal_path:** `typing.Sequence[typing.Optional[typing.Any]]` — The field traversal path of the remote field listed when you hit the GET /remote-fields endpoint.
+
+
+
+
+
+-
+
+**remote_method:** `str` — The method of the remote endpoint where the remote field is coming from.
+
+
+
+
+
+-
+
+**remote_url_path:** `str` — The path of the remote endpoint where the remote field is coming from.
+
+
+
+
+
+-
+
+**common_model_name:** `str` — The name of the Common Model that the remote field corresponds to in a given category.
+
+
+
+
+
+-
+
+**exclude_remote_field_metadata:** `typing.Optional[bool]` — If `true`, remote fields metadata is excluded from each field mapping instance (i.e. `remote_fields.remote_key_name` and `remote_fields.schema` will be null). This will increase the speed of the request since these fields require some calculations.
+
+
+
+
+
+-
+
+**remote_data_iteration_count:** `typing.Optional[int]` — Number of common model instances to iterate through when fetching remote data for field mappings. Defaults to 250 if not provided.
+
+
+
+
+
+-
+
+**target_field_name:** `typing.Optional[str]` — The name of the target field you want this remote field to map to. Required if organization_wide_target_field is not provided.
+
+
+
+
+
+-
+
+**target_field_description:** `typing.Optional[str]` — The description of the target field you want this remote field to map to. Required if organization_wide_target_field is not provided.
+
+
+
+
+
+-
+
+**organization_wide_target_field:** `typing.Optional[str]` — The name or key of an existing Organization-wide target field to map to. When provided, target_field_name and target_field_description are optional.
+
+
+
+
+
+-
+
+**is_integration_wide:** `typing.Optional[bool]` — If true, creates an integration-wide field mapping that applies to all Linked Accounts for the integration. Requires organization_wide_target_field.
+
+
+
+
+
+-
+
+**jmes_path:** `typing.Optional[str]` — DEPRECATED: Use 'advanced_mapping_expression' instead.
+
+
+
+
+
+-
+
+**advanced_mapping_expression:** `typing.Optional[str]` — A JSONata expression used to transform the remote field data.
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+client.email.field_mapping.field_mappings_destroy(...)
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Deletes Field Mappings for a Linked Account. All data related to this Field Mapping will be deleted and these changes will be reflected after the next scheduled sync. This will cause the next sync for this Linked Account to sync **ALL** data from start.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from merge import Merge
+
+client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+)
+client.email.field_mapping.field_mappings_destroy(
+ field_mapping_id="field_mapping_id",
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**field_mapping_id:** `str`
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+client.email.field_mapping.field_mappings_partial_update(...)
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Create or update existing Field Mappings for a Linked Account. Changes will be reflected after the next scheduled sync. This will cause the next sync for this Linked Account to sync **ALL** data from start.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from merge import Merge
+
+client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+)
+client.email.field_mapping.field_mappings_partial_update(
+ field_mapping_id="field_mapping_id",
+ remote_data_iteration_count=1,
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**field_mapping_id:** `str`
+
+
+
+
+
+-
+
+**remote_data_iteration_count:** `typing.Optional[int]` — Number of common model instances to iterate through when fetching remote data for field mappings. Defaults to 250 if not provided.
+
+
+
+
+
+-
+
+**remote_field_traversal_path:** `typing.Optional[typing.Sequence[typing.Optional[typing.Any]]]` — The field traversal path of the remote field listed when you hit the GET /remote-fields endpoint.
+
+
+
+
+
+-
+
+**remote_method:** `typing.Optional[str]` — The method of the remote endpoint where the remote field is coming from.
+
+
+
+
+
+-
+
+**remote_url_path:** `typing.Optional[str]` — The path of the remote endpoint where the remote field is coming from.
+
+
+
+
+
+-
+
+**jmes_path:** `typing.Optional[str]` — DEPRECATED: Use 'advanced_mapping_expression' instead.
+
+
+
+
+
+-
+
+**advanced_mapping_expression:** `typing.Optional[str]` — A JSONata expression used to transform the remote field data.
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+client.email.field_mapping.remote_fields_retrieve(...)
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Get all remote fields for a Linked Account. Remote fields are third-party fields that are accessible after initial sync if remote_data is enabled. You can use remote fields to override existing Merge fields or map a new Merge field. [Learn more](https://docs.merge.dev/supplemental-data/field-mappings/overview/).
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from merge import Merge
+
+client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+)
+client.email.field_mapping.remote_fields_retrieve(
+ common_models="common_models",
+ include_example_values="include_example_values",
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**common_models:** `typing.Optional[str]` — A comma seperated list of Common Model names. If included, will only return Remote Fields for those Common Models.
+
+
+
+
+
+-
+
+**include_example_values:** `typing.Optional[str]` — If true, will include example values, where available, for remote fields in the 3rd party platform. These examples come from active data from your customers.
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+client.email.field_mapping.target_fields_retrieve()
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Get all organization-wide Target Fields, this will not include any Linked Account specific Target Fields. Organization-wide Target Fields are additional fields appended to the Merge Common Model for all Linked Accounts in a category. [Learn more](https://docs.merge.dev/supplemental-data/field-mappings/target-fields/).
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from merge import Merge
+
+client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+)
+client.email.field_mapping.target_fields_retrieve()
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+client.email.field_mapping.target_fields_create(...)
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Create a new organization-wide Target Field. Target Fields are custom fields that your organization defines to collect supplemental data from integrations. [Learn more](https://docs.merge.dev/supplemental-data/field-mappings/target-fields/).
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from merge import Merge
+
+client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+)
+client.email.field_mapping.target_fields_create(
+ name="employee_favorite_team",
+ common_model="Employee",
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**name:** `str` — The name of the target field.
+
+
+
+
+
+-
+
+**common_model:** `str` — The name of the Common Model to associate the target field with.
+
+
+
+
+
+-
+
+**description:** `typing.Optional[str]` — The description of the target field.
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+## Email Folders
+client.email.folders.list(...)
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Returns a list of `Folder` objects.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+import datetime
+
+from merge import Merge
+
+client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+)
+client.email.folders.list(
+ created_after=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ created_before=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ cursor="cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw",
+ include_deleted_data=True,
+ include_remote_data=True,
+ include_shell_data=True,
+ modified_after=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ modified_before=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ name="name",
+ page_size=1,
+ remote_id="remote_id",
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**created_after:** `typing.Optional[dt.datetime]` — If provided, will only return objects created after this datetime.
+
+
+
+
+
+-
+
+**created_before:** `typing.Optional[dt.datetime]` — If provided, will only return objects created before this datetime.
+
+
+
+
+
+-
+
+**cursor:** `typing.Optional[str]` — The pagination cursor value.
+
+
+
+
+
+-
+
+**expand:** `typing.Optional[
+ typing.Union[
+ FoldersListRequestExpandItem,
+ typing.Sequence[FoldersListRequestExpandItem],
+ ]
+]` — Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+
+
+
+
+-
+
+**include_deleted_data:** `typing.Optional[bool]` — Indicates whether or not this object has been deleted in the third party platform. Full coverage deletion detection is a premium add-on. Native deletion detection is offered for free with limited coverage. [Learn more](https://docs.merge.dev/integrations/hris/supported-features/).
+
+
+
+
+
+-
+
+**include_remote_data:** `typing.Optional[bool]` — Whether to include the original data Merge fetched from the third-party to produce these models.
+
+
+
+
+
+-
+
+**include_shell_data:** `typing.Optional[bool]` — Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+
+
+
+
+-
+
+**modified_after:** `typing.Optional[dt.datetime]` — If provided, only objects synced by Merge after this date time will be returned.
+
+
+
+
+
+-
+
+**modified_before:** `typing.Optional[dt.datetime]` — If provided, only objects synced by Merge before this date time will be returned.
+
+
+
+
+
+-
+
+**name:** `typing.Optional[str]` — If provided, will only return Folders with this name.
+
+
+
+
+
+-
+
+**page_size:** `typing.Optional[int]` — Number of results to return per page. The maximum limit is 100.
+
+
+
+
+
+-
+
+**remote_id:** `typing.Optional[str]` — The API provider's ID for the given object.
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+client.email.folders.retrieve(...)
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Returns a `Folder` object with the given `id`.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from merge import Merge
+
+client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+)
+client.email.folders.retrieve(
+ id="id",
+ include_remote_data=True,
+ include_shell_data=True,
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**id:** `str`
+
+
+
+
+
+-
+
+**expand:** `typing.Optional[
+ typing.Union[
+ FoldersRetrieveRequestExpandItem,
+ typing.Sequence[FoldersRetrieveRequestExpandItem],
+ ]
+]` — Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+
+
+
+
+-
+
+**include_remote_data:** `typing.Optional[bool]` — Whether to include the original data Merge fetched from the third-party to produce these models.
+
+
+
+
+
+-
+
+**include_shell_data:** `typing.Optional[bool]` — Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+## Email GenerateKey
+client.email.generate_key.create(...)
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Create a remote key.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from merge import Merge
+
+client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+)
+client.email.generate_key.create(
+ name="Remote Deployment Key 1",
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**name:** `str` — The name of the remote key
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+## Email Groups
+client.email.groups.list(...)
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Returns a list of `Group` objects.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+import datetime
+
+from merge import Merge
+
+client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+)
+client.email.groups.list(
+ created_after=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ created_before=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ cursor="cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw",
+ include_deleted_data=True,
+ include_remote_data=True,
+ include_shell_data=True,
+ modified_after=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ modified_before=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ page_size=1,
+ remote_id="remote_id",
+ user_id="user_id",
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**created_after:** `typing.Optional[dt.datetime]` — If provided, will only return objects created after this datetime.
+
+
+
+
+
+-
+
+**created_before:** `typing.Optional[dt.datetime]` — If provided, will only return objects created before this datetime.
+
+
+
+
+
+-
+
+**cursor:** `typing.Optional[str]` — The pagination cursor value.
+
+
+
+
+
+-
+
+**expand:** `typing.Optional[
+ typing.Union[
+ GroupsListRequestExpandItem,
+ typing.Sequence[GroupsListRequestExpandItem],
+ ]
+]` — Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+
+
+
+
+-
+
+**include_deleted_data:** `typing.Optional[bool]` — Indicates whether or not this object has been deleted in the third party platform. Full coverage deletion detection is a premium add-on. Native deletion detection is offered for free with limited coverage. [Learn more](https://docs.merge.dev/integrations/hris/supported-features/).
+
+
+
+
+
+-
+
+**include_remote_data:** `typing.Optional[bool]` — Whether to include the original data Merge fetched from the third-party to produce these models.
+
+
+
+
+
+-
+
+**include_shell_data:** `typing.Optional[bool]` — Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+
+
+
+
+-
+
+**modified_after:** `typing.Optional[dt.datetime]` — If provided, only objects synced by Merge after this date time will be returned.
+
+
+
+
+
+-
+
+**modified_before:** `typing.Optional[dt.datetime]` — If provided, only objects synced by Merge before this date time will be returned.
+
+
+
+
+
+-
+
+**page_size:** `typing.Optional[int]` — Number of results to return per page. The maximum limit is 100.
+
+
+
+
+
+-
+
+**remote_id:** `typing.Optional[str]` — The API provider's ID for the given object.
+
+
+
+
+
+-
+
+**user_id:** `typing.Optional[str]` — If provided, will only return Groups containing this User.
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+client.email.groups.retrieve(...)
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Returns a `Group` object with the given `id`.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from merge import Merge
+
+client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+)
+client.email.groups.retrieve(
+ id="id",
+ include_remote_data=True,
+ include_shell_data=True,
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**id:** `str`
+
+
+
+
+
+-
+
+**expand:** `typing.Optional[
+ typing.Union[
+ GroupsRetrieveRequestExpandItem,
+ typing.Sequence[GroupsRetrieveRequestExpandItem],
+ ]
+]` — Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+
+
+
+
+-
+
+**include_remote_data:** `typing.Optional[bool]` — Whether to include the original data Merge fetched from the third-party to produce these models.
+
+
+
+
+
+-
+
+**include_shell_data:** `typing.Optional[bool]` — Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+## Email Issues
+client.email.issues.list(...)
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Gets all issues for Organization.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+import datetime
+
+from merge import Merge
+from merge.resources.email.resources.issues import IssuesListRequestStatus
+
+client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+)
+client.email.issues.list(
+ account_token="account_token",
+ cursor="cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw",
+ end_date="end_date",
+ end_user_organization_name="end_user_organization_name",
+ first_incident_time_after=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ first_incident_time_before=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ include_muted="include_muted",
+ integration_name="integration_name",
+ last_incident_time_after=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ last_incident_time_before=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ linked_account_id="linked_account_id",
+ page_size=1,
+ start_date="start_date",
+ status=IssuesListRequestStatus.ONGOING,
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**account_token:** `typing.Optional[str]`
+
+
+
+
+
+-
+
+**cursor:** `typing.Optional[str]` — The pagination cursor value.
+
+
+
+
+
+-
+
+**end_date:** `typing.Optional[str]` — If included, will only include issues whose most recent action occurred before this time
+
+
+
+
+
+-
+
+**end_user_organization_name:** `typing.Optional[str]`
+
+
+
+
+
+-
+
+**first_incident_time_after:** `typing.Optional[dt.datetime]` — If provided, will only return issues whose first incident time was after this datetime.
+
+
+
+
+
+-
+
+**first_incident_time_before:** `typing.Optional[dt.datetime]` — If provided, will only return issues whose first incident time was before this datetime.
+
+
+
+
+
+-
+
+**include_muted:** `typing.Optional[str]` — If true, will include muted issues
+
+
+
+
+
+-
+
+**integration_name:** `typing.Optional[str]`
+
+
+
+
+
+-
+
+**last_incident_time_after:** `typing.Optional[dt.datetime]` — If provided, will only return issues whose last incident time was after this datetime.
+
+
+
+
+
+-
+
+**last_incident_time_before:** `typing.Optional[dt.datetime]` — If provided, will only return issues whose last incident time was before this datetime.
+
+
+
+
+
+-
+
+**linked_account_id:** `typing.Optional[str]` — If provided, will only include issues pertaining to the linked account passed in.
+
+
+
+
+
+-
+
+**page_size:** `typing.Optional[int]` — Number of results to return per page. The maximum limit is 100.
+
+
+
+
+
+-
+
+**start_date:** `typing.Optional[str]` — If included, will only include issues whose most recent action occurred after this time
+
+
+
+
+
+-
+
+**status:** `typing.Optional[IssuesListRequestStatus]` — Status of the issue.
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+client.email.issues.retrieve(...)
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Get a specific issue.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from merge import Merge
+
+client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+)
+client.email.issues.retrieve(
+ id="id",
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**id:** `str`
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+## Email LinkToken
+client.email.link_token.create(...)
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Creates a link token to be used when linking a new end user. The link token expires after single use.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from merge import Merge
+from merge.resources.email import CategoriesEnum
+
+client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+)
+client.email.link_token.create(
+ end_user_email_address="example@gmail.com",
+ end_user_organization_name="Test Organization",
+ end_user_origin_id="12345",
+ categories=[CategoriesEnum.HRIS, CategoriesEnum.ATS],
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**end_user_email_address:** `str` — Your end user's email address. This is purely for identification purposes - setting this value will not cause any emails to be sent.
+
+
+
+
+
+-
+
+**end_user_organization_name:** `str` — Your end user's organization.
+
+
+
+
+
+-
+
+**end_user_origin_id:** `str` — This unique identifier typically represents the ID for your end user in your product's database. This value must be distinct from other Linked Accounts' unique identifiers.
+
+
+
+
+
+-
+
+**categories:** `typing.Sequence[CategoriesEnum]` — The integration categories to show in Merge Link.
+
+
+
+
+
+-
+
+**integration:** `typing.Optional[str]` — The slug of a specific pre-selected integration for this linking flow token. For examples of slugs, see https://docs.merge.dev/guides/merge-link/single-integration/.
+
+
+
+
+
+-
+
+**link_expiry_mins:** `typing.Optional[int]` — An integer number of minutes between [30, 720 or 10080 if for a Magic Link URL] for how long this token is valid. Defaults to 30.
+
+
+
+
+
+-
+
+**should_create_magic_link_url:** `typing.Optional[bool]` — Whether to generate a Magic Link URL. Defaults to false. For more information on Magic Link, see https://merge.dev/blog/integrations-fast-say-hello-to-magic-link.
+
+
+
+
+
+-
+
+**hide_admin_magic_link:** `typing.Optional[bool]` — Whether to generate a Magic Link URL on the Admin Needed screen during the linking flow. Defaults to false. For more information on Magic Link, see https://merge.dev/blog/integrations-fast-say-hello-to-magic-link.
+
+
+
+
+
+-
+
+**common_models:** `typing.Optional[typing.Sequence[CommonModelScopesBodyRequest]]` — An array of objects to specify the models and fields that will be disabled for a given Linked Account. Each object uses model_id, enabled_actions, and disabled_fields to specify the model, method, and fields that are scoped for a given Linked Account.
+
+
+
+
+
+-
+
+**category_common_model_scopes:** `typing.Optional[
+ typing.Dict[
+ str,
+ typing.Optional[
+ typing.Sequence[IndividualCommonModelScopeDeserializerRequest]
+ ],
+ ]
+]` — When creating a Link Token, you can set permissions for Common Models that will apply to the account that is going to be linked. Any model or field not specified in link token payload will default to existing settings.
+
+
+
+
+
+-
+
+**language:** `typing.Optional[EndUserDetailsRequestLanguage]` — The following subset of IETF language tags can be used to configure localization.
+
+
+
+
+
+-
+
+**are_syncs_disabled:** `typing.Optional[bool]` — The boolean that indicates whether initial, periodic, and force syncs will be disabled.
+
+
+
+
+
+-
+
+**integration_specific_config:** `typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]` — A JSON object containing integration-specific configuration options.
+
+
+
+
+
+-
+
+**completed_account_initial_screen:** `typing.Optional[EndUserDetailsRequestCompletedAccountInitialScreen]` — When creating a Link token, you can specifiy the initial screen of Linking Flow for a completed Linked Account.
+
+
+
+
+
+-
+
+**linked_destination_id:** `typing.Optional[str]` — The UUID of the linked destination that you want this Linked Account to be tied to.
+
+
+
+
+
+-
+
+**credential_id:** `typing.Optional[str]` — The id of the credential that you want this Linked Account to be tied to.
+
+
+
+
+
+-
+
+**ekm_enabled:** `typing.Optional[bool]` — Whether to enable EKM (External Key Management) for this Linked Account.
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+## Email LinkedAccounts
+client.email.linked_accounts.list(...)
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+List linked accounts for your organization.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from merge import Merge
+from merge.resources.email.resources.linked_accounts import (
+ LinkedAccountsListRequestCategory,
+)
+
+client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+)
+client.email.linked_accounts.list(
+ category=LinkedAccountsListRequestCategory.ACCOUNTING,
+ cursor="cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw",
+ end_user_email_address="end_user_email_address",
+ end_user_organization_name="end_user_organization_name",
+ end_user_origin_id="end_user_origin_id",
+ end_user_origin_ids="end_user_origin_ids",
+ id="id",
+ ids="ids",
+ include_duplicates=True,
+ integration_name="integration_name",
+ is_test_account="is_test_account",
+ page_size=1,
+ status="status",
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**category:** `typing.Optional[LinkedAccountsListRequestCategory]` — Options: `hris`, `ats`, `accounting`, `ticketing`, `crm`, `mktg`, `filestorage`, `knowledgebase`, `chat`
+
+
+
+
+
+-
+
+**cursor:** `typing.Optional[str]` — The pagination cursor value.
+
+
+
+
+
+-
+
+**end_user_email_address:** `typing.Optional[str]` — If provided, will only return linked accounts associated with the given email address.
+
+
+
+
+
+-
+
+**end_user_organization_name:** `typing.Optional[str]` — If provided, will only return linked accounts associated with the given organization name.
+
+
+
+
+
+-
+
+**end_user_origin_id:** `typing.Optional[str]` — If provided, will only return linked accounts associated with the given origin ID.
+
+
+
+
+
+-
+
+**end_user_origin_ids:** `typing.Optional[str]` — Comma-separated list of EndUser origin IDs, making it possible to specify multiple EndUsers at once.
+
+
+
+
+
+-
+
+**id:** `typing.Optional[str]`
+
+
+
+
+
+-
+
+**ids:** `typing.Optional[str]` — Comma-separated list of LinkedAccount IDs, making it possible to specify multiple LinkedAccounts at once.
+
+
+
+
+
+-
+
+**include_duplicates:** `typing.Optional[bool]` — If `true`, will include complete production duplicates of the account specified by the `id` query parameter in the response. `id` must be for a complete production linked account.
+
+
+
+
+
+-
+
+**integration_name:** `typing.Optional[str]` — If provided, will only return linked accounts associated with the given integration name.
+
+
+
+
+
+-
+
+**is_test_account:** `typing.Optional[str]` — If included, will only include test linked accounts. If not included, will only include non-test linked accounts.
+
+
+
+
+
+-
+
+**page_size:** `typing.Optional[int]` — Number of results to return per page. The maximum limit is 100.
+
+
+
+
+
+-
+
+**status:** `typing.Optional[str]` — Filter by status. Options: `COMPLETE`, `IDLE`, `INCOMPLETE`, `RELINK_NEEDED`
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+## Email Mailboxes
+client.email.mailboxes.list(...)
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Returns a list of `Mailbox` objects.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+import datetime
+
+from merge import Merge
+
+client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+)
+client.email.mailboxes.list(
+ created_after=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ created_before=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ cursor="cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw",
+ include_deleted_data=True,
+ include_remote_data=True,
+ include_shell_data=True,
+ modified_after=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ modified_before=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ page_size=1,
+ primary_email_address_id="primary_email_address_id",
+ remote_id="remote_id",
+ user_id="user_id",
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**created_after:** `typing.Optional[dt.datetime]` — If provided, will only return objects created after this datetime.
+
+
+
+
+
+-
+
+**created_before:** `typing.Optional[dt.datetime]` — If provided, will only return objects created before this datetime.
+
+
+
+
+
+-
+
+**cursor:** `typing.Optional[str]` — The pagination cursor value.
+
+
+
+
+
+-
+
+**expand:** `typing.Optional[
+ typing.Union[
+ MailboxesListRequestExpandItem,
+ typing.Sequence[MailboxesListRequestExpandItem],
+ ]
+]` — Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+
+
+
+
+-
+
+**include_deleted_data:** `typing.Optional[bool]` — Indicates whether or not this object has been deleted in the third party platform. Full coverage deletion detection is a premium add-on. Native deletion detection is offered for free with limited coverage. [Learn more](https://docs.merge.dev/integrations/hris/supported-features/).
+
+
+
+
+
+-
+
+**include_remote_data:** `typing.Optional[bool]` — Whether to include the original data Merge fetched from the third-party to produce these models.
+
+
+
+
+
+-
+
+**include_shell_data:** `typing.Optional[bool]` — Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+
+
+
+
+-
+
+**modified_after:** `typing.Optional[dt.datetime]` — If provided, only objects synced by Merge after this date time will be returned.
+
+
+
+
+
+-
+
+**modified_before:** `typing.Optional[dt.datetime]` — If provided, only objects synced by Merge before this date time will be returned.
+
+
+
+
+
+-
+
+**page_size:** `typing.Optional[int]` — Number of results to return per page. The maximum limit is 100.
+
+
+
+
+
+-
+
+**primary_email_address_id:** `typing.Optional[str]` — If provided, will only return Mailboxes with this primary EmailAddress.
+
+
+
+
+
+-
+
+**remote_fields:** `typing.Optional[typing.Literal["type"]]` — Deprecated. Use show_enum_origins.
+
+
+
+
+
+-
+
+**remote_id:** `typing.Optional[str]` — The API provider's ID for the given object.
+
+
+
+
+
+-
+
+**show_enum_origins:** `typing.Optional[typing.Literal["type"]]` — A comma separated list of enum field names for which you'd like the original values to be returned, instead of Merge's normalized enum values. [Learn more](https://help.merge.dev/en/articles/8950958-show_enum_origins-query-parameter)
+
+
+
+
+
+-
+
+**user_id:** `typing.Optional[str]` — If provided, will only return Mailboxes associated with this User.
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+client.email.mailboxes.retrieve(...)
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Returns a `Mailbox` object with the given `id`.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from merge import Merge
+
+client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+)
+client.email.mailboxes.retrieve(
+ id="id",
+ include_remote_data=True,
+ include_shell_data=True,
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**id:** `str`
+
+
+
+
+
+-
+
+**expand:** `typing.Optional[
+ typing.Union[
+ MailboxesRetrieveRequestExpandItem,
+ typing.Sequence[MailboxesRetrieveRequestExpandItem],
+ ]
+]` — Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+
+
+
+
+-
+
+**include_remote_data:** `typing.Optional[bool]` — Whether to include the original data Merge fetched from the third-party to produce these models.
+
+
+
+
+
+-
+
+**include_shell_data:** `typing.Optional[bool]` — Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+
+
+
+
+-
+
+**remote_fields:** `typing.Optional[typing.Literal["type"]]` — Deprecated. Use show_enum_origins.
+
+
+
+
+
+-
+
+**show_enum_origins:** `typing.Optional[typing.Literal["type"]]` — A comma separated list of enum field names for which you'd like the original values to be returned, instead of Merge's normalized enum values. [Learn more](https://help.merge.dev/en/articles/8950958-show_enum_origins-query-parameter)
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+## Email Messages
+client.email.messages.list(...)
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Returns a list of `Message` objects.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+import datetime
+
+from merge import Merge
+
+client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+)
+client.email.messages.list(
+ bcc_address_id="bcc_address_id",
+ cc_address_id="cc_address_id",
+ created_after=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ created_before=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ cursor="cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw",
+ from_address_id="from_address_id",
+ include_deleted_data=True,
+ include_remote_data=True,
+ include_shell_data=True,
+ mailbox_id="mailbox_id",
+ modified_after=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ modified_before=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ page_size=1,
+ remote_id="remote_id",
+ thread_id="thread_id",
+ to_address_id="to_address_id",
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**bcc_address_id:** `typing.Optional[str]` — If provided, will only return Messages with this EmailAddress in BCC.
+
+
+
+
+
+-
+
+**cc_address_id:** `typing.Optional[str]` — If provided, will only return Messages with this EmailAddress in CC.
+
+
+
+
+
+-
+
+**created_after:** `typing.Optional[dt.datetime]` — If provided, will only return objects created after this datetime.
+
+
+
+
+
+-
+
+**created_before:** `typing.Optional[dt.datetime]` — If provided, will only return objects created before this datetime.
+
+
+
+
+
+-
+
+**cursor:** `typing.Optional[str]` — The pagination cursor value.
+
+
+
+
+
+-
+
+**expand:** `typing.Optional[
+ typing.Union[
+ MessagesListRequestExpandItem,
+ typing.Sequence[MessagesListRequestExpandItem],
+ ]
+]` — Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+
+
+
+
+-
+
+**from_address_id:** `typing.Optional[str]` — If provided, will only return Messages sent from this EmailAddress.
+
+
+
+
+
+-
+
+**include_deleted_data:** `typing.Optional[bool]` — Indicates whether or not this object has been deleted in the third party platform. Full coverage deletion detection is a premium add-on. Native deletion detection is offered for free with limited coverage. [Learn more](https://docs.merge.dev/integrations/hris/supported-features/).
+
+
+
+
+
+-
+
+**include_remote_data:** `typing.Optional[bool]` — Whether to include the original data Merge fetched from the third-party to produce these models.
+
+
+
+
+
+-
+
+**include_shell_data:** `typing.Optional[bool]` — Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+
+
+
+
+-
+
+**mailbox_id:** `typing.Optional[str]` — If provided, will only return Messages in this Mailbox.
+
+
+
+
+
+-
+
+**modified_after:** `typing.Optional[dt.datetime]` — If provided, only objects synced by Merge after this date time will be returned.
+
+
+
+
+
+-
+
+**modified_before:** `typing.Optional[dt.datetime]` — If provided, only objects synced by Merge before this date time will be returned.
+
+
+
+
+
+-
+
+**page_size:** `typing.Optional[int]` — Number of results to return per page. The maximum limit is 100.
+
+
+
+
+
+-
+
+**remote_id:** `typing.Optional[str]` — The API provider's ID for the given object.
+
+
+
+
+
+-
+
+**thread_id:** `typing.Optional[str]` — If provided, will only return Messages belonging to this Thread.
+
+
+
+
+
+-
+
+**to_address_id:** `typing.Optional[str]` — If provided, will only return Messages sent to this EmailAddress.
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+client.email.messages.retrieve(...)
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Returns a `Message` object with the given `id`.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from merge import Merge
+
+client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+)
+client.email.messages.retrieve(
+ id="id",
+ include_remote_data=True,
+ include_shell_data=True,
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**id:** `str`
+
+
+
+
+
+-
+
+**expand:** `typing.Optional[
+ typing.Union[
+ MessagesRetrieveRequestExpandItem,
+ typing.Sequence[MessagesRetrieveRequestExpandItem],
+ ]
+]` — Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+
+
+
+
+-
+
+**include_remote_data:** `typing.Optional[bool]` — Whether to include the original data Merge fetched from the third-party to produce these models.
+
+
+
+
+
+-
+
+**include_shell_data:** `typing.Optional[bool]` — Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+## Email Passthrough
+client.email.passthrough.create(...)
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Pull data from an endpoint not currently supported by Merge.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from merge import Merge
+from merge.resources.email import DataPassthroughRequest, MethodEnum
+
+client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+)
+client.email.passthrough.create(
+ request=DataPassthroughRequest(
+ method=MethodEnum.GET,
+ path="/scooters",
+ ),
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**request:** `DataPassthroughRequest`
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+## Email RegenerateKey
+client.email.regenerate_key.create(...)
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Exchange remote keys.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from merge import Merge
+
+client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+)
+client.email.regenerate_key.create(
+ name="Remote Deployment Key 1",
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**name:** `str` — The name of the remote key
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+## Email SyncStatus
+client.email.sync_status.list(...)
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Get sync status for the current sync and the most recently finished sync. `last_sync_start` represents the most recent time any sync began. `last_sync_finished` represents the most recent time any sync completed. These timestamps may correspond to different sync instances which may result in a sync start time being later than a separate sync completed time. To ensure you are retrieving the latest available data reference the `last_sync_finished` timestamp where `last_sync_result` is `DONE`. Possible values for `status` and `last_sync_result` are `DISABLED`, `DONE`, `FAILED`, `PARTIALLY_SYNCED`, `PAUSED`, `SYNCING`. Learn more about sync status in our [Help Center](https://help.merge.dev/en/articles/8184193-merge-sync-statuses).
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from merge import Merge
+
+client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+)
+client.email.sync_status.list(
+ cursor="cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw",
+ page_size=1,
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**cursor:** `typing.Optional[str]` — The pagination cursor value.
+
+
+
+
+
+-
+
+**page_size:** `typing.Optional[int]` — Number of results to return per page. The maximum limit is 100.
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+## Email ForceResync
+client.email.force_resync.sync_status_resync_create()
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Force re-sync of all models. This endpoint is available for monthly, quarterly, and highest sync frequency customers on the Professional or Enterprise plans. Doing so will consume a sync credit for the relevant linked account. Force re-syncs can also be triggered manually in the Merge Dashboard and is available for all customers.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from merge import Merge
+
+client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+)
+client.email.force_resync.sync_status_resync_create()
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+## Email Users
+client.email.users.list(...)
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Returns a list of `User` objects.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+import datetime
+
+from merge import Merge
+
+client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+)
+client.email.users.list(
+ created_after=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ created_before=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ cursor="cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw",
+ email_address_id="email_address_id",
+ group_id="group_id",
+ include_deleted_data=True,
+ include_remote_data=True,
+ include_shell_data=True,
+ mailbox_id="mailbox_id",
+ modified_after=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ modified_before=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ page_size=1,
+ remote_id="remote_id",
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**created_after:** `typing.Optional[dt.datetime]` — If provided, will only return objects created after this datetime.
+
+
+
+
+
+-
+
+**created_before:** `typing.Optional[dt.datetime]` — If provided, will only return objects created before this datetime.
+
+
+
+
+
+-
+
+**cursor:** `typing.Optional[str]` — The pagination cursor value.
+
+
+
+
+
+-
+
+**email_address_id:** `typing.Optional[str]` — If provided, will only return Users with this EmailAddress.
+
+
+
+
+
+-
+
+**expand:** `typing.Optional[
+ typing.Union[
+ UsersListRequestExpandItem, typing.Sequence[UsersListRequestExpandItem]
+ ]
+]` — Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+
+
+
+
+-
+
+**group_id:** `typing.Optional[str]` — If provided, will only return Users belonging to this Group.
+
+
+
+
+
+-
+
+**include_deleted_data:** `typing.Optional[bool]` — Indicates whether or not this object has been deleted in the third party platform. Full coverage deletion detection is a premium add-on. Native deletion detection is offered for free with limited coverage. [Learn more](https://docs.merge.dev/integrations/hris/supported-features/).
+
+
+
+
+
+-
+
+**include_remote_data:** `typing.Optional[bool]` — Whether to include the original data Merge fetched from the third-party to produce these models.
+
+
+
+
+
+-
+
+**include_shell_data:** `typing.Optional[bool]` — Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+
+
+
+
+-
+
+**mailbox_id:** `typing.Optional[str]` — If provided, will only return Users associated with this Mailbox.
+
+
+
+
+
+-
+
+**modified_after:** `typing.Optional[dt.datetime]` — If provided, only objects synced by Merge after this date time will be returned.
+
+
+
+
+
+-
+
+**modified_before:** `typing.Optional[dt.datetime]` — If provided, only objects synced by Merge before this date time will be returned.
+
+
+
+
+
+-
+
+**page_size:** `typing.Optional[int]` — Number of results to return per page. The maximum limit is 100.
+
+
+
+
+
+-
+
+**remote_fields:** `typing.Optional[typing.Literal["type"]]` — Deprecated. Use show_enum_origins.
+
+
+
+
+
+-
+
+**remote_id:** `typing.Optional[str]` — The API provider's ID for the given object.
+
+
+
+
+
+-
+
+**show_enum_origins:** `typing.Optional[typing.Literal["type"]]` — A comma separated list of enum field names for which you'd like the original values to be returned, instead of Merge's normalized enum values. [Learn more](https://help.merge.dev/en/articles/8950958-show_enum_origins-query-parameter)
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+client.email.users.retrieve(...)
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Returns a `User` object with the given `id`.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from merge import Merge
+
+client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+)
+client.email.users.retrieve(
+ id="id",
+ include_remote_data=True,
+ include_shell_data=True,
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**id:** `str`
+
+
+
+
+
+-
+
+**expand:** `typing.Optional[
+ typing.Union[
+ UsersRetrieveRequestExpandItem,
+ typing.Sequence[UsersRetrieveRequestExpandItem],
+ ]
+]` — Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+
+
+
+
+-
+
+**include_remote_data:** `typing.Optional[bool]` — Whether to include the original data Merge fetched from the third-party to produce these models.
+
+
+
+
+
+-
+
+**include_shell_data:** `typing.Optional[bool]` — Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+
+
+
+
+-
+
+**remote_fields:** `typing.Optional[typing.Literal["type"]]` — Deprecated. Use show_enum_origins.
+
+
+
+
+
+-
+
+**show_enum_origins:** `typing.Optional[typing.Literal["type"]]` — A comma separated list of enum field names for which you'd like the original values to be returned, instead of Merge's normalized enum values. [Learn more](https://help.merge.dev/en/articles/8950958-show_enum_origins-query-parameter)
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+## Email WebhookReceivers
+client.email.webhook_receivers.list()
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Returns a list of `WebhookReceiver` objects.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from merge import Merge
+
+client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+)
+client.email.webhook_receivers.list()
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+client.email.webhook_receivers.create(...)
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+Creates a `WebhookReceiver` object with the given values.
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from merge import Merge
+
+client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+)
+client.email.webhook_receivers.create(
+ event="event",
+ is_active=True,
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**event:** `str`
+
+
+
+
+
+-
+
+**is_active:** `bool`
+
+
+
+
+
+-
+
+**key:** `typing.Optional[str]`
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
diff --git a/src/merge/__init__.py b/src/merge/__init__.py
index 91011bdf..eb986b55 100644
--- a/src/merge/__init__.py
+++ b/src/merge/__init__.py
@@ -6,7 +6,7 @@
from importlib import import_module
if typing.TYPE_CHECKING:
- from .resources import accounting, ats, chat, crm, filestorage, hris, knowledgebase, ticketing
+ from .resources import accounting, ats, chat, crm, email, filestorage, hris, knowledgebase, ticketing
from .client import AsyncMerge, Merge
from .environment import MergeEnvironment
from .version import __version__
@@ -19,6 +19,7 @@
"ats": ".resources",
"chat": ".resources",
"crm": ".resources",
+ "email": ".resources",
"filestorage": ".resources",
"hris": ".resources",
"knowledgebase": ".resources",
@@ -54,6 +55,7 @@ def __dir__():
"ats",
"chat",
"crm",
+ "email",
"filestorage",
"hris",
"knowledgebase",
diff --git a/src/merge/client.py b/src/merge/client.py
index 3e7de8cb..39879aac 100644
--- a/src/merge/client.py
+++ b/src/merge/client.py
@@ -13,6 +13,7 @@
from .resources.ats.client import AsyncAtsClient, AtsClient
from .resources.chat.client import AsyncChatClient, ChatClient
from .resources.crm.client import AsyncCrmClient, CrmClient
+ from .resources.email.client import AsyncEmailClient, EmailClient
from .resources.filestorage.client import AsyncFilestorageClient, FilestorageClient
from .resources.hris.client import AsyncHrisClient, HrisClient
from .resources.knowledgebase.client import AsyncKnowledgebaseClient, KnowledgebaseClient
@@ -94,6 +95,7 @@ def __init__(
self._hris: typing.Optional[HrisClient] = None
self._ticketing: typing.Optional[TicketingClient] = None
self._chat: typing.Optional[ChatClient] = None
+ self._email: typing.Optional[EmailClient] = None
self._filestorage: typing.Optional[FilestorageClient] = None
self._knowledgebase: typing.Optional[KnowledgebaseClient] = None
@@ -145,6 +147,14 @@ def chat(self):
self._chat = ChatClient(client_wrapper=self._client_wrapper)
return self._chat
+ @property
+ def email(self):
+ if self._email is None:
+ from .resources.email.client import EmailClient # noqa: E402
+
+ self._email = EmailClient(client_wrapper=self._client_wrapper)
+ return self._email
+
@property
def filestorage(self):
if self._filestorage is None:
@@ -237,6 +247,7 @@ def __init__(
self._hris: typing.Optional[AsyncHrisClient] = None
self._ticketing: typing.Optional[AsyncTicketingClient] = None
self._chat: typing.Optional[AsyncChatClient] = None
+ self._email: typing.Optional[AsyncEmailClient] = None
self._filestorage: typing.Optional[AsyncFilestorageClient] = None
self._knowledgebase: typing.Optional[AsyncKnowledgebaseClient] = None
@@ -288,6 +299,14 @@ def chat(self):
self._chat = AsyncChatClient(client_wrapper=self._client_wrapper)
return self._chat
+ @property
+ def email(self):
+ if self._email is None:
+ from .resources.email.client import AsyncEmailClient # noqa: E402
+
+ self._email = AsyncEmailClient(client_wrapper=self._client_wrapper)
+ return self._email
+
@property
def filestorage(self):
if self._filestorage is None:
diff --git a/src/merge/resources/__init__.py b/src/merge/resources/__init__.py
index 7fdb8ad9..8a1aa62e 100644
--- a/src/merge/resources/__init__.py
+++ b/src/merge/resources/__init__.py
@@ -6,12 +6,13 @@
from importlib import import_module
if typing.TYPE_CHECKING:
- from . import accounting, ats, chat, crm, filestorage, hris, knowledgebase, ticketing
+ from . import accounting, ats, chat, crm, email, filestorage, hris, knowledgebase, ticketing
_dynamic_imports: typing.Dict[str, str] = {
"accounting": ".",
"ats": ".",
"chat": ".",
"crm": ".",
+ "email": ".",
"filestorage": ".",
"hris": ".",
"knowledgebase": ".",
@@ -38,4 +39,4 @@ def __dir__():
return sorted(lazy_attrs)
-__all__ = ["accounting", "ats", "chat", "crm", "filestorage", "hris", "knowledgebase", "ticketing"]
+__all__ = ["accounting", "ats", "chat", "crm", "email", "filestorage", "hris", "knowledgebase", "ticketing"]
diff --git a/src/merge/resources/email/__init__.py b/src/merge/resources/email/__init__.py
new file mode 100644
index 00000000..94abbf81
--- /dev/null
+++ b/src/merge/resources/email/__init__.py
@@ -0,0 +1,469 @@
+# This file was auto-generated by Fern from our API Definition.
+
+# isort: skip_file
+
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .types import (
+ AccountDetails,
+ AccountDetailsAndActions,
+ AccountDetailsAndActionsCategory,
+ AccountDetailsAndActionsIntegration,
+ AccountDetailsAndActionsStatus,
+ AccountDetailsAndActionsStatusEnum,
+ AccountDetailsCategory,
+ AccountIntegration,
+ AccountToken,
+ ActionsEnum,
+ AdvancedMetadata,
+ AsyncPassthroughReciept,
+ AuditLogEvent,
+ AuditLogEventEventType,
+ AuditLogEventRole,
+ AvailableActions,
+ CategoriesEnum,
+ CategoryEnum,
+ CommonModelScopeApi,
+ CommonModelScopesBodyRequest,
+ CompletedAccountInitialScreenEnum,
+ DataPassthroughRequest,
+ DataPassthroughRequestMethod,
+ DataPassthroughRequestRequestFormat,
+ DebugModeLog,
+ DebugModelLogSummary,
+ EffectEnum,
+ EmailAddress,
+ EmailAddressFieldMappings,
+ EnabledActionsEnum,
+ EncodingEnum,
+ ErrorValidationProblem,
+ EventTypeEnum,
+ ExternalTargetFieldApi,
+ ExternalTargetFieldApiResponse,
+ FieldMappingApiInstance,
+ FieldMappingApiInstanceRemoteField,
+ FieldMappingApiInstanceRemoteFieldRemoteEndpointInfo,
+ FieldMappingApiInstanceResponse,
+ FieldMappingApiInstanceTargetField,
+ FieldMappingInstanceResponse,
+ FieldPermissionDeserializer,
+ FieldPermissionDeserializerRequest,
+ Folder,
+ FolderFieldMappings,
+ Group,
+ GroupFieldMappings,
+ IndividualCommonModelScopeDeserializer,
+ IndividualCommonModelScopeDeserializerRequest,
+ Issue,
+ IssueStatus,
+ IssueStatusEnum,
+ LanguageEnum,
+ LastSyncResultEnum,
+ LinkToken,
+ Mailbox,
+ MailboxFieldMappings,
+ MailboxType,
+ MailboxTypeEnum,
+ Message,
+ MethodEnum,
+ ModelOperation,
+ ModelPermissionDeserializer,
+ ModelPermissionDeserializerRequest,
+ MultipartFormFieldRequest,
+ MultipartFormFieldRequestEncoding,
+ PaginatedAccountDetailsAndActionsList,
+ PaginatedAuditLogEventList,
+ PaginatedEmailAddressList,
+ PaginatedFolderList,
+ PaginatedGroupList,
+ PaginatedIssueList,
+ PaginatedMailboxList,
+ PaginatedMessageList,
+ PaginatedSyncStatusList,
+ PaginatedUserList,
+ Permission,
+ PermissionEffect,
+ PermissionFieldMappings,
+ RegenerateAccountToken,
+ RemoteData,
+ RemoteEndpointInfo,
+ RemoteFieldApi,
+ RemoteFieldApiAdvancedMetadata,
+ RemoteFieldApiCoverage,
+ RemoteFieldApiResponse,
+ RemoteKey,
+ RemoteResponse,
+ RemoteResponseResponseType,
+ RequestFormatEnum,
+ ResponseTypeEnum,
+ RoleEnum,
+ SelectiveSyncConfigurationsUsageEnum,
+ StatusFd5Enum,
+ SyncStatus,
+ SyncStatusLastSyncResult,
+ SyncStatusStatus,
+ User,
+ UserFieldMappings,
+ UserType,
+ UserTypeEnum,
+ ValidationProblemSource,
+ WarningValidationProblem,
+ WebhookReceiver,
+ )
+ from .resources import (
+ AsyncPassthroughRetrieveResponse,
+ EmailAddressesListRequestExpandItem,
+ EmailAddressesRetrieveRequestExpandItem,
+ EndUserDetailsRequestCompletedAccountInitialScreen,
+ EndUserDetailsRequestLanguage,
+ FoldersListRequestExpandItem,
+ FoldersRetrieveRequestExpandItem,
+ GroupsListRequestExpandItem,
+ GroupsRetrieveRequestExpandItem,
+ IssuesListRequestStatus,
+ LinkedAccountsListRequestCategory,
+ MailboxesListRequestExpandItem,
+ MailboxesRetrieveRequestExpandItem,
+ MessagesListRequestExpandItem,
+ MessagesRetrieveRequestExpandItem,
+ UsersListRequestExpandItem,
+ UsersRetrieveRequestExpandItem,
+ account_details,
+ account_token,
+ async_passthrough,
+ audit_trail,
+ available_actions,
+ delete_account,
+ email_addresses,
+ field_mapping,
+ folders,
+ force_resync,
+ generate_key,
+ groups,
+ issues,
+ link_token,
+ linked_accounts,
+ mailboxes,
+ messages,
+ passthrough,
+ regenerate_key,
+ scopes,
+ sync_status,
+ users,
+ webhook_receivers,
+ )
+_dynamic_imports: typing.Dict[str, str] = {
+ "AccountDetails": ".types",
+ "AccountDetailsAndActions": ".types",
+ "AccountDetailsAndActionsCategory": ".types",
+ "AccountDetailsAndActionsIntegration": ".types",
+ "AccountDetailsAndActionsStatus": ".types",
+ "AccountDetailsAndActionsStatusEnum": ".types",
+ "AccountDetailsCategory": ".types",
+ "AccountIntegration": ".types",
+ "AccountToken": ".types",
+ "ActionsEnum": ".types",
+ "AdvancedMetadata": ".types",
+ "AsyncPassthroughReciept": ".types",
+ "AsyncPassthroughRetrieveResponse": ".resources",
+ "AuditLogEvent": ".types",
+ "AuditLogEventEventType": ".types",
+ "AuditLogEventRole": ".types",
+ "AvailableActions": ".types",
+ "CategoriesEnum": ".types",
+ "CategoryEnum": ".types",
+ "CommonModelScopeApi": ".types",
+ "CommonModelScopesBodyRequest": ".types",
+ "CompletedAccountInitialScreenEnum": ".types",
+ "DataPassthroughRequest": ".types",
+ "DataPassthroughRequestMethod": ".types",
+ "DataPassthroughRequestRequestFormat": ".types",
+ "DebugModeLog": ".types",
+ "DebugModelLogSummary": ".types",
+ "EffectEnum": ".types",
+ "EmailAddress": ".types",
+ "EmailAddressFieldMappings": ".types",
+ "EmailAddressesListRequestExpandItem": ".resources",
+ "EmailAddressesRetrieveRequestExpandItem": ".resources",
+ "EnabledActionsEnum": ".types",
+ "EncodingEnum": ".types",
+ "EndUserDetailsRequestCompletedAccountInitialScreen": ".resources",
+ "EndUserDetailsRequestLanguage": ".resources",
+ "ErrorValidationProblem": ".types",
+ "EventTypeEnum": ".types",
+ "ExternalTargetFieldApi": ".types",
+ "ExternalTargetFieldApiResponse": ".types",
+ "FieldMappingApiInstance": ".types",
+ "FieldMappingApiInstanceRemoteField": ".types",
+ "FieldMappingApiInstanceRemoteFieldRemoteEndpointInfo": ".types",
+ "FieldMappingApiInstanceResponse": ".types",
+ "FieldMappingApiInstanceTargetField": ".types",
+ "FieldMappingInstanceResponse": ".types",
+ "FieldPermissionDeserializer": ".types",
+ "FieldPermissionDeserializerRequest": ".types",
+ "Folder": ".types",
+ "FolderFieldMappings": ".types",
+ "FoldersListRequestExpandItem": ".resources",
+ "FoldersRetrieveRequestExpandItem": ".resources",
+ "Group": ".types",
+ "GroupFieldMappings": ".types",
+ "GroupsListRequestExpandItem": ".resources",
+ "GroupsRetrieveRequestExpandItem": ".resources",
+ "IndividualCommonModelScopeDeserializer": ".types",
+ "IndividualCommonModelScopeDeserializerRequest": ".types",
+ "Issue": ".types",
+ "IssueStatus": ".types",
+ "IssueStatusEnum": ".types",
+ "IssuesListRequestStatus": ".resources",
+ "LanguageEnum": ".types",
+ "LastSyncResultEnum": ".types",
+ "LinkToken": ".types",
+ "LinkedAccountsListRequestCategory": ".resources",
+ "Mailbox": ".types",
+ "MailboxFieldMappings": ".types",
+ "MailboxType": ".types",
+ "MailboxTypeEnum": ".types",
+ "MailboxesListRequestExpandItem": ".resources",
+ "MailboxesRetrieveRequestExpandItem": ".resources",
+ "Message": ".types",
+ "MessagesListRequestExpandItem": ".resources",
+ "MessagesRetrieveRequestExpandItem": ".resources",
+ "MethodEnum": ".types",
+ "ModelOperation": ".types",
+ "ModelPermissionDeserializer": ".types",
+ "ModelPermissionDeserializerRequest": ".types",
+ "MultipartFormFieldRequest": ".types",
+ "MultipartFormFieldRequestEncoding": ".types",
+ "PaginatedAccountDetailsAndActionsList": ".types",
+ "PaginatedAuditLogEventList": ".types",
+ "PaginatedEmailAddressList": ".types",
+ "PaginatedFolderList": ".types",
+ "PaginatedGroupList": ".types",
+ "PaginatedIssueList": ".types",
+ "PaginatedMailboxList": ".types",
+ "PaginatedMessageList": ".types",
+ "PaginatedSyncStatusList": ".types",
+ "PaginatedUserList": ".types",
+ "Permission": ".types",
+ "PermissionEffect": ".types",
+ "PermissionFieldMappings": ".types",
+ "RegenerateAccountToken": ".types",
+ "RemoteData": ".types",
+ "RemoteEndpointInfo": ".types",
+ "RemoteFieldApi": ".types",
+ "RemoteFieldApiAdvancedMetadata": ".types",
+ "RemoteFieldApiCoverage": ".types",
+ "RemoteFieldApiResponse": ".types",
+ "RemoteKey": ".types",
+ "RemoteResponse": ".types",
+ "RemoteResponseResponseType": ".types",
+ "RequestFormatEnum": ".types",
+ "ResponseTypeEnum": ".types",
+ "RoleEnum": ".types",
+ "SelectiveSyncConfigurationsUsageEnum": ".types",
+ "StatusFd5Enum": ".types",
+ "SyncStatus": ".types",
+ "SyncStatusLastSyncResult": ".types",
+ "SyncStatusStatus": ".types",
+ "User": ".types",
+ "UserFieldMappings": ".types",
+ "UserType": ".types",
+ "UserTypeEnum": ".types",
+ "UsersListRequestExpandItem": ".resources",
+ "UsersRetrieveRequestExpandItem": ".resources",
+ "ValidationProblemSource": ".types",
+ "WarningValidationProblem": ".types",
+ "WebhookReceiver": ".types",
+ "account_details": ".resources",
+ "account_token": ".resources",
+ "async_passthrough": ".resources",
+ "audit_trail": ".resources",
+ "available_actions": ".resources",
+ "delete_account": ".resources",
+ "email_addresses": ".resources",
+ "field_mapping": ".resources",
+ "folders": ".resources",
+ "force_resync": ".resources",
+ "generate_key": ".resources",
+ "groups": ".resources",
+ "issues": ".resources",
+ "link_token": ".resources",
+ "linked_accounts": ".resources",
+ "mailboxes": ".resources",
+ "messages": ".resources",
+ "passthrough": ".resources",
+ "regenerate_key": ".resources",
+ "scopes": ".resources",
+ "sync_status": ".resources",
+ "users": ".resources",
+ "webhook_receivers": ".resources",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ result = getattr(module, attr_name)
+ return result
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
+
+__all__ = [
+ "AccountDetails",
+ "AccountDetailsAndActions",
+ "AccountDetailsAndActionsCategory",
+ "AccountDetailsAndActionsIntegration",
+ "AccountDetailsAndActionsStatus",
+ "AccountDetailsAndActionsStatusEnum",
+ "AccountDetailsCategory",
+ "AccountIntegration",
+ "AccountToken",
+ "ActionsEnum",
+ "AdvancedMetadata",
+ "AsyncPassthroughReciept",
+ "AsyncPassthroughRetrieveResponse",
+ "AuditLogEvent",
+ "AuditLogEventEventType",
+ "AuditLogEventRole",
+ "AvailableActions",
+ "CategoriesEnum",
+ "CategoryEnum",
+ "CommonModelScopeApi",
+ "CommonModelScopesBodyRequest",
+ "CompletedAccountInitialScreenEnum",
+ "DataPassthroughRequest",
+ "DataPassthroughRequestMethod",
+ "DataPassthroughRequestRequestFormat",
+ "DebugModeLog",
+ "DebugModelLogSummary",
+ "EffectEnum",
+ "EmailAddress",
+ "EmailAddressFieldMappings",
+ "EmailAddressesListRequestExpandItem",
+ "EmailAddressesRetrieveRequestExpandItem",
+ "EnabledActionsEnum",
+ "EncodingEnum",
+ "EndUserDetailsRequestCompletedAccountInitialScreen",
+ "EndUserDetailsRequestLanguage",
+ "ErrorValidationProblem",
+ "EventTypeEnum",
+ "ExternalTargetFieldApi",
+ "ExternalTargetFieldApiResponse",
+ "FieldMappingApiInstance",
+ "FieldMappingApiInstanceRemoteField",
+ "FieldMappingApiInstanceRemoteFieldRemoteEndpointInfo",
+ "FieldMappingApiInstanceResponse",
+ "FieldMappingApiInstanceTargetField",
+ "FieldMappingInstanceResponse",
+ "FieldPermissionDeserializer",
+ "FieldPermissionDeserializerRequest",
+ "Folder",
+ "FolderFieldMappings",
+ "FoldersListRequestExpandItem",
+ "FoldersRetrieveRequestExpandItem",
+ "Group",
+ "GroupFieldMappings",
+ "GroupsListRequestExpandItem",
+ "GroupsRetrieveRequestExpandItem",
+ "IndividualCommonModelScopeDeserializer",
+ "IndividualCommonModelScopeDeserializerRequest",
+ "Issue",
+ "IssueStatus",
+ "IssueStatusEnum",
+ "IssuesListRequestStatus",
+ "LanguageEnum",
+ "LastSyncResultEnum",
+ "LinkToken",
+ "LinkedAccountsListRequestCategory",
+ "Mailbox",
+ "MailboxFieldMappings",
+ "MailboxType",
+ "MailboxTypeEnum",
+ "MailboxesListRequestExpandItem",
+ "MailboxesRetrieveRequestExpandItem",
+ "Message",
+ "MessagesListRequestExpandItem",
+ "MessagesRetrieveRequestExpandItem",
+ "MethodEnum",
+ "ModelOperation",
+ "ModelPermissionDeserializer",
+ "ModelPermissionDeserializerRequest",
+ "MultipartFormFieldRequest",
+ "MultipartFormFieldRequestEncoding",
+ "PaginatedAccountDetailsAndActionsList",
+ "PaginatedAuditLogEventList",
+ "PaginatedEmailAddressList",
+ "PaginatedFolderList",
+ "PaginatedGroupList",
+ "PaginatedIssueList",
+ "PaginatedMailboxList",
+ "PaginatedMessageList",
+ "PaginatedSyncStatusList",
+ "PaginatedUserList",
+ "Permission",
+ "PermissionEffect",
+ "PermissionFieldMappings",
+ "RegenerateAccountToken",
+ "RemoteData",
+ "RemoteEndpointInfo",
+ "RemoteFieldApi",
+ "RemoteFieldApiAdvancedMetadata",
+ "RemoteFieldApiCoverage",
+ "RemoteFieldApiResponse",
+ "RemoteKey",
+ "RemoteResponse",
+ "RemoteResponseResponseType",
+ "RequestFormatEnum",
+ "ResponseTypeEnum",
+ "RoleEnum",
+ "SelectiveSyncConfigurationsUsageEnum",
+ "StatusFd5Enum",
+ "SyncStatus",
+ "SyncStatusLastSyncResult",
+ "SyncStatusStatus",
+ "User",
+ "UserFieldMappings",
+ "UserType",
+ "UserTypeEnum",
+ "UsersListRequestExpandItem",
+ "UsersRetrieveRequestExpandItem",
+ "ValidationProblemSource",
+ "WarningValidationProblem",
+ "WebhookReceiver",
+ "account_details",
+ "account_token",
+ "async_passthrough",
+ "audit_trail",
+ "available_actions",
+ "delete_account",
+ "email_addresses",
+ "field_mapping",
+ "folders",
+ "force_resync",
+ "generate_key",
+ "groups",
+ "issues",
+ "link_token",
+ "linked_accounts",
+ "mailboxes",
+ "messages",
+ "passthrough",
+ "regenerate_key",
+ "scopes",
+ "sync_status",
+ "users",
+ "webhook_receivers",
+]
diff --git a/src/merge/resources/email/client.py b/src/merge/resources/email/client.py
new file mode 100644
index 00000000..5f811da3
--- /dev/null
+++ b/src/merge/resources/email/client.py
@@ -0,0 +1,497 @@
+# This file was auto-generated by Fern from our API Definition.
+
+from __future__ import annotations
+
+import typing
+
+from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .raw_client import AsyncRawEmailClient, RawEmailClient
+
+if typing.TYPE_CHECKING:
+ from .resources.account_details.client import AccountDetailsClient, AsyncAccountDetailsClient
+ from .resources.account_token.client import AccountTokenClient, AsyncAccountTokenClient
+ from .resources.async_passthrough.client import AsyncAsyncPassthroughClient
+ from .resources.async_passthrough.client import (
+ AsyncPassthroughClient as resources_email_resources_async_passthrough_client_AsyncPassthroughClient,
+ )
+ from .resources.audit_trail.client import AsyncAuditTrailClient, AuditTrailClient
+ from .resources.available_actions.client import AsyncAvailableActionsClient, AvailableActionsClient
+ from .resources.delete_account.client import AsyncDeleteAccountClient, DeleteAccountClient
+ from .resources.email_addresses.client import AsyncEmailAddressesClient, EmailAddressesClient
+ from .resources.field_mapping.client import AsyncFieldMappingClient, FieldMappingClient
+ from .resources.folders.client import AsyncFoldersClient, FoldersClient
+ from .resources.force_resync.client import AsyncForceResyncClient, ForceResyncClient
+ from .resources.generate_key.client import AsyncGenerateKeyClient, GenerateKeyClient
+ from .resources.groups.client import AsyncGroupsClient, GroupsClient
+ from .resources.issues.client import AsyncIssuesClient, IssuesClient
+ from .resources.link_token.client import AsyncLinkTokenClient, LinkTokenClient
+ from .resources.linked_accounts.client import AsyncLinkedAccountsClient, LinkedAccountsClient
+ from .resources.mailboxes.client import AsyncMailboxesClient, MailboxesClient
+ from .resources.messages.client import AsyncMessagesClient, MessagesClient
+ from .resources.passthrough.client import (
+ AsyncPassthroughClient as resources_email_resources_passthrough_client_AsyncPassthroughClient,
+ )
+ from .resources.passthrough.client import PassthroughClient
+ from .resources.regenerate_key.client import AsyncRegenerateKeyClient, RegenerateKeyClient
+ from .resources.scopes.client import AsyncScopesClient, ScopesClient
+ from .resources.sync_status.client import AsyncSyncStatusClient, SyncStatusClient
+ from .resources.users.client import AsyncUsersClient, UsersClient
+ from .resources.webhook_receivers.client import AsyncWebhookReceiversClient, WebhookReceiversClient
+
+
+class EmailClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._raw_client = RawEmailClient(client_wrapper=client_wrapper)
+ self._client_wrapper = client_wrapper
+ self._account_details: typing.Optional[AccountDetailsClient] = None
+ self._account_token: typing.Optional[AccountTokenClient] = None
+ self._async_passthrough: typing.Optional[
+ resources_email_resources_async_passthrough_client_AsyncPassthroughClient
+ ] = None
+ self._audit_trail: typing.Optional[AuditTrailClient] = None
+ self._available_actions: typing.Optional[AvailableActionsClient] = None
+ self._scopes: typing.Optional[ScopesClient] = None
+ self._delete_account: typing.Optional[DeleteAccountClient] = None
+ self._email_addresses: typing.Optional[EmailAddressesClient] = None
+ self._field_mapping: typing.Optional[FieldMappingClient] = None
+ self._folders: typing.Optional[FoldersClient] = None
+ self._generate_key: typing.Optional[GenerateKeyClient] = None
+ self._groups: typing.Optional[GroupsClient] = None
+ self._issues: typing.Optional[IssuesClient] = None
+ self._link_token: typing.Optional[LinkTokenClient] = None
+ self._linked_accounts: typing.Optional[LinkedAccountsClient] = None
+ self._mailboxes: typing.Optional[MailboxesClient] = None
+ self._messages: typing.Optional[MessagesClient] = None
+ self._passthrough: typing.Optional[PassthroughClient] = None
+ self._regenerate_key: typing.Optional[RegenerateKeyClient] = None
+ self._sync_status: typing.Optional[SyncStatusClient] = None
+ self._force_resync: typing.Optional[ForceResyncClient] = None
+ self._users: typing.Optional[UsersClient] = None
+ self._webhook_receivers: typing.Optional[WebhookReceiversClient] = None
+
+ @property
+ def with_raw_response(self) -> RawEmailClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ RawEmailClient
+ """
+ return self._raw_client
+
+ @property
+ def account_details(self):
+ if self._account_details is None:
+ from .resources.account_details.client import AccountDetailsClient # noqa: E402
+
+ self._account_details = AccountDetailsClient(client_wrapper=self._client_wrapper)
+ return self._account_details
+
+ @property
+ def account_token(self):
+ if self._account_token is None:
+ from .resources.account_token.client import AccountTokenClient # noqa: E402
+
+ self._account_token = AccountTokenClient(client_wrapper=self._client_wrapper)
+ return self._account_token
+
+ @property
+ def async_passthrough(self):
+ if self._async_passthrough is None:
+ from .resources.async_passthrough.client import (
+ AsyncPassthroughClient as resources_email_resources_async_passthrough_client_AsyncPassthroughClient, # noqa: E402
+ )
+
+ self._async_passthrough = resources_email_resources_async_passthrough_client_AsyncPassthroughClient(
+ client_wrapper=self._client_wrapper
+ )
+ return self._async_passthrough
+
+ @property
+ def audit_trail(self):
+ if self._audit_trail is None:
+ from .resources.audit_trail.client import AuditTrailClient # noqa: E402
+
+ self._audit_trail = AuditTrailClient(client_wrapper=self._client_wrapper)
+ return self._audit_trail
+
+ @property
+ def available_actions(self):
+ if self._available_actions is None:
+ from .resources.available_actions.client import AvailableActionsClient # noqa: E402
+
+ self._available_actions = AvailableActionsClient(client_wrapper=self._client_wrapper)
+ return self._available_actions
+
+ @property
+ def scopes(self):
+ if self._scopes is None:
+ from .resources.scopes.client import ScopesClient # noqa: E402
+
+ self._scopes = ScopesClient(client_wrapper=self._client_wrapper)
+ return self._scopes
+
+ @property
+ def delete_account(self):
+ if self._delete_account is None:
+ from .resources.delete_account.client import DeleteAccountClient # noqa: E402
+
+ self._delete_account = DeleteAccountClient(client_wrapper=self._client_wrapper)
+ return self._delete_account
+
+ @property
+ def email_addresses(self):
+ if self._email_addresses is None:
+ from .resources.email_addresses.client import EmailAddressesClient # noqa: E402
+
+ self._email_addresses = EmailAddressesClient(client_wrapper=self._client_wrapper)
+ return self._email_addresses
+
+ @property
+ def field_mapping(self):
+ if self._field_mapping is None:
+ from .resources.field_mapping.client import FieldMappingClient # noqa: E402
+
+ self._field_mapping = FieldMappingClient(client_wrapper=self._client_wrapper)
+ return self._field_mapping
+
+ @property
+ def folders(self):
+ if self._folders is None:
+ from .resources.folders.client import FoldersClient # noqa: E402
+
+ self._folders = FoldersClient(client_wrapper=self._client_wrapper)
+ return self._folders
+
+ @property
+ def generate_key(self):
+ if self._generate_key is None:
+ from .resources.generate_key.client import GenerateKeyClient # noqa: E402
+
+ self._generate_key = GenerateKeyClient(client_wrapper=self._client_wrapper)
+ return self._generate_key
+
+ @property
+ def groups(self):
+ if self._groups is None:
+ from .resources.groups.client import GroupsClient # noqa: E402
+
+ self._groups = GroupsClient(client_wrapper=self._client_wrapper)
+ return self._groups
+
+ @property
+ def issues(self):
+ if self._issues is None:
+ from .resources.issues.client import IssuesClient # noqa: E402
+
+ self._issues = IssuesClient(client_wrapper=self._client_wrapper)
+ return self._issues
+
+ @property
+ def link_token(self):
+ if self._link_token is None:
+ from .resources.link_token.client import LinkTokenClient # noqa: E402
+
+ self._link_token = LinkTokenClient(client_wrapper=self._client_wrapper)
+ return self._link_token
+
+ @property
+ def linked_accounts(self):
+ if self._linked_accounts is None:
+ from .resources.linked_accounts.client import LinkedAccountsClient # noqa: E402
+
+ self._linked_accounts = LinkedAccountsClient(client_wrapper=self._client_wrapper)
+ return self._linked_accounts
+
+ @property
+ def mailboxes(self):
+ if self._mailboxes is None:
+ from .resources.mailboxes.client import MailboxesClient # noqa: E402
+
+ self._mailboxes = MailboxesClient(client_wrapper=self._client_wrapper)
+ return self._mailboxes
+
+ @property
+ def messages(self):
+ if self._messages is None:
+ from .resources.messages.client import MessagesClient # noqa: E402
+
+ self._messages = MessagesClient(client_wrapper=self._client_wrapper)
+ return self._messages
+
+ @property
+ def passthrough(self):
+ if self._passthrough is None:
+ from .resources.passthrough.client import PassthroughClient # noqa: E402
+
+ self._passthrough = PassthroughClient(client_wrapper=self._client_wrapper)
+ return self._passthrough
+
+ @property
+ def regenerate_key(self):
+ if self._regenerate_key is None:
+ from .resources.regenerate_key.client import RegenerateKeyClient # noqa: E402
+
+ self._regenerate_key = RegenerateKeyClient(client_wrapper=self._client_wrapper)
+ return self._regenerate_key
+
+ @property
+ def sync_status(self):
+ if self._sync_status is None:
+ from .resources.sync_status.client import SyncStatusClient # noqa: E402
+
+ self._sync_status = SyncStatusClient(client_wrapper=self._client_wrapper)
+ return self._sync_status
+
+ @property
+ def force_resync(self):
+ if self._force_resync is None:
+ from .resources.force_resync.client import ForceResyncClient # noqa: E402
+
+ self._force_resync = ForceResyncClient(client_wrapper=self._client_wrapper)
+ return self._force_resync
+
+ @property
+ def users(self):
+ if self._users is None:
+ from .resources.users.client import UsersClient # noqa: E402
+
+ self._users = UsersClient(client_wrapper=self._client_wrapper)
+ return self._users
+
+ @property
+ def webhook_receivers(self):
+ if self._webhook_receivers is None:
+ from .resources.webhook_receivers.client import WebhookReceiversClient # noqa: E402
+
+ self._webhook_receivers = WebhookReceiversClient(client_wrapper=self._client_wrapper)
+ return self._webhook_receivers
+
+
+class AsyncEmailClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._raw_client = AsyncRawEmailClient(client_wrapper=client_wrapper)
+ self._client_wrapper = client_wrapper
+ self._account_details: typing.Optional[AsyncAccountDetailsClient] = None
+ self._account_token: typing.Optional[AsyncAccountTokenClient] = None
+ self._async_passthrough: typing.Optional[AsyncAsyncPassthroughClient] = None
+ self._audit_trail: typing.Optional[AsyncAuditTrailClient] = None
+ self._available_actions: typing.Optional[AsyncAvailableActionsClient] = None
+ self._scopes: typing.Optional[AsyncScopesClient] = None
+ self._delete_account: typing.Optional[AsyncDeleteAccountClient] = None
+ self._email_addresses: typing.Optional[AsyncEmailAddressesClient] = None
+ self._field_mapping: typing.Optional[AsyncFieldMappingClient] = None
+ self._folders: typing.Optional[AsyncFoldersClient] = None
+ self._generate_key: typing.Optional[AsyncGenerateKeyClient] = None
+ self._groups: typing.Optional[AsyncGroupsClient] = None
+ self._issues: typing.Optional[AsyncIssuesClient] = None
+ self._link_token: typing.Optional[AsyncLinkTokenClient] = None
+ self._linked_accounts: typing.Optional[AsyncLinkedAccountsClient] = None
+ self._mailboxes: typing.Optional[AsyncMailboxesClient] = None
+ self._messages: typing.Optional[AsyncMessagesClient] = None
+ self._passthrough: typing.Optional[resources_email_resources_passthrough_client_AsyncPassthroughClient] = None
+ self._regenerate_key: typing.Optional[AsyncRegenerateKeyClient] = None
+ self._sync_status: typing.Optional[AsyncSyncStatusClient] = None
+ self._force_resync: typing.Optional[AsyncForceResyncClient] = None
+ self._users: typing.Optional[AsyncUsersClient] = None
+ self._webhook_receivers: typing.Optional[AsyncWebhookReceiversClient] = None
+
+ @property
+ def with_raw_response(self) -> AsyncRawEmailClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ AsyncRawEmailClient
+ """
+ return self._raw_client
+
+ @property
+ def account_details(self):
+ if self._account_details is None:
+ from .resources.account_details.client import AsyncAccountDetailsClient # noqa: E402
+
+ self._account_details = AsyncAccountDetailsClient(client_wrapper=self._client_wrapper)
+ return self._account_details
+
+ @property
+ def account_token(self):
+ if self._account_token is None:
+ from .resources.account_token.client import AsyncAccountTokenClient # noqa: E402
+
+ self._account_token = AsyncAccountTokenClient(client_wrapper=self._client_wrapper)
+ return self._account_token
+
+ @property
+ def async_passthrough(self):
+ if self._async_passthrough is None:
+ from .resources.async_passthrough.client import AsyncAsyncPassthroughClient # noqa: E402
+
+ self._async_passthrough = AsyncAsyncPassthroughClient(client_wrapper=self._client_wrapper)
+ return self._async_passthrough
+
+ @property
+ def audit_trail(self):
+ if self._audit_trail is None:
+ from .resources.audit_trail.client import AsyncAuditTrailClient # noqa: E402
+
+ self._audit_trail = AsyncAuditTrailClient(client_wrapper=self._client_wrapper)
+ return self._audit_trail
+
+ @property
+ def available_actions(self):
+ if self._available_actions is None:
+ from .resources.available_actions.client import AsyncAvailableActionsClient # noqa: E402
+
+ self._available_actions = AsyncAvailableActionsClient(client_wrapper=self._client_wrapper)
+ return self._available_actions
+
+ @property
+ def scopes(self):
+ if self._scopes is None:
+ from .resources.scopes.client import AsyncScopesClient # noqa: E402
+
+ self._scopes = AsyncScopesClient(client_wrapper=self._client_wrapper)
+ return self._scopes
+
+ @property
+ def delete_account(self):
+ if self._delete_account is None:
+ from .resources.delete_account.client import AsyncDeleteAccountClient # noqa: E402
+
+ self._delete_account = AsyncDeleteAccountClient(client_wrapper=self._client_wrapper)
+ return self._delete_account
+
+ @property
+ def email_addresses(self):
+ if self._email_addresses is None:
+ from .resources.email_addresses.client import AsyncEmailAddressesClient # noqa: E402
+
+ self._email_addresses = AsyncEmailAddressesClient(client_wrapper=self._client_wrapper)
+ return self._email_addresses
+
+ @property
+ def field_mapping(self):
+ if self._field_mapping is None:
+ from .resources.field_mapping.client import AsyncFieldMappingClient # noqa: E402
+
+ self._field_mapping = AsyncFieldMappingClient(client_wrapper=self._client_wrapper)
+ return self._field_mapping
+
+ @property
+ def folders(self):
+ if self._folders is None:
+ from .resources.folders.client import AsyncFoldersClient # noqa: E402
+
+ self._folders = AsyncFoldersClient(client_wrapper=self._client_wrapper)
+ return self._folders
+
+ @property
+ def generate_key(self):
+ if self._generate_key is None:
+ from .resources.generate_key.client import AsyncGenerateKeyClient # noqa: E402
+
+ self._generate_key = AsyncGenerateKeyClient(client_wrapper=self._client_wrapper)
+ return self._generate_key
+
+ @property
+ def groups(self):
+ if self._groups is None:
+ from .resources.groups.client import AsyncGroupsClient # noqa: E402
+
+ self._groups = AsyncGroupsClient(client_wrapper=self._client_wrapper)
+ return self._groups
+
+ @property
+ def issues(self):
+ if self._issues is None:
+ from .resources.issues.client import AsyncIssuesClient # noqa: E402
+
+ self._issues = AsyncIssuesClient(client_wrapper=self._client_wrapper)
+ return self._issues
+
+ @property
+ def link_token(self):
+ if self._link_token is None:
+ from .resources.link_token.client import AsyncLinkTokenClient # noqa: E402
+
+ self._link_token = AsyncLinkTokenClient(client_wrapper=self._client_wrapper)
+ return self._link_token
+
+ @property
+ def linked_accounts(self):
+ if self._linked_accounts is None:
+ from .resources.linked_accounts.client import AsyncLinkedAccountsClient # noqa: E402
+
+ self._linked_accounts = AsyncLinkedAccountsClient(client_wrapper=self._client_wrapper)
+ return self._linked_accounts
+
+ @property
+ def mailboxes(self):
+ if self._mailboxes is None:
+ from .resources.mailboxes.client import AsyncMailboxesClient # noqa: E402
+
+ self._mailboxes = AsyncMailboxesClient(client_wrapper=self._client_wrapper)
+ return self._mailboxes
+
+ @property
+ def messages(self):
+ if self._messages is None:
+ from .resources.messages.client import AsyncMessagesClient # noqa: E402
+
+ self._messages = AsyncMessagesClient(client_wrapper=self._client_wrapper)
+ return self._messages
+
+ @property
+ def passthrough(self):
+ if self._passthrough is None:
+ from .resources.passthrough.client import (
+ AsyncPassthroughClient as resources_email_resources_passthrough_client_AsyncPassthroughClient, # noqa: E402
+ )
+
+ self._passthrough = resources_email_resources_passthrough_client_AsyncPassthroughClient(
+ client_wrapper=self._client_wrapper
+ )
+ return self._passthrough
+
+ @property
+ def regenerate_key(self):
+ if self._regenerate_key is None:
+ from .resources.regenerate_key.client import AsyncRegenerateKeyClient # noqa: E402
+
+ self._regenerate_key = AsyncRegenerateKeyClient(client_wrapper=self._client_wrapper)
+ return self._regenerate_key
+
+ @property
+ def sync_status(self):
+ if self._sync_status is None:
+ from .resources.sync_status.client import AsyncSyncStatusClient # noqa: E402
+
+ self._sync_status = AsyncSyncStatusClient(client_wrapper=self._client_wrapper)
+ return self._sync_status
+
+ @property
+ def force_resync(self):
+ if self._force_resync is None:
+ from .resources.force_resync.client import AsyncForceResyncClient # noqa: E402
+
+ self._force_resync = AsyncForceResyncClient(client_wrapper=self._client_wrapper)
+ return self._force_resync
+
+ @property
+ def users(self):
+ if self._users is None:
+ from .resources.users.client import AsyncUsersClient # noqa: E402
+
+ self._users = AsyncUsersClient(client_wrapper=self._client_wrapper)
+ return self._users
+
+ @property
+ def webhook_receivers(self):
+ if self._webhook_receivers is None:
+ from .resources.webhook_receivers.client import AsyncWebhookReceiversClient # noqa: E402
+
+ self._webhook_receivers = AsyncWebhookReceiversClient(client_wrapper=self._client_wrapper)
+ return self._webhook_receivers
diff --git a/src/merge/resources/email/raw_client.py b/src/merge/resources/email/raw_client.py
new file mode 100644
index 00000000..49364023
--- /dev/null
+++ b/src/merge/resources/email/raw_client.py
@@ -0,0 +1,13 @@
+# This file was auto-generated by Fern from our API Definition.
+
+from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+
+
+class RawEmailClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+
+class AsyncRawEmailClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._client_wrapper = client_wrapper
diff --git a/src/merge/resources/email/resources/__init__.py b/src/merge/resources/email/resources/__init__.py
new file mode 100644
index 00000000..37ecb5e6
--- /dev/null
+++ b/src/merge/resources/email/resources/__init__.py
@@ -0,0 +1,148 @@
+# This file was auto-generated by Fern from our API Definition.
+
+# isort: skip_file
+
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from . import (
+ account_details,
+ account_token,
+ async_passthrough,
+ audit_trail,
+ available_actions,
+ delete_account,
+ email_addresses,
+ field_mapping,
+ folders,
+ force_resync,
+ generate_key,
+ groups,
+ issues,
+ link_token,
+ linked_accounts,
+ mailboxes,
+ messages,
+ passthrough,
+ regenerate_key,
+ scopes,
+ sync_status,
+ users,
+ webhook_receivers,
+ )
+ from .async_passthrough import AsyncPassthroughRetrieveResponse
+ from .email_addresses import EmailAddressesListRequestExpandItem, EmailAddressesRetrieveRequestExpandItem
+ from .folders import FoldersListRequestExpandItem, FoldersRetrieveRequestExpandItem
+ from .groups import GroupsListRequestExpandItem, GroupsRetrieveRequestExpandItem
+ from .issues import IssuesListRequestStatus
+ from .link_token import EndUserDetailsRequestCompletedAccountInitialScreen, EndUserDetailsRequestLanguage
+ from .linked_accounts import LinkedAccountsListRequestCategory
+ from .mailboxes import MailboxesListRequestExpandItem, MailboxesRetrieveRequestExpandItem
+ from .messages import MessagesListRequestExpandItem, MessagesRetrieveRequestExpandItem
+ from .users import UsersListRequestExpandItem, UsersRetrieveRequestExpandItem
+_dynamic_imports: typing.Dict[str, str] = {
+ "AsyncPassthroughRetrieveResponse": ".async_passthrough",
+ "EmailAddressesListRequestExpandItem": ".email_addresses",
+ "EmailAddressesRetrieveRequestExpandItem": ".email_addresses",
+ "EndUserDetailsRequestCompletedAccountInitialScreen": ".link_token",
+ "EndUserDetailsRequestLanguage": ".link_token",
+ "FoldersListRequestExpandItem": ".folders",
+ "FoldersRetrieveRequestExpandItem": ".folders",
+ "GroupsListRequestExpandItem": ".groups",
+ "GroupsRetrieveRequestExpandItem": ".groups",
+ "IssuesListRequestStatus": ".issues",
+ "LinkedAccountsListRequestCategory": ".linked_accounts",
+ "MailboxesListRequestExpandItem": ".mailboxes",
+ "MailboxesRetrieveRequestExpandItem": ".mailboxes",
+ "MessagesListRequestExpandItem": ".messages",
+ "MessagesRetrieveRequestExpandItem": ".messages",
+ "UsersListRequestExpandItem": ".users",
+ "UsersRetrieveRequestExpandItem": ".users",
+ "account_details": ".",
+ "account_token": ".",
+ "async_passthrough": ".",
+ "audit_trail": ".",
+ "available_actions": ".",
+ "delete_account": ".",
+ "email_addresses": ".",
+ "field_mapping": ".",
+ "folders": ".",
+ "force_resync": ".",
+ "generate_key": ".",
+ "groups": ".",
+ "issues": ".",
+ "link_token": ".",
+ "linked_accounts": ".",
+ "mailboxes": ".",
+ "messages": ".",
+ "passthrough": ".",
+ "regenerate_key": ".",
+ "scopes": ".",
+ "sync_status": ".",
+ "users": ".",
+ "webhook_receivers": ".",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ result = getattr(module, attr_name)
+ return result
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
+
+__all__ = [
+ "AsyncPassthroughRetrieveResponse",
+ "EmailAddressesListRequestExpandItem",
+ "EmailAddressesRetrieveRequestExpandItem",
+ "EndUserDetailsRequestCompletedAccountInitialScreen",
+ "EndUserDetailsRequestLanguage",
+ "FoldersListRequestExpandItem",
+ "FoldersRetrieveRequestExpandItem",
+ "GroupsListRequestExpandItem",
+ "GroupsRetrieveRequestExpandItem",
+ "IssuesListRequestStatus",
+ "LinkedAccountsListRequestCategory",
+ "MailboxesListRequestExpandItem",
+ "MailboxesRetrieveRequestExpandItem",
+ "MessagesListRequestExpandItem",
+ "MessagesRetrieveRequestExpandItem",
+ "UsersListRequestExpandItem",
+ "UsersRetrieveRequestExpandItem",
+ "account_details",
+ "account_token",
+ "async_passthrough",
+ "audit_trail",
+ "available_actions",
+ "delete_account",
+ "email_addresses",
+ "field_mapping",
+ "folders",
+ "force_resync",
+ "generate_key",
+ "groups",
+ "issues",
+ "link_token",
+ "linked_accounts",
+ "mailboxes",
+ "messages",
+ "passthrough",
+ "regenerate_key",
+ "scopes",
+ "sync_status",
+ "users",
+ "webhook_receivers",
+]
diff --git a/src/merge/resources/email/resources/account_details/__init__.py b/src/merge/resources/email/resources/account_details/__init__.py
new file mode 100644
index 00000000..5cde0202
--- /dev/null
+++ b/src/merge/resources/email/resources/account_details/__init__.py
@@ -0,0 +1,4 @@
+# This file was auto-generated by Fern from our API Definition.
+
+# isort: skip_file
+
diff --git a/src/merge/resources/email/resources/account_details/client.py b/src/merge/resources/email/resources/account_details/client.py
new file mode 100644
index 00000000..827c6251
--- /dev/null
+++ b/src/merge/resources/email/resources/account_details/client.py
@@ -0,0 +1,102 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .....core.request_options import RequestOptions
+from ...types.account_details import AccountDetails
+from .raw_client import AsyncRawAccountDetailsClient, RawAccountDetailsClient
+
+
+class AccountDetailsClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._raw_client = RawAccountDetailsClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> RawAccountDetailsClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ RawAccountDetailsClient
+ """
+ return self._raw_client
+
+ def retrieve(self, *, request_options: typing.Optional[RequestOptions] = None) -> AccountDetails:
+ """
+ Get details for a linked account.
+
+ Parameters
+ ----------
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AccountDetails
+
+
+ Examples
+ --------
+ from merge import Merge
+
+ client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+ client.email.account_details.retrieve()
+ """
+ _response = self._raw_client.retrieve(request_options=request_options)
+ return _response.data
+
+
+class AsyncAccountDetailsClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._raw_client = AsyncRawAccountDetailsClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> AsyncRawAccountDetailsClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ AsyncRawAccountDetailsClient
+ """
+ return self._raw_client
+
+ async def retrieve(self, *, request_options: typing.Optional[RequestOptions] = None) -> AccountDetails:
+ """
+ Get details for a linked account.
+
+ Parameters
+ ----------
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AccountDetails
+
+
+ Examples
+ --------
+ import asyncio
+
+ from merge import AsyncMerge
+
+ client = AsyncMerge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.email.account_details.retrieve()
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.retrieve(request_options=request_options)
+ return _response.data
diff --git a/src/merge/resources/email/resources/account_details/raw_client.py b/src/merge/resources/email/resources/account_details/raw_client.py
new file mode 100644
index 00000000..9918bc2a
--- /dev/null
+++ b/src/merge/resources/email/resources/account_details/raw_client.py
@@ -0,0 +1,91 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+from json.decoder import JSONDecodeError
+
+from .....core.api_error import ApiError
+from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .....core.http_response import AsyncHttpResponse, HttpResponse
+from .....core.request_options import RequestOptions
+from .....core.unchecked_base_model import construct_type
+from ...types.account_details import AccountDetails
+
+
+class RawAccountDetailsClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ def retrieve(self, *, request_options: typing.Optional[RequestOptions] = None) -> HttpResponse[AccountDetails]:
+ """
+ Get details for a linked account.
+
+ Parameters
+ ----------
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[AccountDetails]
+
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ "email/v1/account-details",
+ method="GET",
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ AccountDetails,
+ construct_type(
+ type_=AccountDetails, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+
+class AsyncRawAccountDetailsClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ async def retrieve(
+ self, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> AsyncHttpResponse[AccountDetails]:
+ """
+ Get details for a linked account.
+
+ Parameters
+ ----------
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[AccountDetails]
+
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ "email/v1/account-details",
+ method="GET",
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ AccountDetails,
+ construct_type(
+ type_=AccountDetails, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
diff --git a/src/merge/resources/email/resources/account_token/__init__.py b/src/merge/resources/email/resources/account_token/__init__.py
new file mode 100644
index 00000000..5cde0202
--- /dev/null
+++ b/src/merge/resources/email/resources/account_token/__init__.py
@@ -0,0 +1,4 @@
+# This file was auto-generated by Fern from our API Definition.
+
+# isort: skip_file
+
diff --git a/src/merge/resources/email/resources/account_token/client.py b/src/merge/resources/email/resources/account_token/client.py
new file mode 100644
index 00000000..08869cab
--- /dev/null
+++ b/src/merge/resources/email/resources/account_token/client.py
@@ -0,0 +1,177 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .....core.request_options import RequestOptions
+from ...types.account_token import AccountToken
+from ...types.regenerate_account_token import RegenerateAccountToken
+from .raw_client import AsyncRawAccountTokenClient, RawAccountTokenClient
+
+
+class AccountTokenClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._raw_client = RawAccountTokenClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> RawAccountTokenClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ RawAccountTokenClient
+ """
+ return self._raw_client
+
+ def retrieve(self, public_token: str, *, request_options: typing.Optional[RequestOptions] = None) -> AccountToken:
+ """
+ Returns the account token for the end user with the provided public token.
+
+ Parameters
+ ----------
+ public_token : str
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AccountToken
+
+
+ Examples
+ --------
+ from merge import Merge
+
+ client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+ client.email.account_token.retrieve(
+ public_token="public_token",
+ )
+ """
+ _response = self._raw_client.retrieve(public_token, request_options=request_options)
+ return _response.data
+
+ def regenerate_create(self, *, request_options: typing.Optional[RequestOptions] = None) -> RegenerateAccountToken:
+ """
+ Exchange Linked Account account tokens.
+
+ Parameters
+ ----------
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ RegenerateAccountToken
+
+
+ Examples
+ --------
+ from merge import Merge
+
+ client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+ client.email.account_token.regenerate_create()
+ """
+ _response = self._raw_client.regenerate_create(request_options=request_options)
+ return _response.data
+
+
+class AsyncAccountTokenClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._raw_client = AsyncRawAccountTokenClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> AsyncRawAccountTokenClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ AsyncRawAccountTokenClient
+ """
+ return self._raw_client
+
+ async def retrieve(
+ self, public_token: str, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> AccountToken:
+ """
+ Returns the account token for the end user with the provided public token.
+
+ Parameters
+ ----------
+ public_token : str
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AccountToken
+
+
+ Examples
+ --------
+ import asyncio
+
+ from merge import AsyncMerge
+
+ client = AsyncMerge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.email.account_token.retrieve(
+ public_token="public_token",
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.retrieve(public_token, request_options=request_options)
+ return _response.data
+
+ async def regenerate_create(
+ self, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> RegenerateAccountToken:
+ """
+ Exchange Linked Account account tokens.
+
+ Parameters
+ ----------
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ RegenerateAccountToken
+
+
+ Examples
+ --------
+ import asyncio
+
+ from merge import AsyncMerge
+
+ client = AsyncMerge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.email.account_token.regenerate_create()
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.regenerate_create(request_options=request_options)
+ return _response.data
diff --git a/src/merge/resources/email/resources/account_token/raw_client.py b/src/merge/resources/email/resources/account_token/raw_client.py
new file mode 100644
index 00000000..7370a253
--- /dev/null
+++ b/src/merge/resources/email/resources/account_token/raw_client.py
@@ -0,0 +1,171 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+from json.decoder import JSONDecodeError
+
+from .....core.api_error import ApiError
+from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .....core.http_response import AsyncHttpResponse, HttpResponse
+from .....core.jsonable_encoder import jsonable_encoder
+from .....core.request_options import RequestOptions
+from .....core.unchecked_base_model import construct_type
+from ...types.account_token import AccountToken
+from ...types.regenerate_account_token import RegenerateAccountToken
+
+
+class RawAccountTokenClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ def retrieve(
+ self, public_token: str, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> HttpResponse[AccountToken]:
+ """
+ Returns the account token for the end user with the provided public token.
+
+ Parameters
+ ----------
+ public_token : str
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[AccountToken]
+
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ f"email/v1/account-token/{jsonable_encoder(public_token)}",
+ method="GET",
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ AccountToken,
+ construct_type(
+ type_=AccountToken, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ def regenerate_create(
+ self, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> HttpResponse[RegenerateAccountToken]:
+ """
+ Exchange Linked Account account tokens.
+
+ Parameters
+ ----------
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[RegenerateAccountToken]
+
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ "email/v1/account-token/regenerate",
+ method="POST",
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ RegenerateAccountToken,
+ construct_type(
+ type_=RegenerateAccountToken, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+
+class AsyncRawAccountTokenClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ async def retrieve(
+ self, public_token: str, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> AsyncHttpResponse[AccountToken]:
+ """
+ Returns the account token for the end user with the provided public token.
+
+ Parameters
+ ----------
+ public_token : str
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[AccountToken]
+
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ f"email/v1/account-token/{jsonable_encoder(public_token)}",
+ method="GET",
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ AccountToken,
+ construct_type(
+ type_=AccountToken, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ async def regenerate_create(
+ self, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> AsyncHttpResponse[RegenerateAccountToken]:
+ """
+ Exchange Linked Account account tokens.
+
+ Parameters
+ ----------
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[RegenerateAccountToken]
+
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ "email/v1/account-token/regenerate",
+ method="POST",
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ RegenerateAccountToken,
+ construct_type(
+ type_=RegenerateAccountToken, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
diff --git a/src/merge/resources/email/resources/async_passthrough/__init__.py b/src/merge/resources/email/resources/async_passthrough/__init__.py
new file mode 100644
index 00000000..375c7953
--- /dev/null
+++ b/src/merge/resources/email/resources/async_passthrough/__init__.py
@@ -0,0 +1,32 @@
+# This file was auto-generated by Fern from our API Definition.
+
+# isort: skip_file
+
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .types import AsyncPassthroughRetrieveResponse
+_dynamic_imports: typing.Dict[str, str] = {"AsyncPassthroughRetrieveResponse": ".types"}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ result = getattr(module, attr_name)
+ return result
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
+
+__all__ = ["AsyncPassthroughRetrieveResponse"]
diff --git a/src/merge/resources/email/resources/async_passthrough/client.py b/src/merge/resources/email/resources/async_passthrough/client.py
new file mode 100644
index 00000000..161c0054
--- /dev/null
+++ b/src/merge/resources/email/resources/async_passthrough/client.py
@@ -0,0 +1,201 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .....core.request_options import RequestOptions
+from ...types.async_passthrough_reciept import AsyncPassthroughReciept
+from ...types.data_passthrough_request import DataPassthroughRequest
+from .raw_client import AsyncRawAsyncPassthroughClient, RawAsyncPassthroughClient
+from .types.async_passthrough_retrieve_response import AsyncPassthroughRetrieveResponse
+
+# this is used as the default value for optional parameters
+OMIT = typing.cast(typing.Any, ...)
+
+
+class AsyncPassthroughClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._raw_client = RawAsyncPassthroughClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> RawAsyncPassthroughClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ RawAsyncPassthroughClient
+ """
+ return self._raw_client
+
+ def create(
+ self, *, request: DataPassthroughRequest, request_options: typing.Optional[RequestOptions] = None
+ ) -> AsyncPassthroughReciept:
+ """
+ Asynchronously pull data from an endpoint not currently supported by Merge.
+
+ Parameters
+ ----------
+ request : DataPassthroughRequest
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncPassthroughReciept
+
+
+ Examples
+ --------
+ from merge import Merge
+ from merge.resources.email import DataPassthroughRequest, MethodEnum
+
+ client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+ client.email.async_passthrough.create(
+ request=DataPassthroughRequest(
+ method=MethodEnum.GET,
+ path="/scooters",
+ ),
+ )
+ """
+ _response = self._raw_client.create(request=request, request_options=request_options)
+ return _response.data
+
+ def retrieve(
+ self, async_passthrough_receipt_id: str, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> AsyncPassthroughRetrieveResponse:
+ """
+ Retrieves data from earlier async-passthrough POST request
+
+ Parameters
+ ----------
+ async_passthrough_receipt_id : str
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncPassthroughRetrieveResponse
+
+
+ Examples
+ --------
+ from merge import Merge
+
+ client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+ client.email.async_passthrough.retrieve(
+ async_passthrough_receipt_id="async_passthrough_receipt_id",
+ )
+ """
+ _response = self._raw_client.retrieve(async_passthrough_receipt_id, request_options=request_options)
+ return _response.data
+
+
+class AsyncAsyncPassthroughClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._raw_client = AsyncRawAsyncPassthroughClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> AsyncRawAsyncPassthroughClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ AsyncRawAsyncPassthroughClient
+ """
+ return self._raw_client
+
+ async def create(
+ self, *, request: DataPassthroughRequest, request_options: typing.Optional[RequestOptions] = None
+ ) -> AsyncPassthroughReciept:
+ """
+ Asynchronously pull data from an endpoint not currently supported by Merge.
+
+ Parameters
+ ----------
+ request : DataPassthroughRequest
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncPassthroughReciept
+
+
+ Examples
+ --------
+ import asyncio
+
+ from merge import AsyncMerge
+ from merge.resources.email import DataPassthroughRequest, MethodEnum
+
+ client = AsyncMerge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.email.async_passthrough.create(
+ request=DataPassthroughRequest(
+ method=MethodEnum.GET,
+ path="/scooters",
+ ),
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.create(request=request, request_options=request_options)
+ return _response.data
+
+ async def retrieve(
+ self, async_passthrough_receipt_id: str, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> AsyncPassthroughRetrieveResponse:
+ """
+ Retrieves data from earlier async-passthrough POST request
+
+ Parameters
+ ----------
+ async_passthrough_receipt_id : str
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncPassthroughRetrieveResponse
+
+
+ Examples
+ --------
+ import asyncio
+
+ from merge import AsyncMerge
+
+ client = AsyncMerge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.email.async_passthrough.retrieve(
+ async_passthrough_receipt_id="async_passthrough_receipt_id",
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.retrieve(async_passthrough_receipt_id, request_options=request_options)
+ return _response.data
diff --git a/src/merge/resources/email/resources/async_passthrough/raw_client.py b/src/merge/resources/email/resources/async_passthrough/raw_client.py
new file mode 100644
index 00000000..7787eb3c
--- /dev/null
+++ b/src/merge/resources/email/resources/async_passthrough/raw_client.py
@@ -0,0 +1,189 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+from json.decoder import JSONDecodeError
+
+from .....core.api_error import ApiError
+from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .....core.http_response import AsyncHttpResponse, HttpResponse
+from .....core.jsonable_encoder import jsonable_encoder
+from .....core.request_options import RequestOptions
+from .....core.unchecked_base_model import construct_type
+from ...types.async_passthrough_reciept import AsyncPassthroughReciept
+from ...types.data_passthrough_request import DataPassthroughRequest
+from .types.async_passthrough_retrieve_response import AsyncPassthroughRetrieveResponse
+
+# this is used as the default value for optional parameters
+OMIT = typing.cast(typing.Any, ...)
+
+
+class RawAsyncPassthroughClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ def create(
+ self, *, request: DataPassthroughRequest, request_options: typing.Optional[RequestOptions] = None
+ ) -> HttpResponse[AsyncPassthroughReciept]:
+ """
+ Asynchronously pull data from an endpoint not currently supported by Merge.
+
+ Parameters
+ ----------
+ request : DataPassthroughRequest
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[AsyncPassthroughReciept]
+
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ "email/v1/async-passthrough",
+ method="POST",
+ json=request,
+ headers={
+ "content-type": "application/json",
+ },
+ request_options=request_options,
+ omit=OMIT,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ AsyncPassthroughReciept,
+ construct_type(
+ type_=AsyncPassthroughReciept, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ def retrieve(
+ self, async_passthrough_receipt_id: str, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> HttpResponse[AsyncPassthroughRetrieveResponse]:
+ """
+ Retrieves data from earlier async-passthrough POST request
+
+ Parameters
+ ----------
+ async_passthrough_receipt_id : str
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[AsyncPassthroughRetrieveResponse]
+
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ f"email/v1/async-passthrough/{jsonable_encoder(async_passthrough_receipt_id)}",
+ method="GET",
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ AsyncPassthroughRetrieveResponse,
+ construct_type(
+ type_=AsyncPassthroughRetrieveResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+
+class AsyncRawAsyncPassthroughClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ async def create(
+ self, *, request: DataPassthroughRequest, request_options: typing.Optional[RequestOptions] = None
+ ) -> AsyncHttpResponse[AsyncPassthroughReciept]:
+ """
+ Asynchronously pull data from an endpoint not currently supported by Merge.
+
+ Parameters
+ ----------
+ request : DataPassthroughRequest
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[AsyncPassthroughReciept]
+
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ "email/v1/async-passthrough",
+ method="POST",
+ json=request,
+ headers={
+ "content-type": "application/json",
+ },
+ request_options=request_options,
+ omit=OMIT,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ AsyncPassthroughReciept,
+ construct_type(
+ type_=AsyncPassthroughReciept, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ async def retrieve(
+ self, async_passthrough_receipt_id: str, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> AsyncHttpResponse[AsyncPassthroughRetrieveResponse]:
+ """
+ Retrieves data from earlier async-passthrough POST request
+
+ Parameters
+ ----------
+ async_passthrough_receipt_id : str
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[AsyncPassthroughRetrieveResponse]
+
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ f"email/v1/async-passthrough/{jsonable_encoder(async_passthrough_receipt_id)}",
+ method="GET",
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ AsyncPassthroughRetrieveResponse,
+ construct_type(
+ type_=AsyncPassthroughRetrieveResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
diff --git a/src/merge/resources/email/resources/async_passthrough/types/__init__.py b/src/merge/resources/email/resources/async_passthrough/types/__init__.py
new file mode 100644
index 00000000..f6e9bec9
--- /dev/null
+++ b/src/merge/resources/email/resources/async_passthrough/types/__init__.py
@@ -0,0 +1,32 @@
+# This file was auto-generated by Fern from our API Definition.
+
+# isort: skip_file
+
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .async_passthrough_retrieve_response import AsyncPassthroughRetrieveResponse
+_dynamic_imports: typing.Dict[str, str] = {"AsyncPassthroughRetrieveResponse": ".async_passthrough_retrieve_response"}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ result = getattr(module, attr_name)
+ return result
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
+
+__all__ = ["AsyncPassthroughRetrieveResponse"]
diff --git a/src/merge/resources/email/resources/async_passthrough/types/async_passthrough_retrieve_response.py b/src/merge/resources/email/resources/async_passthrough/types/async_passthrough_retrieve_response.py
new file mode 100644
index 00000000..f8f87c18
--- /dev/null
+++ b/src/merge/resources/email/resources/async_passthrough/types/async_passthrough_retrieve_response.py
@@ -0,0 +1,7 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+from ....types.remote_response import RemoteResponse
+
+AsyncPassthroughRetrieveResponse = typing.Union[RemoteResponse, str]
diff --git a/src/merge/resources/email/resources/audit_trail/__init__.py b/src/merge/resources/email/resources/audit_trail/__init__.py
new file mode 100644
index 00000000..5cde0202
--- /dev/null
+++ b/src/merge/resources/email/resources/audit_trail/__init__.py
@@ -0,0 +1,4 @@
+# This file was auto-generated by Fern from our API Definition.
+
+# isort: skip_file
+
diff --git a/src/merge/resources/email/resources/audit_trail/client.py b/src/merge/resources/email/resources/audit_trail/client.py
new file mode 100644
index 00000000..512d0b5c
--- /dev/null
+++ b/src/merge/resources/email/resources/audit_trail/client.py
@@ -0,0 +1,188 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .....core.request_options import RequestOptions
+from ...types.paginated_audit_log_event_list import PaginatedAuditLogEventList
+from .raw_client import AsyncRawAuditTrailClient, RawAuditTrailClient
+
+
+class AuditTrailClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._raw_client = RawAuditTrailClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> RawAuditTrailClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ RawAuditTrailClient
+ """
+ return self._raw_client
+
+ def list(
+ self,
+ *,
+ cursor: typing.Optional[str] = None,
+ end_date: typing.Optional[str] = None,
+ event_type: typing.Optional[str] = None,
+ page_size: typing.Optional[int] = None,
+ start_date: typing.Optional[str] = None,
+ user_email: typing.Optional[str] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> PaginatedAuditLogEventList:
+ """
+ Gets a list of audit trail events.
+
+ Parameters
+ ----------
+ cursor : typing.Optional[str]
+ The pagination cursor value.
+
+ end_date : typing.Optional[str]
+ If included, will only include audit trail events that occurred before this time
+
+ event_type : typing.Optional[str]
+ If included, will only include events with the given event type. Possible values include: `CREATED_REMOTE_PRODUCTION_API_KEY`, `DELETED_REMOTE_PRODUCTION_API_KEY`, `CREATED_TEST_API_KEY`, `DELETED_TEST_API_KEY`, `REGENERATED_PRODUCTION_API_KEY`, `REGENERATED_WEBHOOK_SIGNATURE`, `INVITED_USER`, `TWO_FACTOR_AUTH_ENABLED`, `TWO_FACTOR_AUTH_DISABLED`, `DELETED_LINKED_ACCOUNT`, `DELETED_ALL_COMMON_MODELS_FOR_LINKED_ACCOUNT`, `CREATED_DESTINATION`, `DELETED_DESTINATION`, `CHANGED_DESTINATION`, `CHANGED_SCOPES`, `CHANGED_PERSONAL_INFORMATION`, `CHANGED_ORGANIZATION_SETTINGS`, `ENABLED_INTEGRATION`, `DISABLED_INTEGRATION`, `ENABLED_CATEGORY`, `DISABLED_CATEGORY`, `CHANGED_PASSWORD`, `RESET_PASSWORD`, `ENABLED_REDACT_UNMAPPED_DATA_FOR_ORGANIZATION`, `ENABLED_REDACT_UNMAPPED_DATA_FOR_LINKED_ACCOUNT`, `DISABLED_REDACT_UNMAPPED_DATA_FOR_ORGANIZATION`, `DISABLED_REDACT_UNMAPPED_DATA_FOR_LINKED_ACCOUNT`, `CREATED_INTEGRATION_WIDE_FIELD_MAPPING`, `CREATED_LINKED_ACCOUNT_FIELD_MAPPING`, `CHANGED_INTEGRATION_WIDE_FIELD_MAPPING`, `CHANGED_LINKED_ACCOUNT_FIELD_MAPPING`, `DELETED_INTEGRATION_WIDE_FIELD_MAPPING`, `DELETED_LINKED_ACCOUNT_FIELD_MAPPING`, `CREATED_LINKED_ACCOUNT_COMMON_MODEL_OVERRIDE`, `CHANGED_LINKED_ACCOUNT_COMMON_MODEL_OVERRIDE`, `DELETED_LINKED_ACCOUNT_COMMON_MODEL_OVERRIDE`, `FORCED_LINKED_ACCOUNT_RESYNC`, `MUTED_ISSUE`, `GENERATED_MAGIC_LINK`, `ENABLED_MERGE_WEBHOOK`, `DISABLED_MERGE_WEBHOOK`, `MERGE_WEBHOOK_TARGET_CHANGED`, `END_USER_CREDENTIALS_ACCESSED`
+
+ page_size : typing.Optional[int]
+ Number of results to return per page. The maximum limit is 100.
+
+ start_date : typing.Optional[str]
+ If included, will only include audit trail events that occurred after this time
+
+ user_email : typing.Optional[str]
+ If provided, this will return events associated with the specified user email. Please note that the email address reflects the user's email at the time of the event, and may not be their current email.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ PaginatedAuditLogEventList
+
+
+ Examples
+ --------
+ from merge import Merge
+
+ client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+ client.email.audit_trail.list(
+ cursor="cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw",
+ end_date="end_date",
+ event_type="event_type",
+ page_size=1,
+ start_date="start_date",
+ user_email="user_email",
+ )
+ """
+ _response = self._raw_client.list(
+ cursor=cursor,
+ end_date=end_date,
+ event_type=event_type,
+ page_size=page_size,
+ start_date=start_date,
+ user_email=user_email,
+ request_options=request_options,
+ )
+ return _response.data
+
+
+class AsyncAuditTrailClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._raw_client = AsyncRawAuditTrailClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> AsyncRawAuditTrailClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ AsyncRawAuditTrailClient
+ """
+ return self._raw_client
+
+ async def list(
+ self,
+ *,
+ cursor: typing.Optional[str] = None,
+ end_date: typing.Optional[str] = None,
+ event_type: typing.Optional[str] = None,
+ page_size: typing.Optional[int] = None,
+ start_date: typing.Optional[str] = None,
+ user_email: typing.Optional[str] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> PaginatedAuditLogEventList:
+ """
+ Gets a list of audit trail events.
+
+ Parameters
+ ----------
+ cursor : typing.Optional[str]
+ The pagination cursor value.
+
+ end_date : typing.Optional[str]
+ If included, will only include audit trail events that occurred before this time
+
+ event_type : typing.Optional[str]
+ If included, will only include events with the given event type. Possible values include: `CREATED_REMOTE_PRODUCTION_API_KEY`, `DELETED_REMOTE_PRODUCTION_API_KEY`, `CREATED_TEST_API_KEY`, `DELETED_TEST_API_KEY`, `REGENERATED_PRODUCTION_API_KEY`, `REGENERATED_WEBHOOK_SIGNATURE`, `INVITED_USER`, `TWO_FACTOR_AUTH_ENABLED`, `TWO_FACTOR_AUTH_DISABLED`, `DELETED_LINKED_ACCOUNT`, `DELETED_ALL_COMMON_MODELS_FOR_LINKED_ACCOUNT`, `CREATED_DESTINATION`, `DELETED_DESTINATION`, `CHANGED_DESTINATION`, `CHANGED_SCOPES`, `CHANGED_PERSONAL_INFORMATION`, `CHANGED_ORGANIZATION_SETTINGS`, `ENABLED_INTEGRATION`, `DISABLED_INTEGRATION`, `ENABLED_CATEGORY`, `DISABLED_CATEGORY`, `CHANGED_PASSWORD`, `RESET_PASSWORD`, `ENABLED_REDACT_UNMAPPED_DATA_FOR_ORGANIZATION`, `ENABLED_REDACT_UNMAPPED_DATA_FOR_LINKED_ACCOUNT`, `DISABLED_REDACT_UNMAPPED_DATA_FOR_ORGANIZATION`, `DISABLED_REDACT_UNMAPPED_DATA_FOR_LINKED_ACCOUNT`, `CREATED_INTEGRATION_WIDE_FIELD_MAPPING`, `CREATED_LINKED_ACCOUNT_FIELD_MAPPING`, `CHANGED_INTEGRATION_WIDE_FIELD_MAPPING`, `CHANGED_LINKED_ACCOUNT_FIELD_MAPPING`, `DELETED_INTEGRATION_WIDE_FIELD_MAPPING`, `DELETED_LINKED_ACCOUNT_FIELD_MAPPING`, `CREATED_LINKED_ACCOUNT_COMMON_MODEL_OVERRIDE`, `CHANGED_LINKED_ACCOUNT_COMMON_MODEL_OVERRIDE`, `DELETED_LINKED_ACCOUNT_COMMON_MODEL_OVERRIDE`, `FORCED_LINKED_ACCOUNT_RESYNC`, `MUTED_ISSUE`, `GENERATED_MAGIC_LINK`, `ENABLED_MERGE_WEBHOOK`, `DISABLED_MERGE_WEBHOOK`, `MERGE_WEBHOOK_TARGET_CHANGED`, `END_USER_CREDENTIALS_ACCESSED`
+
+ page_size : typing.Optional[int]
+ Number of results to return per page. The maximum limit is 100.
+
+ start_date : typing.Optional[str]
+ If included, will only include audit trail events that occurred after this time
+
+ user_email : typing.Optional[str]
+ If provided, this will return events associated with the specified user email. Please note that the email address reflects the user's email at the time of the event, and may not be their current email.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ PaginatedAuditLogEventList
+
+
+ Examples
+ --------
+ import asyncio
+
+ from merge import AsyncMerge
+
+ client = AsyncMerge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.email.audit_trail.list(
+ cursor="cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw",
+ end_date="end_date",
+ event_type="event_type",
+ page_size=1,
+ start_date="start_date",
+ user_email="user_email",
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.list(
+ cursor=cursor,
+ end_date=end_date,
+ event_type=event_type,
+ page_size=page_size,
+ start_date=start_date,
+ user_email=user_email,
+ request_options=request_options,
+ )
+ return _response.data
diff --git a/src/merge/resources/email/resources/audit_trail/raw_client.py b/src/merge/resources/email/resources/audit_trail/raw_client.py
new file mode 100644
index 00000000..79332f47
--- /dev/null
+++ b/src/merge/resources/email/resources/audit_trail/raw_client.py
@@ -0,0 +1,161 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+from json.decoder import JSONDecodeError
+
+from .....core.api_error import ApiError
+from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .....core.http_response import AsyncHttpResponse, HttpResponse
+from .....core.request_options import RequestOptions
+from .....core.unchecked_base_model import construct_type
+from ...types.paginated_audit_log_event_list import PaginatedAuditLogEventList
+
+
+class RawAuditTrailClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ def list(
+ self,
+ *,
+ cursor: typing.Optional[str] = None,
+ end_date: typing.Optional[str] = None,
+ event_type: typing.Optional[str] = None,
+ page_size: typing.Optional[int] = None,
+ start_date: typing.Optional[str] = None,
+ user_email: typing.Optional[str] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> HttpResponse[PaginatedAuditLogEventList]:
+ """
+ Gets a list of audit trail events.
+
+ Parameters
+ ----------
+ cursor : typing.Optional[str]
+ The pagination cursor value.
+
+ end_date : typing.Optional[str]
+ If included, will only include audit trail events that occurred before this time
+
+ event_type : typing.Optional[str]
+ If included, will only include events with the given event type. Possible values include: `CREATED_REMOTE_PRODUCTION_API_KEY`, `DELETED_REMOTE_PRODUCTION_API_KEY`, `CREATED_TEST_API_KEY`, `DELETED_TEST_API_KEY`, `REGENERATED_PRODUCTION_API_KEY`, `REGENERATED_WEBHOOK_SIGNATURE`, `INVITED_USER`, `TWO_FACTOR_AUTH_ENABLED`, `TWO_FACTOR_AUTH_DISABLED`, `DELETED_LINKED_ACCOUNT`, `DELETED_ALL_COMMON_MODELS_FOR_LINKED_ACCOUNT`, `CREATED_DESTINATION`, `DELETED_DESTINATION`, `CHANGED_DESTINATION`, `CHANGED_SCOPES`, `CHANGED_PERSONAL_INFORMATION`, `CHANGED_ORGANIZATION_SETTINGS`, `ENABLED_INTEGRATION`, `DISABLED_INTEGRATION`, `ENABLED_CATEGORY`, `DISABLED_CATEGORY`, `CHANGED_PASSWORD`, `RESET_PASSWORD`, `ENABLED_REDACT_UNMAPPED_DATA_FOR_ORGANIZATION`, `ENABLED_REDACT_UNMAPPED_DATA_FOR_LINKED_ACCOUNT`, `DISABLED_REDACT_UNMAPPED_DATA_FOR_ORGANIZATION`, `DISABLED_REDACT_UNMAPPED_DATA_FOR_LINKED_ACCOUNT`, `CREATED_INTEGRATION_WIDE_FIELD_MAPPING`, `CREATED_LINKED_ACCOUNT_FIELD_MAPPING`, `CHANGED_INTEGRATION_WIDE_FIELD_MAPPING`, `CHANGED_LINKED_ACCOUNT_FIELD_MAPPING`, `DELETED_INTEGRATION_WIDE_FIELD_MAPPING`, `DELETED_LINKED_ACCOUNT_FIELD_MAPPING`, `CREATED_LINKED_ACCOUNT_COMMON_MODEL_OVERRIDE`, `CHANGED_LINKED_ACCOUNT_COMMON_MODEL_OVERRIDE`, `DELETED_LINKED_ACCOUNT_COMMON_MODEL_OVERRIDE`, `FORCED_LINKED_ACCOUNT_RESYNC`, `MUTED_ISSUE`, `GENERATED_MAGIC_LINK`, `ENABLED_MERGE_WEBHOOK`, `DISABLED_MERGE_WEBHOOK`, `MERGE_WEBHOOK_TARGET_CHANGED`, `END_USER_CREDENTIALS_ACCESSED`
+
+ page_size : typing.Optional[int]
+ Number of results to return per page. The maximum limit is 100.
+
+ start_date : typing.Optional[str]
+ If included, will only include audit trail events that occurred after this time
+
+ user_email : typing.Optional[str]
+ If provided, this will return events associated with the specified user email. Please note that the email address reflects the user's email at the time of the event, and may not be their current email.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[PaginatedAuditLogEventList]
+
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ "email/v1/audit-trail",
+ method="GET",
+ params={
+ "cursor": cursor,
+ "end_date": end_date,
+ "event_type": event_type,
+ "page_size": page_size,
+ "start_date": start_date,
+ "user_email": user_email,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ PaginatedAuditLogEventList,
+ construct_type(
+ type_=PaginatedAuditLogEventList, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+
+class AsyncRawAuditTrailClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ async def list(
+ self,
+ *,
+ cursor: typing.Optional[str] = None,
+ end_date: typing.Optional[str] = None,
+ event_type: typing.Optional[str] = None,
+ page_size: typing.Optional[int] = None,
+ start_date: typing.Optional[str] = None,
+ user_email: typing.Optional[str] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> AsyncHttpResponse[PaginatedAuditLogEventList]:
+ """
+ Gets a list of audit trail events.
+
+ Parameters
+ ----------
+ cursor : typing.Optional[str]
+ The pagination cursor value.
+
+ end_date : typing.Optional[str]
+ If included, will only include audit trail events that occurred before this time
+
+ event_type : typing.Optional[str]
+ If included, will only include events with the given event type. Possible values include: `CREATED_REMOTE_PRODUCTION_API_KEY`, `DELETED_REMOTE_PRODUCTION_API_KEY`, `CREATED_TEST_API_KEY`, `DELETED_TEST_API_KEY`, `REGENERATED_PRODUCTION_API_KEY`, `REGENERATED_WEBHOOK_SIGNATURE`, `INVITED_USER`, `TWO_FACTOR_AUTH_ENABLED`, `TWO_FACTOR_AUTH_DISABLED`, `DELETED_LINKED_ACCOUNT`, `DELETED_ALL_COMMON_MODELS_FOR_LINKED_ACCOUNT`, `CREATED_DESTINATION`, `DELETED_DESTINATION`, `CHANGED_DESTINATION`, `CHANGED_SCOPES`, `CHANGED_PERSONAL_INFORMATION`, `CHANGED_ORGANIZATION_SETTINGS`, `ENABLED_INTEGRATION`, `DISABLED_INTEGRATION`, `ENABLED_CATEGORY`, `DISABLED_CATEGORY`, `CHANGED_PASSWORD`, `RESET_PASSWORD`, `ENABLED_REDACT_UNMAPPED_DATA_FOR_ORGANIZATION`, `ENABLED_REDACT_UNMAPPED_DATA_FOR_LINKED_ACCOUNT`, `DISABLED_REDACT_UNMAPPED_DATA_FOR_ORGANIZATION`, `DISABLED_REDACT_UNMAPPED_DATA_FOR_LINKED_ACCOUNT`, `CREATED_INTEGRATION_WIDE_FIELD_MAPPING`, `CREATED_LINKED_ACCOUNT_FIELD_MAPPING`, `CHANGED_INTEGRATION_WIDE_FIELD_MAPPING`, `CHANGED_LINKED_ACCOUNT_FIELD_MAPPING`, `DELETED_INTEGRATION_WIDE_FIELD_MAPPING`, `DELETED_LINKED_ACCOUNT_FIELD_MAPPING`, `CREATED_LINKED_ACCOUNT_COMMON_MODEL_OVERRIDE`, `CHANGED_LINKED_ACCOUNT_COMMON_MODEL_OVERRIDE`, `DELETED_LINKED_ACCOUNT_COMMON_MODEL_OVERRIDE`, `FORCED_LINKED_ACCOUNT_RESYNC`, `MUTED_ISSUE`, `GENERATED_MAGIC_LINK`, `ENABLED_MERGE_WEBHOOK`, `DISABLED_MERGE_WEBHOOK`, `MERGE_WEBHOOK_TARGET_CHANGED`, `END_USER_CREDENTIALS_ACCESSED`
+
+ page_size : typing.Optional[int]
+ Number of results to return per page. The maximum limit is 100.
+
+ start_date : typing.Optional[str]
+ If included, will only include audit trail events that occurred after this time
+
+ user_email : typing.Optional[str]
+ If provided, this will return events associated with the specified user email. Please note that the email address reflects the user's email at the time of the event, and may not be their current email.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[PaginatedAuditLogEventList]
+
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ "email/v1/audit-trail",
+ method="GET",
+ params={
+ "cursor": cursor,
+ "end_date": end_date,
+ "event_type": event_type,
+ "page_size": page_size,
+ "start_date": start_date,
+ "user_email": user_email,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ PaginatedAuditLogEventList,
+ construct_type(
+ type_=PaginatedAuditLogEventList, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
diff --git a/src/merge/resources/email/resources/available_actions/__init__.py b/src/merge/resources/email/resources/available_actions/__init__.py
new file mode 100644
index 00000000..5cde0202
--- /dev/null
+++ b/src/merge/resources/email/resources/available_actions/__init__.py
@@ -0,0 +1,4 @@
+# This file was auto-generated by Fern from our API Definition.
+
+# isort: skip_file
+
diff --git a/src/merge/resources/email/resources/available_actions/client.py b/src/merge/resources/email/resources/available_actions/client.py
new file mode 100644
index 00000000..d61c0a93
--- /dev/null
+++ b/src/merge/resources/email/resources/available_actions/client.py
@@ -0,0 +1,102 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .....core.request_options import RequestOptions
+from ...types.available_actions import AvailableActions
+from .raw_client import AsyncRawAvailableActionsClient, RawAvailableActionsClient
+
+
+class AvailableActionsClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._raw_client = RawAvailableActionsClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> RawAvailableActionsClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ RawAvailableActionsClient
+ """
+ return self._raw_client
+
+ def retrieve(self, *, request_options: typing.Optional[RequestOptions] = None) -> AvailableActions:
+ """
+ Returns a list of models and actions available for an account.
+
+ Parameters
+ ----------
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AvailableActions
+
+
+ Examples
+ --------
+ from merge import Merge
+
+ client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+ client.email.available_actions.retrieve()
+ """
+ _response = self._raw_client.retrieve(request_options=request_options)
+ return _response.data
+
+
+class AsyncAvailableActionsClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._raw_client = AsyncRawAvailableActionsClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> AsyncRawAvailableActionsClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ AsyncRawAvailableActionsClient
+ """
+ return self._raw_client
+
+ async def retrieve(self, *, request_options: typing.Optional[RequestOptions] = None) -> AvailableActions:
+ """
+ Returns a list of models and actions available for an account.
+
+ Parameters
+ ----------
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AvailableActions
+
+
+ Examples
+ --------
+ import asyncio
+
+ from merge import AsyncMerge
+
+ client = AsyncMerge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.email.available_actions.retrieve()
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.retrieve(request_options=request_options)
+ return _response.data
diff --git a/src/merge/resources/email/resources/available_actions/raw_client.py b/src/merge/resources/email/resources/available_actions/raw_client.py
new file mode 100644
index 00000000..ca72efd1
--- /dev/null
+++ b/src/merge/resources/email/resources/available_actions/raw_client.py
@@ -0,0 +1,91 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+from json.decoder import JSONDecodeError
+
+from .....core.api_error import ApiError
+from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .....core.http_response import AsyncHttpResponse, HttpResponse
+from .....core.request_options import RequestOptions
+from .....core.unchecked_base_model import construct_type
+from ...types.available_actions import AvailableActions
+
+
+class RawAvailableActionsClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ def retrieve(self, *, request_options: typing.Optional[RequestOptions] = None) -> HttpResponse[AvailableActions]:
+ """
+ Returns a list of models and actions available for an account.
+
+ Parameters
+ ----------
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[AvailableActions]
+
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ "email/v1/available-actions",
+ method="GET",
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ AvailableActions,
+ construct_type(
+ type_=AvailableActions, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+
+class AsyncRawAvailableActionsClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ async def retrieve(
+ self, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> AsyncHttpResponse[AvailableActions]:
+ """
+ Returns a list of models and actions available for an account.
+
+ Parameters
+ ----------
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[AvailableActions]
+
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ "email/v1/available-actions",
+ method="GET",
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ AvailableActions,
+ construct_type(
+ type_=AvailableActions, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
diff --git a/src/merge/resources/email/resources/delete_account/__init__.py b/src/merge/resources/email/resources/delete_account/__init__.py
new file mode 100644
index 00000000..5cde0202
--- /dev/null
+++ b/src/merge/resources/email/resources/delete_account/__init__.py
@@ -0,0 +1,4 @@
+# This file was auto-generated by Fern from our API Definition.
+
+# isort: skip_file
+
diff --git a/src/merge/resources/email/resources/delete_account/client.py b/src/merge/resources/email/resources/delete_account/client.py
new file mode 100644
index 00000000..e4d10f1b
--- /dev/null
+++ b/src/merge/resources/email/resources/delete_account/client.py
@@ -0,0 +1,99 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .....core.request_options import RequestOptions
+from .raw_client import AsyncRawDeleteAccountClient, RawDeleteAccountClient
+
+
+class DeleteAccountClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._raw_client = RawDeleteAccountClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> RawDeleteAccountClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ RawDeleteAccountClient
+ """
+ return self._raw_client
+
+ def delete(self, *, request_options: typing.Optional[RequestOptions] = None) -> None:
+ """
+ Delete a linked account.
+
+ Parameters
+ ----------
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ None
+
+ Examples
+ --------
+ from merge import Merge
+
+ client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+ client.email.delete_account.delete()
+ """
+ _response = self._raw_client.delete(request_options=request_options)
+ return _response.data
+
+
+class AsyncDeleteAccountClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._raw_client = AsyncRawDeleteAccountClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> AsyncRawDeleteAccountClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ AsyncRawDeleteAccountClient
+ """
+ return self._raw_client
+
+ async def delete(self, *, request_options: typing.Optional[RequestOptions] = None) -> None:
+ """
+ Delete a linked account.
+
+ Parameters
+ ----------
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ None
+
+ Examples
+ --------
+ import asyncio
+
+ from merge import AsyncMerge
+
+ client = AsyncMerge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.email.delete_account.delete()
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.delete(request_options=request_options)
+ return _response.data
diff --git a/src/merge/resources/email/resources/delete_account/raw_client.py b/src/merge/resources/email/resources/delete_account/raw_client.py
new file mode 100644
index 00000000..c49a9b44
--- /dev/null
+++ b/src/merge/resources/email/resources/delete_account/raw_client.py
@@ -0,0 +1,71 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+from json.decoder import JSONDecodeError
+
+from .....core.api_error import ApiError
+from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .....core.http_response import AsyncHttpResponse, HttpResponse
+from .....core.request_options import RequestOptions
+
+
+class RawDeleteAccountClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ def delete(self, *, request_options: typing.Optional[RequestOptions] = None) -> HttpResponse[None]:
+ """
+ Delete a linked account.
+
+ Parameters
+ ----------
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[None]
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ "email/v1/delete-account",
+ method="POST",
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ return HttpResponse(response=_response, data=None)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+
+class AsyncRawDeleteAccountClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ async def delete(self, *, request_options: typing.Optional[RequestOptions] = None) -> AsyncHttpResponse[None]:
+ """
+ Delete a linked account.
+
+ Parameters
+ ----------
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[None]
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ "email/v1/delete-account",
+ method="POST",
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ return AsyncHttpResponse(response=_response, data=None)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
diff --git a/src/merge/resources/email/resources/email_addresses/__init__.py b/src/merge/resources/email/resources/email_addresses/__init__.py
new file mode 100644
index 00000000..081f4b52
--- /dev/null
+++ b/src/merge/resources/email/resources/email_addresses/__init__.py
@@ -0,0 +1,35 @@
+# This file was auto-generated by Fern from our API Definition.
+
+# isort: skip_file
+
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .types import EmailAddressesListRequestExpandItem, EmailAddressesRetrieveRequestExpandItem
+_dynamic_imports: typing.Dict[str, str] = {
+ "EmailAddressesListRequestExpandItem": ".types",
+ "EmailAddressesRetrieveRequestExpandItem": ".types",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ result = getattr(module, attr_name)
+ return result
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
+
+__all__ = ["EmailAddressesListRequestExpandItem", "EmailAddressesRetrieveRequestExpandItem"]
diff --git a/src/merge/resources/email/resources/email_addresses/client.py b/src/merge/resources/email/resources/email_addresses/client.py
new file mode 100644
index 00000000..4be59319
--- /dev/null
+++ b/src/merge/resources/email/resources/email_addresses/client.py
@@ -0,0 +1,413 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+
+from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .....core.request_options import RequestOptions
+from ...types.email_address import EmailAddress
+from ...types.paginated_email_address_list import PaginatedEmailAddressList
+from .raw_client import AsyncRawEmailAddressesClient, RawEmailAddressesClient
+from .types.email_addresses_list_request_expand_item import EmailAddressesListRequestExpandItem
+from .types.email_addresses_retrieve_request_expand_item import EmailAddressesRetrieveRequestExpandItem
+
+
+class EmailAddressesClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._raw_client = RawEmailAddressesClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> RawEmailAddressesClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ RawEmailAddressesClient
+ """
+ return self._raw_client
+
+ def list(
+ self,
+ *,
+ created_after: typing.Optional[dt.datetime] = None,
+ created_before: typing.Optional[dt.datetime] = None,
+ cursor: typing.Optional[str] = None,
+ email_address: typing.Optional[str] = None,
+ expand: typing.Optional[
+ typing.Union[EmailAddressesListRequestExpandItem, typing.Sequence[EmailAddressesListRequestExpandItem]]
+ ] = None,
+ include_deleted_data: typing.Optional[bool] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ modified_after: typing.Optional[dt.datetime] = None,
+ modified_before: typing.Optional[dt.datetime] = None,
+ page_size: typing.Optional[int] = None,
+ remote_id: typing.Optional[str] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> PaginatedEmailAddressList:
+ """
+ Returns a list of `EmailAddress` objects.
+
+ Parameters
+ ----------
+ created_after : typing.Optional[dt.datetime]
+ If provided, will only return objects created after this datetime.
+
+ created_before : typing.Optional[dt.datetime]
+ If provided, will only return objects created before this datetime.
+
+ cursor : typing.Optional[str]
+ The pagination cursor value.
+
+ email_address : typing.Optional[str]
+ If provided, will only return EmailAddresses matching this value (case insensitive).
+
+ expand : typing.Optional[typing.Union[EmailAddressesListRequestExpandItem, typing.Sequence[EmailAddressesListRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ include_deleted_data : typing.Optional[bool]
+ Indicates whether or not this object has been deleted in the third party platform. Full coverage deletion detection is a premium add-on. Native deletion detection is offered for free with limited coverage. [Learn more](https://docs.merge.dev/integrations/hris/supported-features/).
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ modified_after : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge after this date time will be returned.
+
+ modified_before : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge before this date time will be returned.
+
+ page_size : typing.Optional[int]
+ Number of results to return per page. The maximum limit is 100.
+
+ remote_id : typing.Optional[str]
+ The API provider's ID for the given object.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ PaginatedEmailAddressList
+
+
+ Examples
+ --------
+ import datetime
+
+ from merge import Merge
+
+ client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+ client.email.email_addresses.list(
+ created_after=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ created_before=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ cursor="cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw",
+ email_address="email_address",
+ include_deleted_data=True,
+ include_remote_data=True,
+ include_shell_data=True,
+ modified_after=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ modified_before=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ page_size=1,
+ remote_id="remote_id",
+ )
+ """
+ _response = self._raw_client.list(
+ created_after=created_after,
+ created_before=created_before,
+ cursor=cursor,
+ email_address=email_address,
+ expand=expand,
+ include_deleted_data=include_deleted_data,
+ include_remote_data=include_remote_data,
+ include_shell_data=include_shell_data,
+ modified_after=modified_after,
+ modified_before=modified_before,
+ page_size=page_size,
+ remote_id=remote_id,
+ request_options=request_options,
+ )
+ return _response.data
+
+ def retrieve(
+ self,
+ id: str,
+ *,
+ expand: typing.Optional[
+ typing.Union[
+ EmailAddressesRetrieveRequestExpandItem, typing.Sequence[EmailAddressesRetrieveRequestExpandItem]
+ ]
+ ] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> EmailAddress:
+ """
+ Returns an `EmailAddress` object with the given `id`.
+
+ Parameters
+ ----------
+ id : str
+
+ expand : typing.Optional[typing.Union[EmailAddressesRetrieveRequestExpandItem, typing.Sequence[EmailAddressesRetrieveRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ EmailAddress
+
+
+ Examples
+ --------
+ from merge import Merge
+
+ client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+ client.email.email_addresses.retrieve(
+ id="id",
+ include_remote_data=True,
+ include_shell_data=True,
+ )
+ """
+ _response = self._raw_client.retrieve(
+ id,
+ expand=expand,
+ include_remote_data=include_remote_data,
+ include_shell_data=include_shell_data,
+ request_options=request_options,
+ )
+ return _response.data
+
+
+class AsyncEmailAddressesClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._raw_client = AsyncRawEmailAddressesClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> AsyncRawEmailAddressesClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ AsyncRawEmailAddressesClient
+ """
+ return self._raw_client
+
+ async def list(
+ self,
+ *,
+ created_after: typing.Optional[dt.datetime] = None,
+ created_before: typing.Optional[dt.datetime] = None,
+ cursor: typing.Optional[str] = None,
+ email_address: typing.Optional[str] = None,
+ expand: typing.Optional[
+ typing.Union[EmailAddressesListRequestExpandItem, typing.Sequence[EmailAddressesListRequestExpandItem]]
+ ] = None,
+ include_deleted_data: typing.Optional[bool] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ modified_after: typing.Optional[dt.datetime] = None,
+ modified_before: typing.Optional[dt.datetime] = None,
+ page_size: typing.Optional[int] = None,
+ remote_id: typing.Optional[str] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> PaginatedEmailAddressList:
+ """
+ Returns a list of `EmailAddress` objects.
+
+ Parameters
+ ----------
+ created_after : typing.Optional[dt.datetime]
+ If provided, will only return objects created after this datetime.
+
+ created_before : typing.Optional[dt.datetime]
+ If provided, will only return objects created before this datetime.
+
+ cursor : typing.Optional[str]
+ The pagination cursor value.
+
+ email_address : typing.Optional[str]
+ If provided, will only return EmailAddresses matching this value (case insensitive).
+
+ expand : typing.Optional[typing.Union[EmailAddressesListRequestExpandItem, typing.Sequence[EmailAddressesListRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ include_deleted_data : typing.Optional[bool]
+ Indicates whether or not this object has been deleted in the third party platform. Full coverage deletion detection is a premium add-on. Native deletion detection is offered for free with limited coverage. [Learn more](https://docs.merge.dev/integrations/hris/supported-features/).
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ modified_after : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge after this date time will be returned.
+
+ modified_before : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge before this date time will be returned.
+
+ page_size : typing.Optional[int]
+ Number of results to return per page. The maximum limit is 100.
+
+ remote_id : typing.Optional[str]
+ The API provider's ID for the given object.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ PaginatedEmailAddressList
+
+
+ Examples
+ --------
+ import asyncio
+ import datetime
+
+ from merge import AsyncMerge
+
+ client = AsyncMerge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.email.email_addresses.list(
+ created_after=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ created_before=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ cursor="cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw",
+ email_address="email_address",
+ include_deleted_data=True,
+ include_remote_data=True,
+ include_shell_data=True,
+ modified_after=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ modified_before=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ page_size=1,
+ remote_id="remote_id",
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.list(
+ created_after=created_after,
+ created_before=created_before,
+ cursor=cursor,
+ email_address=email_address,
+ expand=expand,
+ include_deleted_data=include_deleted_data,
+ include_remote_data=include_remote_data,
+ include_shell_data=include_shell_data,
+ modified_after=modified_after,
+ modified_before=modified_before,
+ page_size=page_size,
+ remote_id=remote_id,
+ request_options=request_options,
+ )
+ return _response.data
+
+ async def retrieve(
+ self,
+ id: str,
+ *,
+ expand: typing.Optional[
+ typing.Union[
+ EmailAddressesRetrieveRequestExpandItem, typing.Sequence[EmailAddressesRetrieveRequestExpandItem]
+ ]
+ ] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> EmailAddress:
+ """
+ Returns an `EmailAddress` object with the given `id`.
+
+ Parameters
+ ----------
+ id : str
+
+ expand : typing.Optional[typing.Union[EmailAddressesRetrieveRequestExpandItem, typing.Sequence[EmailAddressesRetrieveRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ EmailAddress
+
+
+ Examples
+ --------
+ import asyncio
+
+ from merge import AsyncMerge
+
+ client = AsyncMerge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.email.email_addresses.retrieve(
+ id="id",
+ include_remote_data=True,
+ include_shell_data=True,
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.retrieve(
+ id,
+ expand=expand,
+ include_remote_data=include_remote_data,
+ include_shell_data=include_shell_data,
+ request_options=request_options,
+ )
+ return _response.data
diff --git a/src/merge/resources/email/resources/email_addresses/raw_client.py b/src/merge/resources/email/resources/email_addresses/raw_client.py
new file mode 100644
index 00000000..ca6713d8
--- /dev/null
+++ b/src/merge/resources/email/resources/email_addresses/raw_client.py
@@ -0,0 +1,355 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+from json.decoder import JSONDecodeError
+
+from .....core.api_error import ApiError
+from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .....core.datetime_utils import serialize_datetime
+from .....core.http_response import AsyncHttpResponse, HttpResponse
+from .....core.jsonable_encoder import jsonable_encoder
+from .....core.request_options import RequestOptions
+from .....core.unchecked_base_model import construct_type
+from ...types.email_address import EmailAddress
+from ...types.paginated_email_address_list import PaginatedEmailAddressList
+from .types.email_addresses_list_request_expand_item import EmailAddressesListRequestExpandItem
+from .types.email_addresses_retrieve_request_expand_item import EmailAddressesRetrieveRequestExpandItem
+
+
+class RawEmailAddressesClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ def list(
+ self,
+ *,
+ created_after: typing.Optional[dt.datetime] = None,
+ created_before: typing.Optional[dt.datetime] = None,
+ cursor: typing.Optional[str] = None,
+ email_address: typing.Optional[str] = None,
+ expand: typing.Optional[
+ typing.Union[EmailAddressesListRequestExpandItem, typing.Sequence[EmailAddressesListRequestExpandItem]]
+ ] = None,
+ include_deleted_data: typing.Optional[bool] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ modified_after: typing.Optional[dt.datetime] = None,
+ modified_before: typing.Optional[dt.datetime] = None,
+ page_size: typing.Optional[int] = None,
+ remote_id: typing.Optional[str] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> HttpResponse[PaginatedEmailAddressList]:
+ """
+ Returns a list of `EmailAddress` objects.
+
+ Parameters
+ ----------
+ created_after : typing.Optional[dt.datetime]
+ If provided, will only return objects created after this datetime.
+
+ created_before : typing.Optional[dt.datetime]
+ If provided, will only return objects created before this datetime.
+
+ cursor : typing.Optional[str]
+ The pagination cursor value.
+
+ email_address : typing.Optional[str]
+ If provided, will only return EmailAddresses matching this value (case insensitive).
+
+ expand : typing.Optional[typing.Union[EmailAddressesListRequestExpandItem, typing.Sequence[EmailAddressesListRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ include_deleted_data : typing.Optional[bool]
+ Indicates whether or not this object has been deleted in the third party platform. Full coverage deletion detection is a premium add-on. Native deletion detection is offered for free with limited coverage. [Learn more](https://docs.merge.dev/integrations/hris/supported-features/).
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ modified_after : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge after this date time will be returned.
+
+ modified_before : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge before this date time will be returned.
+
+ page_size : typing.Optional[int]
+ Number of results to return per page. The maximum limit is 100.
+
+ remote_id : typing.Optional[str]
+ The API provider's ID for the given object.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[PaginatedEmailAddressList]
+
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ "email/v1/email-addresses",
+ method="GET",
+ params={
+ "created_after": serialize_datetime(created_after) if created_after is not None else None,
+ "created_before": serialize_datetime(created_before) if created_before is not None else None,
+ "cursor": cursor,
+ "email_address": email_address,
+ "expand": expand,
+ "include_deleted_data": include_deleted_data,
+ "include_remote_data": include_remote_data,
+ "include_shell_data": include_shell_data,
+ "modified_after": serialize_datetime(modified_after) if modified_after is not None else None,
+ "modified_before": serialize_datetime(modified_before) if modified_before is not None else None,
+ "page_size": page_size,
+ "remote_id": remote_id,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ PaginatedEmailAddressList,
+ construct_type(
+ type_=PaginatedEmailAddressList, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ def retrieve(
+ self,
+ id: str,
+ *,
+ expand: typing.Optional[
+ typing.Union[
+ EmailAddressesRetrieveRequestExpandItem, typing.Sequence[EmailAddressesRetrieveRequestExpandItem]
+ ]
+ ] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> HttpResponse[EmailAddress]:
+ """
+ Returns an `EmailAddress` object with the given `id`.
+
+ Parameters
+ ----------
+ id : str
+
+ expand : typing.Optional[typing.Union[EmailAddressesRetrieveRequestExpandItem, typing.Sequence[EmailAddressesRetrieveRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[EmailAddress]
+
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ f"email/v1/email-addresses/{jsonable_encoder(id)}",
+ method="GET",
+ params={
+ "expand": expand,
+ "include_remote_data": include_remote_data,
+ "include_shell_data": include_shell_data,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ EmailAddress,
+ construct_type(
+ type_=EmailAddress, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+
+class AsyncRawEmailAddressesClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ async def list(
+ self,
+ *,
+ created_after: typing.Optional[dt.datetime] = None,
+ created_before: typing.Optional[dt.datetime] = None,
+ cursor: typing.Optional[str] = None,
+ email_address: typing.Optional[str] = None,
+ expand: typing.Optional[
+ typing.Union[EmailAddressesListRequestExpandItem, typing.Sequence[EmailAddressesListRequestExpandItem]]
+ ] = None,
+ include_deleted_data: typing.Optional[bool] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ modified_after: typing.Optional[dt.datetime] = None,
+ modified_before: typing.Optional[dt.datetime] = None,
+ page_size: typing.Optional[int] = None,
+ remote_id: typing.Optional[str] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> AsyncHttpResponse[PaginatedEmailAddressList]:
+ """
+ Returns a list of `EmailAddress` objects.
+
+ Parameters
+ ----------
+ created_after : typing.Optional[dt.datetime]
+ If provided, will only return objects created after this datetime.
+
+ created_before : typing.Optional[dt.datetime]
+ If provided, will only return objects created before this datetime.
+
+ cursor : typing.Optional[str]
+ The pagination cursor value.
+
+ email_address : typing.Optional[str]
+ If provided, will only return EmailAddresses matching this value (case insensitive).
+
+ expand : typing.Optional[typing.Union[EmailAddressesListRequestExpandItem, typing.Sequence[EmailAddressesListRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ include_deleted_data : typing.Optional[bool]
+ Indicates whether or not this object has been deleted in the third party platform. Full coverage deletion detection is a premium add-on. Native deletion detection is offered for free with limited coverage. [Learn more](https://docs.merge.dev/integrations/hris/supported-features/).
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ modified_after : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge after this date time will be returned.
+
+ modified_before : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge before this date time will be returned.
+
+ page_size : typing.Optional[int]
+ Number of results to return per page. The maximum limit is 100.
+
+ remote_id : typing.Optional[str]
+ The API provider's ID for the given object.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[PaginatedEmailAddressList]
+
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ "email/v1/email-addresses",
+ method="GET",
+ params={
+ "created_after": serialize_datetime(created_after) if created_after is not None else None,
+ "created_before": serialize_datetime(created_before) if created_before is not None else None,
+ "cursor": cursor,
+ "email_address": email_address,
+ "expand": expand,
+ "include_deleted_data": include_deleted_data,
+ "include_remote_data": include_remote_data,
+ "include_shell_data": include_shell_data,
+ "modified_after": serialize_datetime(modified_after) if modified_after is not None else None,
+ "modified_before": serialize_datetime(modified_before) if modified_before is not None else None,
+ "page_size": page_size,
+ "remote_id": remote_id,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ PaginatedEmailAddressList,
+ construct_type(
+ type_=PaginatedEmailAddressList, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ async def retrieve(
+ self,
+ id: str,
+ *,
+ expand: typing.Optional[
+ typing.Union[
+ EmailAddressesRetrieveRequestExpandItem, typing.Sequence[EmailAddressesRetrieveRequestExpandItem]
+ ]
+ ] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> AsyncHttpResponse[EmailAddress]:
+ """
+ Returns an `EmailAddress` object with the given `id`.
+
+ Parameters
+ ----------
+ id : str
+
+ expand : typing.Optional[typing.Union[EmailAddressesRetrieveRequestExpandItem, typing.Sequence[EmailAddressesRetrieveRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[EmailAddress]
+
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ f"email/v1/email-addresses/{jsonable_encoder(id)}",
+ method="GET",
+ params={
+ "expand": expand,
+ "include_remote_data": include_remote_data,
+ "include_shell_data": include_shell_data,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ EmailAddress,
+ construct_type(
+ type_=EmailAddress, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
diff --git a/src/merge/resources/email/resources/email_addresses/types/__init__.py b/src/merge/resources/email/resources/email_addresses/types/__init__.py
new file mode 100644
index 00000000..bb0ec1ee
--- /dev/null
+++ b/src/merge/resources/email/resources/email_addresses/types/__init__.py
@@ -0,0 +1,36 @@
+# This file was auto-generated by Fern from our API Definition.
+
+# isort: skip_file
+
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .email_addresses_list_request_expand_item import EmailAddressesListRequestExpandItem
+ from .email_addresses_retrieve_request_expand_item import EmailAddressesRetrieveRequestExpandItem
+_dynamic_imports: typing.Dict[str, str] = {
+ "EmailAddressesListRequestExpandItem": ".email_addresses_list_request_expand_item",
+ "EmailAddressesRetrieveRequestExpandItem": ".email_addresses_retrieve_request_expand_item",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ result = getattr(module, attr_name)
+ return result
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
+
+__all__ = ["EmailAddressesListRequestExpandItem", "EmailAddressesRetrieveRequestExpandItem"]
diff --git a/src/merge/resources/email/resources/email_addresses/types/email_addresses_list_request_expand_item.py b/src/merge/resources/email/resources/email_addresses/types/email_addresses_list_request_expand_item.py
new file mode 100644
index 00000000..2046a0d1
--- /dev/null
+++ b/src/merge/resources/email/resources/email_addresses/types/email_addresses_list_request_expand_item.py
@@ -0,0 +1,25 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import enum
+import typing
+
+T_Result = typing.TypeVar("T_Result")
+
+
+class EmailAddressesListRequestExpandItem(str, enum.Enum):
+ GROUPS = "groups"
+ MAILBOXES = "mailboxes"
+ USERS = "users"
+
+ def visit(
+ self,
+ groups: typing.Callable[[], T_Result],
+ mailboxes: typing.Callable[[], T_Result],
+ users: typing.Callable[[], T_Result],
+ ) -> T_Result:
+ if self is EmailAddressesListRequestExpandItem.GROUPS:
+ return groups()
+ if self is EmailAddressesListRequestExpandItem.MAILBOXES:
+ return mailboxes()
+ if self is EmailAddressesListRequestExpandItem.USERS:
+ return users()
diff --git a/src/merge/resources/email/resources/email_addresses/types/email_addresses_retrieve_request_expand_item.py b/src/merge/resources/email/resources/email_addresses/types/email_addresses_retrieve_request_expand_item.py
new file mode 100644
index 00000000..f50edc8c
--- /dev/null
+++ b/src/merge/resources/email/resources/email_addresses/types/email_addresses_retrieve_request_expand_item.py
@@ -0,0 +1,25 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import enum
+import typing
+
+T_Result = typing.TypeVar("T_Result")
+
+
+class EmailAddressesRetrieveRequestExpandItem(str, enum.Enum):
+ GROUPS = "groups"
+ MAILBOXES = "mailboxes"
+ USERS = "users"
+
+ def visit(
+ self,
+ groups: typing.Callable[[], T_Result],
+ mailboxes: typing.Callable[[], T_Result],
+ users: typing.Callable[[], T_Result],
+ ) -> T_Result:
+ if self is EmailAddressesRetrieveRequestExpandItem.GROUPS:
+ return groups()
+ if self is EmailAddressesRetrieveRequestExpandItem.MAILBOXES:
+ return mailboxes()
+ if self is EmailAddressesRetrieveRequestExpandItem.USERS:
+ return users()
diff --git a/src/merge/resources/email/resources/field_mapping/__init__.py b/src/merge/resources/email/resources/field_mapping/__init__.py
new file mode 100644
index 00000000..5cde0202
--- /dev/null
+++ b/src/merge/resources/email/resources/field_mapping/__init__.py
@@ -0,0 +1,4 @@
+# This file was auto-generated by Fern from our API Definition.
+
+# isort: skip_file
+
diff --git a/src/merge/resources/email/resources/field_mapping/client.py b/src/merge/resources/email/resources/field_mapping/client.py
new file mode 100644
index 00000000..65f4eb02
--- /dev/null
+++ b/src/merge/resources/email/resources/field_mapping/client.py
@@ -0,0 +1,828 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .....core.request_options import RequestOptions
+from ...types.external_target_field_api_response import ExternalTargetFieldApiResponse
+from ...types.field_mapping_api_instance_response import FieldMappingApiInstanceResponse
+from ...types.field_mapping_instance_response import FieldMappingInstanceResponse
+from ...types.remote_field_api_response import RemoteFieldApiResponse
+from .raw_client import AsyncRawFieldMappingClient, RawFieldMappingClient
+
+# this is used as the default value for optional parameters
+OMIT = typing.cast(typing.Any, ...)
+
+
+class FieldMappingClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._raw_client = RawFieldMappingClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> RawFieldMappingClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ RawFieldMappingClient
+ """
+ return self._raw_client
+
+ def field_mappings_retrieve(
+ self,
+ *,
+ exclude_remote_field_metadata: typing.Optional[bool] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> FieldMappingApiInstanceResponse:
+ """
+ Get all Field Mappings for this Linked Account. Field Mappings are mappings between third-party Remote Fields and user defined Merge fields. [Learn more](https://docs.merge.dev/supplemental-data/field-mappings/overview/).
+
+ Parameters
+ ----------
+ exclude_remote_field_metadata : typing.Optional[bool]
+ If `true`, remote fields metadata is excluded from each field mapping instance (i.e. `remote_fields.remote_key_name` and `remote_fields.schema` will be null). This will increase the speed of the request since these fields require some calculations.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ FieldMappingApiInstanceResponse
+
+
+ Examples
+ --------
+ from merge import Merge
+
+ client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+ client.email.field_mapping.field_mappings_retrieve(
+ exclude_remote_field_metadata=True,
+ )
+ """
+ _response = self._raw_client.field_mappings_retrieve(
+ exclude_remote_field_metadata=exclude_remote_field_metadata, request_options=request_options
+ )
+ return _response.data
+
+ def field_mappings_create(
+ self,
+ *,
+ remote_field_traversal_path: typing.Sequence[typing.Optional[typing.Any]],
+ remote_method: str,
+ remote_url_path: str,
+ common_model_name: str,
+ exclude_remote_field_metadata: typing.Optional[bool] = None,
+ remote_data_iteration_count: typing.Optional[int] = None,
+ target_field_name: typing.Optional[str] = OMIT,
+ target_field_description: typing.Optional[str] = OMIT,
+ organization_wide_target_field: typing.Optional[str] = OMIT,
+ is_integration_wide: typing.Optional[bool] = OMIT,
+ jmes_path: typing.Optional[str] = OMIT,
+ advanced_mapping_expression: typing.Optional[str] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> FieldMappingInstanceResponse:
+ """
+ Create new Field Mappings that will be available after the next scheduled sync. This will cause the next sync for this Linked Account to sync **ALL** data from start.
+
+ Parameters
+ ----------
+ remote_field_traversal_path : typing.Sequence[typing.Optional[typing.Any]]
+ The field traversal path of the remote field listed when you hit the GET /remote-fields endpoint.
+
+ remote_method : str
+ The method of the remote endpoint where the remote field is coming from.
+
+ remote_url_path : str
+ The path of the remote endpoint where the remote field is coming from.
+
+ common_model_name : str
+ The name of the Common Model that the remote field corresponds to in a given category.
+
+ exclude_remote_field_metadata : typing.Optional[bool]
+ If `true`, remote fields metadata is excluded from each field mapping instance (i.e. `remote_fields.remote_key_name` and `remote_fields.schema` will be null). This will increase the speed of the request since these fields require some calculations.
+
+ remote_data_iteration_count : typing.Optional[int]
+ Number of common model instances to iterate through when fetching remote data for field mappings. Defaults to 250 if not provided.
+
+ target_field_name : typing.Optional[str]
+ The name of the target field you want this remote field to map to. Required if organization_wide_target_field is not provided.
+
+ target_field_description : typing.Optional[str]
+ The description of the target field you want this remote field to map to. Required if organization_wide_target_field is not provided.
+
+ organization_wide_target_field : typing.Optional[str]
+ The name or key of an existing Organization-wide target field to map to. When provided, target_field_name and target_field_description are optional.
+
+ is_integration_wide : typing.Optional[bool]
+ If true, creates an integration-wide field mapping that applies to all Linked Accounts for the integration. Requires organization_wide_target_field.
+
+ jmes_path : typing.Optional[str]
+ DEPRECATED: Use 'advanced_mapping_expression' instead.
+
+ advanced_mapping_expression : typing.Optional[str]
+ A JSONata expression used to transform the remote field data.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ FieldMappingInstanceResponse
+
+
+ Examples
+ --------
+ from merge import Merge
+
+ client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+ client.email.field_mapping.field_mappings_create(
+ exclude_remote_field_metadata=True,
+ remote_data_iteration_count=1,
+ remote_field_traversal_path=["example_remote_field"],
+ remote_method="GET",
+ remote_url_path="/example-url-path",
+ common_model_name="ExampleCommonModel",
+ )
+ """
+ _response = self._raw_client.field_mappings_create(
+ remote_field_traversal_path=remote_field_traversal_path,
+ remote_method=remote_method,
+ remote_url_path=remote_url_path,
+ common_model_name=common_model_name,
+ exclude_remote_field_metadata=exclude_remote_field_metadata,
+ remote_data_iteration_count=remote_data_iteration_count,
+ target_field_name=target_field_name,
+ target_field_description=target_field_description,
+ organization_wide_target_field=organization_wide_target_field,
+ is_integration_wide=is_integration_wide,
+ jmes_path=jmes_path,
+ advanced_mapping_expression=advanced_mapping_expression,
+ request_options=request_options,
+ )
+ return _response.data
+
+ def field_mappings_destroy(
+ self, field_mapping_id: str, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> FieldMappingInstanceResponse:
+ """
+ Deletes Field Mappings for a Linked Account. All data related to this Field Mapping will be deleted and these changes will be reflected after the next scheduled sync. This will cause the next sync for this Linked Account to sync **ALL** data from start.
+
+ Parameters
+ ----------
+ field_mapping_id : str
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ FieldMappingInstanceResponse
+
+
+ Examples
+ --------
+ from merge import Merge
+
+ client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+ client.email.field_mapping.field_mappings_destroy(
+ field_mapping_id="field_mapping_id",
+ )
+ """
+ _response = self._raw_client.field_mappings_destroy(field_mapping_id, request_options=request_options)
+ return _response.data
+
+ def field_mappings_partial_update(
+ self,
+ field_mapping_id: str,
+ *,
+ remote_data_iteration_count: typing.Optional[int] = None,
+ remote_field_traversal_path: typing.Optional[typing.Sequence[typing.Optional[typing.Any]]] = OMIT,
+ remote_method: typing.Optional[str] = OMIT,
+ remote_url_path: typing.Optional[str] = OMIT,
+ jmes_path: typing.Optional[str] = OMIT,
+ advanced_mapping_expression: typing.Optional[str] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> FieldMappingInstanceResponse:
+ """
+ Create or update existing Field Mappings for a Linked Account. Changes will be reflected after the next scheduled sync. This will cause the next sync for this Linked Account to sync **ALL** data from start.
+
+ Parameters
+ ----------
+ field_mapping_id : str
+
+ remote_data_iteration_count : typing.Optional[int]
+ Number of common model instances to iterate through when fetching remote data for field mappings. Defaults to 250 if not provided.
+
+ remote_field_traversal_path : typing.Optional[typing.Sequence[typing.Optional[typing.Any]]]
+ The field traversal path of the remote field listed when you hit the GET /remote-fields endpoint.
+
+ remote_method : typing.Optional[str]
+ The method of the remote endpoint where the remote field is coming from.
+
+ remote_url_path : typing.Optional[str]
+ The path of the remote endpoint where the remote field is coming from.
+
+ jmes_path : typing.Optional[str]
+ DEPRECATED: Use 'advanced_mapping_expression' instead.
+
+ advanced_mapping_expression : typing.Optional[str]
+ A JSONata expression used to transform the remote field data.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ FieldMappingInstanceResponse
+
+
+ Examples
+ --------
+ from merge import Merge
+
+ client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+ client.email.field_mapping.field_mappings_partial_update(
+ field_mapping_id="field_mapping_id",
+ remote_data_iteration_count=1,
+ )
+ """
+ _response = self._raw_client.field_mappings_partial_update(
+ field_mapping_id,
+ remote_data_iteration_count=remote_data_iteration_count,
+ remote_field_traversal_path=remote_field_traversal_path,
+ remote_method=remote_method,
+ remote_url_path=remote_url_path,
+ jmes_path=jmes_path,
+ advanced_mapping_expression=advanced_mapping_expression,
+ request_options=request_options,
+ )
+ return _response.data
+
+ def remote_fields_retrieve(
+ self,
+ *,
+ common_models: typing.Optional[str] = None,
+ include_example_values: typing.Optional[str] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> RemoteFieldApiResponse:
+ """
+ Get all remote fields for a Linked Account. Remote fields are third-party fields that are accessible after initial sync if remote_data is enabled. You can use remote fields to override existing Merge fields or map a new Merge field. [Learn more](https://docs.merge.dev/supplemental-data/field-mappings/overview/).
+
+ Parameters
+ ----------
+ common_models : typing.Optional[str]
+ A comma seperated list of Common Model names. If included, will only return Remote Fields for those Common Models.
+
+ include_example_values : typing.Optional[str]
+ If true, will include example values, where available, for remote fields in the 3rd party platform. These examples come from active data from your customers.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ RemoteFieldApiResponse
+
+
+ Examples
+ --------
+ from merge import Merge
+
+ client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+ client.email.field_mapping.remote_fields_retrieve(
+ common_models="common_models",
+ include_example_values="include_example_values",
+ )
+ """
+ _response = self._raw_client.remote_fields_retrieve(
+ common_models=common_models, include_example_values=include_example_values, request_options=request_options
+ )
+ return _response.data
+
+ def target_fields_retrieve(
+ self, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> ExternalTargetFieldApiResponse:
+ """
+ Get all organization-wide Target Fields, this will not include any Linked Account specific Target Fields. Organization-wide Target Fields are additional fields appended to the Merge Common Model for all Linked Accounts in a category. [Learn more](https://docs.merge.dev/supplemental-data/field-mappings/target-fields/).
+
+ Parameters
+ ----------
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ ExternalTargetFieldApiResponse
+
+
+ Examples
+ --------
+ from merge import Merge
+
+ client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+ client.email.field_mapping.target_fields_retrieve()
+ """
+ _response = self._raw_client.target_fields_retrieve(request_options=request_options)
+ return _response.data
+
+ def target_fields_create(
+ self,
+ *,
+ name: str,
+ common_model: str,
+ description: typing.Optional[str] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> ExternalTargetFieldApiResponse:
+ """
+ Create a new organization-wide Target Field. Target Fields are custom fields that your organization defines to collect supplemental data from integrations. [Learn more](https://docs.merge.dev/supplemental-data/field-mappings/target-fields/).
+
+ Parameters
+ ----------
+ name : str
+ The name of the target field.
+
+ common_model : str
+ The name of the Common Model to associate the target field with.
+
+ description : typing.Optional[str]
+ The description of the target field.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ ExternalTargetFieldApiResponse
+
+
+ Examples
+ --------
+ from merge import Merge
+
+ client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+ client.email.field_mapping.target_fields_create(
+ name="employee_favorite_team",
+ common_model="Employee",
+ )
+ """
+ _response = self._raw_client.target_fields_create(
+ name=name, common_model=common_model, description=description, request_options=request_options
+ )
+ return _response.data
+
+
+class AsyncFieldMappingClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._raw_client = AsyncRawFieldMappingClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> AsyncRawFieldMappingClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ AsyncRawFieldMappingClient
+ """
+ return self._raw_client
+
+ async def field_mappings_retrieve(
+ self,
+ *,
+ exclude_remote_field_metadata: typing.Optional[bool] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> FieldMappingApiInstanceResponse:
+ """
+ Get all Field Mappings for this Linked Account. Field Mappings are mappings between third-party Remote Fields and user defined Merge fields. [Learn more](https://docs.merge.dev/supplemental-data/field-mappings/overview/).
+
+ Parameters
+ ----------
+ exclude_remote_field_metadata : typing.Optional[bool]
+ If `true`, remote fields metadata is excluded from each field mapping instance (i.e. `remote_fields.remote_key_name` and `remote_fields.schema` will be null). This will increase the speed of the request since these fields require some calculations.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ FieldMappingApiInstanceResponse
+
+
+ Examples
+ --------
+ import asyncio
+
+ from merge import AsyncMerge
+
+ client = AsyncMerge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.email.field_mapping.field_mappings_retrieve(
+ exclude_remote_field_metadata=True,
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.field_mappings_retrieve(
+ exclude_remote_field_metadata=exclude_remote_field_metadata, request_options=request_options
+ )
+ return _response.data
+
+ async def field_mappings_create(
+ self,
+ *,
+ remote_field_traversal_path: typing.Sequence[typing.Optional[typing.Any]],
+ remote_method: str,
+ remote_url_path: str,
+ common_model_name: str,
+ exclude_remote_field_metadata: typing.Optional[bool] = None,
+ remote_data_iteration_count: typing.Optional[int] = None,
+ target_field_name: typing.Optional[str] = OMIT,
+ target_field_description: typing.Optional[str] = OMIT,
+ organization_wide_target_field: typing.Optional[str] = OMIT,
+ is_integration_wide: typing.Optional[bool] = OMIT,
+ jmes_path: typing.Optional[str] = OMIT,
+ advanced_mapping_expression: typing.Optional[str] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> FieldMappingInstanceResponse:
+ """
+ Create new Field Mappings that will be available after the next scheduled sync. This will cause the next sync for this Linked Account to sync **ALL** data from start.
+
+ Parameters
+ ----------
+ remote_field_traversal_path : typing.Sequence[typing.Optional[typing.Any]]
+ The field traversal path of the remote field listed when you hit the GET /remote-fields endpoint.
+
+ remote_method : str
+ The method of the remote endpoint where the remote field is coming from.
+
+ remote_url_path : str
+ The path of the remote endpoint where the remote field is coming from.
+
+ common_model_name : str
+ The name of the Common Model that the remote field corresponds to in a given category.
+
+ exclude_remote_field_metadata : typing.Optional[bool]
+ If `true`, remote fields metadata is excluded from each field mapping instance (i.e. `remote_fields.remote_key_name` and `remote_fields.schema` will be null). This will increase the speed of the request since these fields require some calculations.
+
+ remote_data_iteration_count : typing.Optional[int]
+ Number of common model instances to iterate through when fetching remote data for field mappings. Defaults to 250 if not provided.
+
+ target_field_name : typing.Optional[str]
+ The name of the target field you want this remote field to map to. Required if organization_wide_target_field is not provided.
+
+ target_field_description : typing.Optional[str]
+ The description of the target field you want this remote field to map to. Required if organization_wide_target_field is not provided.
+
+ organization_wide_target_field : typing.Optional[str]
+ The name or key of an existing Organization-wide target field to map to. When provided, target_field_name and target_field_description are optional.
+
+ is_integration_wide : typing.Optional[bool]
+ If true, creates an integration-wide field mapping that applies to all Linked Accounts for the integration. Requires organization_wide_target_field.
+
+ jmes_path : typing.Optional[str]
+ DEPRECATED: Use 'advanced_mapping_expression' instead.
+
+ advanced_mapping_expression : typing.Optional[str]
+ A JSONata expression used to transform the remote field data.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ FieldMappingInstanceResponse
+
+
+ Examples
+ --------
+ import asyncio
+
+ from merge import AsyncMerge
+
+ client = AsyncMerge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.email.field_mapping.field_mappings_create(
+ exclude_remote_field_metadata=True,
+ remote_data_iteration_count=1,
+ remote_field_traversal_path=["example_remote_field"],
+ remote_method="GET",
+ remote_url_path="/example-url-path",
+ common_model_name="ExampleCommonModel",
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.field_mappings_create(
+ remote_field_traversal_path=remote_field_traversal_path,
+ remote_method=remote_method,
+ remote_url_path=remote_url_path,
+ common_model_name=common_model_name,
+ exclude_remote_field_metadata=exclude_remote_field_metadata,
+ remote_data_iteration_count=remote_data_iteration_count,
+ target_field_name=target_field_name,
+ target_field_description=target_field_description,
+ organization_wide_target_field=organization_wide_target_field,
+ is_integration_wide=is_integration_wide,
+ jmes_path=jmes_path,
+ advanced_mapping_expression=advanced_mapping_expression,
+ request_options=request_options,
+ )
+ return _response.data
+
+ async def field_mappings_destroy(
+ self, field_mapping_id: str, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> FieldMappingInstanceResponse:
+ """
+ Deletes Field Mappings for a Linked Account. All data related to this Field Mapping will be deleted and these changes will be reflected after the next scheduled sync. This will cause the next sync for this Linked Account to sync **ALL** data from start.
+
+ Parameters
+ ----------
+ field_mapping_id : str
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ FieldMappingInstanceResponse
+
+
+ Examples
+ --------
+ import asyncio
+
+ from merge import AsyncMerge
+
+ client = AsyncMerge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.email.field_mapping.field_mappings_destroy(
+ field_mapping_id="field_mapping_id",
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.field_mappings_destroy(field_mapping_id, request_options=request_options)
+ return _response.data
+
+ async def field_mappings_partial_update(
+ self,
+ field_mapping_id: str,
+ *,
+ remote_data_iteration_count: typing.Optional[int] = None,
+ remote_field_traversal_path: typing.Optional[typing.Sequence[typing.Optional[typing.Any]]] = OMIT,
+ remote_method: typing.Optional[str] = OMIT,
+ remote_url_path: typing.Optional[str] = OMIT,
+ jmes_path: typing.Optional[str] = OMIT,
+ advanced_mapping_expression: typing.Optional[str] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> FieldMappingInstanceResponse:
+ """
+ Create or update existing Field Mappings for a Linked Account. Changes will be reflected after the next scheduled sync. This will cause the next sync for this Linked Account to sync **ALL** data from start.
+
+ Parameters
+ ----------
+ field_mapping_id : str
+
+ remote_data_iteration_count : typing.Optional[int]
+ Number of common model instances to iterate through when fetching remote data for field mappings. Defaults to 250 if not provided.
+
+ remote_field_traversal_path : typing.Optional[typing.Sequence[typing.Optional[typing.Any]]]
+ The field traversal path of the remote field listed when you hit the GET /remote-fields endpoint.
+
+ remote_method : typing.Optional[str]
+ The method of the remote endpoint where the remote field is coming from.
+
+ remote_url_path : typing.Optional[str]
+ The path of the remote endpoint where the remote field is coming from.
+
+ jmes_path : typing.Optional[str]
+ DEPRECATED: Use 'advanced_mapping_expression' instead.
+
+ advanced_mapping_expression : typing.Optional[str]
+ A JSONata expression used to transform the remote field data.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ FieldMappingInstanceResponse
+
+
+ Examples
+ --------
+ import asyncio
+
+ from merge import AsyncMerge
+
+ client = AsyncMerge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.email.field_mapping.field_mappings_partial_update(
+ field_mapping_id="field_mapping_id",
+ remote_data_iteration_count=1,
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.field_mappings_partial_update(
+ field_mapping_id,
+ remote_data_iteration_count=remote_data_iteration_count,
+ remote_field_traversal_path=remote_field_traversal_path,
+ remote_method=remote_method,
+ remote_url_path=remote_url_path,
+ jmes_path=jmes_path,
+ advanced_mapping_expression=advanced_mapping_expression,
+ request_options=request_options,
+ )
+ return _response.data
+
+ async def remote_fields_retrieve(
+ self,
+ *,
+ common_models: typing.Optional[str] = None,
+ include_example_values: typing.Optional[str] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> RemoteFieldApiResponse:
+ """
+ Get all remote fields for a Linked Account. Remote fields are third-party fields that are accessible after initial sync if remote_data is enabled. You can use remote fields to override existing Merge fields or map a new Merge field. [Learn more](https://docs.merge.dev/supplemental-data/field-mappings/overview/).
+
+ Parameters
+ ----------
+ common_models : typing.Optional[str]
+ A comma seperated list of Common Model names. If included, will only return Remote Fields for those Common Models.
+
+ include_example_values : typing.Optional[str]
+ If true, will include example values, where available, for remote fields in the 3rd party platform. These examples come from active data from your customers.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ RemoteFieldApiResponse
+
+
+ Examples
+ --------
+ import asyncio
+
+ from merge import AsyncMerge
+
+ client = AsyncMerge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.email.field_mapping.remote_fields_retrieve(
+ common_models="common_models",
+ include_example_values="include_example_values",
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.remote_fields_retrieve(
+ common_models=common_models, include_example_values=include_example_values, request_options=request_options
+ )
+ return _response.data
+
+ async def target_fields_retrieve(
+ self, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> ExternalTargetFieldApiResponse:
+ """
+ Get all organization-wide Target Fields, this will not include any Linked Account specific Target Fields. Organization-wide Target Fields are additional fields appended to the Merge Common Model for all Linked Accounts in a category. [Learn more](https://docs.merge.dev/supplemental-data/field-mappings/target-fields/).
+
+ Parameters
+ ----------
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ ExternalTargetFieldApiResponse
+
+
+ Examples
+ --------
+ import asyncio
+
+ from merge import AsyncMerge
+
+ client = AsyncMerge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.email.field_mapping.target_fields_retrieve()
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.target_fields_retrieve(request_options=request_options)
+ return _response.data
+
+ async def target_fields_create(
+ self,
+ *,
+ name: str,
+ common_model: str,
+ description: typing.Optional[str] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> ExternalTargetFieldApiResponse:
+ """
+ Create a new organization-wide Target Field. Target Fields are custom fields that your organization defines to collect supplemental data from integrations. [Learn more](https://docs.merge.dev/supplemental-data/field-mappings/target-fields/).
+
+ Parameters
+ ----------
+ name : str
+ The name of the target field.
+
+ common_model : str
+ The name of the Common Model to associate the target field with.
+
+ description : typing.Optional[str]
+ The description of the target field.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ ExternalTargetFieldApiResponse
+
+
+ Examples
+ --------
+ import asyncio
+
+ from merge import AsyncMerge
+
+ client = AsyncMerge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.email.field_mapping.target_fields_create(
+ name="employee_favorite_team",
+ common_model="Employee",
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.target_fields_create(
+ name=name, common_model=common_model, description=description, request_options=request_options
+ )
+ return _response.data
diff --git a/src/merge/resources/email/resources/field_mapping/raw_client.py b/src/merge/resources/email/resources/field_mapping/raw_client.py
new file mode 100644
index 00000000..6c6a6db6
--- /dev/null
+++ b/src/merge/resources/email/resources/field_mapping/raw_client.py
@@ -0,0 +1,854 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+from json.decoder import JSONDecodeError
+
+from .....core.api_error import ApiError
+from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .....core.http_response import AsyncHttpResponse, HttpResponse
+from .....core.jsonable_encoder import jsonable_encoder
+from .....core.request_options import RequestOptions
+from .....core.unchecked_base_model import construct_type
+from ...types.external_target_field_api_response import ExternalTargetFieldApiResponse
+from ...types.field_mapping_api_instance_response import FieldMappingApiInstanceResponse
+from ...types.field_mapping_instance_response import FieldMappingInstanceResponse
+from ...types.remote_field_api_response import RemoteFieldApiResponse
+
+# this is used as the default value for optional parameters
+OMIT = typing.cast(typing.Any, ...)
+
+
+class RawFieldMappingClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ def field_mappings_retrieve(
+ self,
+ *,
+ exclude_remote_field_metadata: typing.Optional[bool] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> HttpResponse[FieldMappingApiInstanceResponse]:
+ """
+ Get all Field Mappings for this Linked Account. Field Mappings are mappings between third-party Remote Fields and user defined Merge fields. [Learn more](https://docs.merge.dev/supplemental-data/field-mappings/overview/).
+
+ Parameters
+ ----------
+ exclude_remote_field_metadata : typing.Optional[bool]
+ If `true`, remote fields metadata is excluded from each field mapping instance (i.e. `remote_fields.remote_key_name` and `remote_fields.schema` will be null). This will increase the speed of the request since these fields require some calculations.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[FieldMappingApiInstanceResponse]
+
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ "email/v1/field-mappings",
+ method="GET",
+ params={
+ "exclude_remote_field_metadata": exclude_remote_field_metadata,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ FieldMappingApiInstanceResponse,
+ construct_type(
+ type_=FieldMappingApiInstanceResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ def field_mappings_create(
+ self,
+ *,
+ remote_field_traversal_path: typing.Sequence[typing.Optional[typing.Any]],
+ remote_method: str,
+ remote_url_path: str,
+ common_model_name: str,
+ exclude_remote_field_metadata: typing.Optional[bool] = None,
+ remote_data_iteration_count: typing.Optional[int] = None,
+ target_field_name: typing.Optional[str] = OMIT,
+ target_field_description: typing.Optional[str] = OMIT,
+ organization_wide_target_field: typing.Optional[str] = OMIT,
+ is_integration_wide: typing.Optional[bool] = OMIT,
+ jmes_path: typing.Optional[str] = OMIT,
+ advanced_mapping_expression: typing.Optional[str] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> HttpResponse[FieldMappingInstanceResponse]:
+ """
+ Create new Field Mappings that will be available after the next scheduled sync. This will cause the next sync for this Linked Account to sync **ALL** data from start.
+
+ Parameters
+ ----------
+ remote_field_traversal_path : typing.Sequence[typing.Optional[typing.Any]]
+ The field traversal path of the remote field listed when you hit the GET /remote-fields endpoint.
+
+ remote_method : str
+ The method of the remote endpoint where the remote field is coming from.
+
+ remote_url_path : str
+ The path of the remote endpoint where the remote field is coming from.
+
+ common_model_name : str
+ The name of the Common Model that the remote field corresponds to in a given category.
+
+ exclude_remote_field_metadata : typing.Optional[bool]
+ If `true`, remote fields metadata is excluded from each field mapping instance (i.e. `remote_fields.remote_key_name` and `remote_fields.schema` will be null). This will increase the speed of the request since these fields require some calculations.
+
+ remote_data_iteration_count : typing.Optional[int]
+ Number of common model instances to iterate through when fetching remote data for field mappings. Defaults to 250 if not provided.
+
+ target_field_name : typing.Optional[str]
+ The name of the target field you want this remote field to map to. Required if organization_wide_target_field is not provided.
+
+ target_field_description : typing.Optional[str]
+ The description of the target field you want this remote field to map to. Required if organization_wide_target_field is not provided.
+
+ organization_wide_target_field : typing.Optional[str]
+ The name or key of an existing Organization-wide target field to map to. When provided, target_field_name and target_field_description are optional.
+
+ is_integration_wide : typing.Optional[bool]
+ If true, creates an integration-wide field mapping that applies to all Linked Accounts for the integration. Requires organization_wide_target_field.
+
+ jmes_path : typing.Optional[str]
+ DEPRECATED: Use 'advanced_mapping_expression' instead.
+
+ advanced_mapping_expression : typing.Optional[str]
+ A JSONata expression used to transform the remote field data.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[FieldMappingInstanceResponse]
+
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ "email/v1/field-mappings",
+ method="POST",
+ params={
+ "exclude_remote_field_metadata": exclude_remote_field_metadata,
+ "remote_data_iteration_count": remote_data_iteration_count,
+ },
+ json={
+ "target_field_name": target_field_name,
+ "target_field_description": target_field_description,
+ "organization_wide_target_field": organization_wide_target_field,
+ "is_integration_wide": is_integration_wide,
+ "remote_field_traversal_path": remote_field_traversal_path,
+ "remote_method": remote_method,
+ "remote_url_path": remote_url_path,
+ "common_model_name": common_model_name,
+ "jmes_path": jmes_path,
+ "advanced_mapping_expression": advanced_mapping_expression,
+ },
+ headers={
+ "content-type": "application/json",
+ },
+ request_options=request_options,
+ omit=OMIT,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ FieldMappingInstanceResponse,
+ construct_type(
+ type_=FieldMappingInstanceResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ def field_mappings_destroy(
+ self, field_mapping_id: str, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> HttpResponse[FieldMappingInstanceResponse]:
+ """
+ Deletes Field Mappings for a Linked Account. All data related to this Field Mapping will be deleted and these changes will be reflected after the next scheduled sync. This will cause the next sync for this Linked Account to sync **ALL** data from start.
+
+ Parameters
+ ----------
+ field_mapping_id : str
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[FieldMappingInstanceResponse]
+
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ f"email/v1/field-mappings/{jsonable_encoder(field_mapping_id)}",
+ method="DELETE",
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ FieldMappingInstanceResponse,
+ construct_type(
+ type_=FieldMappingInstanceResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ def field_mappings_partial_update(
+ self,
+ field_mapping_id: str,
+ *,
+ remote_data_iteration_count: typing.Optional[int] = None,
+ remote_field_traversal_path: typing.Optional[typing.Sequence[typing.Optional[typing.Any]]] = OMIT,
+ remote_method: typing.Optional[str] = OMIT,
+ remote_url_path: typing.Optional[str] = OMIT,
+ jmes_path: typing.Optional[str] = OMIT,
+ advanced_mapping_expression: typing.Optional[str] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> HttpResponse[FieldMappingInstanceResponse]:
+ """
+ Create or update existing Field Mappings for a Linked Account. Changes will be reflected after the next scheduled sync. This will cause the next sync for this Linked Account to sync **ALL** data from start.
+
+ Parameters
+ ----------
+ field_mapping_id : str
+
+ remote_data_iteration_count : typing.Optional[int]
+ Number of common model instances to iterate through when fetching remote data for field mappings. Defaults to 250 if not provided.
+
+ remote_field_traversal_path : typing.Optional[typing.Sequence[typing.Optional[typing.Any]]]
+ The field traversal path of the remote field listed when you hit the GET /remote-fields endpoint.
+
+ remote_method : typing.Optional[str]
+ The method of the remote endpoint where the remote field is coming from.
+
+ remote_url_path : typing.Optional[str]
+ The path of the remote endpoint where the remote field is coming from.
+
+ jmes_path : typing.Optional[str]
+ DEPRECATED: Use 'advanced_mapping_expression' instead.
+
+ advanced_mapping_expression : typing.Optional[str]
+ A JSONata expression used to transform the remote field data.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[FieldMappingInstanceResponse]
+
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ f"email/v1/field-mappings/{jsonable_encoder(field_mapping_id)}",
+ method="PATCH",
+ params={
+ "remote_data_iteration_count": remote_data_iteration_count,
+ },
+ json={
+ "remote_field_traversal_path": remote_field_traversal_path,
+ "remote_method": remote_method,
+ "remote_url_path": remote_url_path,
+ "jmes_path": jmes_path,
+ "advanced_mapping_expression": advanced_mapping_expression,
+ },
+ headers={
+ "content-type": "application/json",
+ },
+ request_options=request_options,
+ omit=OMIT,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ FieldMappingInstanceResponse,
+ construct_type(
+ type_=FieldMappingInstanceResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ def remote_fields_retrieve(
+ self,
+ *,
+ common_models: typing.Optional[str] = None,
+ include_example_values: typing.Optional[str] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> HttpResponse[RemoteFieldApiResponse]:
+ """
+ Get all remote fields for a Linked Account. Remote fields are third-party fields that are accessible after initial sync if remote_data is enabled. You can use remote fields to override existing Merge fields or map a new Merge field. [Learn more](https://docs.merge.dev/supplemental-data/field-mappings/overview/).
+
+ Parameters
+ ----------
+ common_models : typing.Optional[str]
+ A comma seperated list of Common Model names. If included, will only return Remote Fields for those Common Models.
+
+ include_example_values : typing.Optional[str]
+ If true, will include example values, where available, for remote fields in the 3rd party platform. These examples come from active data from your customers.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[RemoteFieldApiResponse]
+
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ "email/v1/remote-fields",
+ method="GET",
+ params={
+ "common_models": common_models,
+ "include_example_values": include_example_values,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ RemoteFieldApiResponse,
+ construct_type(
+ type_=RemoteFieldApiResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ def target_fields_retrieve(
+ self, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> HttpResponse[ExternalTargetFieldApiResponse]:
+ """
+ Get all organization-wide Target Fields, this will not include any Linked Account specific Target Fields. Organization-wide Target Fields are additional fields appended to the Merge Common Model for all Linked Accounts in a category. [Learn more](https://docs.merge.dev/supplemental-data/field-mappings/target-fields/).
+
+ Parameters
+ ----------
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[ExternalTargetFieldApiResponse]
+
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ "email/v1/target-fields",
+ method="GET",
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ ExternalTargetFieldApiResponse,
+ construct_type(
+ type_=ExternalTargetFieldApiResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ def target_fields_create(
+ self,
+ *,
+ name: str,
+ common_model: str,
+ description: typing.Optional[str] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> HttpResponse[ExternalTargetFieldApiResponse]:
+ """
+ Create a new organization-wide Target Field. Target Fields are custom fields that your organization defines to collect supplemental data from integrations. [Learn more](https://docs.merge.dev/supplemental-data/field-mappings/target-fields/).
+
+ Parameters
+ ----------
+ name : str
+ The name of the target field.
+
+ common_model : str
+ The name of the Common Model to associate the target field with.
+
+ description : typing.Optional[str]
+ The description of the target field.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[ExternalTargetFieldApiResponse]
+
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ "email/v1/target-fields",
+ method="POST",
+ json={
+ "name": name,
+ "description": description,
+ "common_model": common_model,
+ },
+ headers={
+ "content-type": "application/json",
+ },
+ request_options=request_options,
+ omit=OMIT,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ ExternalTargetFieldApiResponse,
+ construct_type(
+ type_=ExternalTargetFieldApiResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+
+class AsyncRawFieldMappingClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ async def field_mappings_retrieve(
+ self,
+ *,
+ exclude_remote_field_metadata: typing.Optional[bool] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> AsyncHttpResponse[FieldMappingApiInstanceResponse]:
+ """
+ Get all Field Mappings for this Linked Account. Field Mappings are mappings between third-party Remote Fields and user defined Merge fields. [Learn more](https://docs.merge.dev/supplemental-data/field-mappings/overview/).
+
+ Parameters
+ ----------
+ exclude_remote_field_metadata : typing.Optional[bool]
+ If `true`, remote fields metadata is excluded from each field mapping instance (i.e. `remote_fields.remote_key_name` and `remote_fields.schema` will be null). This will increase the speed of the request since these fields require some calculations.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[FieldMappingApiInstanceResponse]
+
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ "email/v1/field-mappings",
+ method="GET",
+ params={
+ "exclude_remote_field_metadata": exclude_remote_field_metadata,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ FieldMappingApiInstanceResponse,
+ construct_type(
+ type_=FieldMappingApiInstanceResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ async def field_mappings_create(
+ self,
+ *,
+ remote_field_traversal_path: typing.Sequence[typing.Optional[typing.Any]],
+ remote_method: str,
+ remote_url_path: str,
+ common_model_name: str,
+ exclude_remote_field_metadata: typing.Optional[bool] = None,
+ remote_data_iteration_count: typing.Optional[int] = None,
+ target_field_name: typing.Optional[str] = OMIT,
+ target_field_description: typing.Optional[str] = OMIT,
+ organization_wide_target_field: typing.Optional[str] = OMIT,
+ is_integration_wide: typing.Optional[bool] = OMIT,
+ jmes_path: typing.Optional[str] = OMIT,
+ advanced_mapping_expression: typing.Optional[str] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> AsyncHttpResponse[FieldMappingInstanceResponse]:
+ """
+ Create new Field Mappings that will be available after the next scheduled sync. This will cause the next sync for this Linked Account to sync **ALL** data from start.
+
+ Parameters
+ ----------
+ remote_field_traversal_path : typing.Sequence[typing.Optional[typing.Any]]
+ The field traversal path of the remote field listed when you hit the GET /remote-fields endpoint.
+
+ remote_method : str
+ The method of the remote endpoint where the remote field is coming from.
+
+ remote_url_path : str
+ The path of the remote endpoint where the remote field is coming from.
+
+ common_model_name : str
+ The name of the Common Model that the remote field corresponds to in a given category.
+
+ exclude_remote_field_metadata : typing.Optional[bool]
+ If `true`, remote fields metadata is excluded from each field mapping instance (i.e. `remote_fields.remote_key_name` and `remote_fields.schema` will be null). This will increase the speed of the request since these fields require some calculations.
+
+ remote_data_iteration_count : typing.Optional[int]
+ Number of common model instances to iterate through when fetching remote data for field mappings. Defaults to 250 if not provided.
+
+ target_field_name : typing.Optional[str]
+ The name of the target field you want this remote field to map to. Required if organization_wide_target_field is not provided.
+
+ target_field_description : typing.Optional[str]
+ The description of the target field you want this remote field to map to. Required if organization_wide_target_field is not provided.
+
+ organization_wide_target_field : typing.Optional[str]
+ The name or key of an existing Organization-wide target field to map to. When provided, target_field_name and target_field_description are optional.
+
+ is_integration_wide : typing.Optional[bool]
+ If true, creates an integration-wide field mapping that applies to all Linked Accounts for the integration. Requires organization_wide_target_field.
+
+ jmes_path : typing.Optional[str]
+ DEPRECATED: Use 'advanced_mapping_expression' instead.
+
+ advanced_mapping_expression : typing.Optional[str]
+ A JSONata expression used to transform the remote field data.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[FieldMappingInstanceResponse]
+
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ "email/v1/field-mappings",
+ method="POST",
+ params={
+ "exclude_remote_field_metadata": exclude_remote_field_metadata,
+ "remote_data_iteration_count": remote_data_iteration_count,
+ },
+ json={
+ "target_field_name": target_field_name,
+ "target_field_description": target_field_description,
+ "organization_wide_target_field": organization_wide_target_field,
+ "is_integration_wide": is_integration_wide,
+ "remote_field_traversal_path": remote_field_traversal_path,
+ "remote_method": remote_method,
+ "remote_url_path": remote_url_path,
+ "common_model_name": common_model_name,
+ "jmes_path": jmes_path,
+ "advanced_mapping_expression": advanced_mapping_expression,
+ },
+ headers={
+ "content-type": "application/json",
+ },
+ request_options=request_options,
+ omit=OMIT,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ FieldMappingInstanceResponse,
+ construct_type(
+ type_=FieldMappingInstanceResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ async def field_mappings_destroy(
+ self, field_mapping_id: str, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> AsyncHttpResponse[FieldMappingInstanceResponse]:
+ """
+ Deletes Field Mappings for a Linked Account. All data related to this Field Mapping will be deleted and these changes will be reflected after the next scheduled sync. This will cause the next sync for this Linked Account to sync **ALL** data from start.
+
+ Parameters
+ ----------
+ field_mapping_id : str
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[FieldMappingInstanceResponse]
+
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ f"email/v1/field-mappings/{jsonable_encoder(field_mapping_id)}",
+ method="DELETE",
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ FieldMappingInstanceResponse,
+ construct_type(
+ type_=FieldMappingInstanceResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ async def field_mappings_partial_update(
+ self,
+ field_mapping_id: str,
+ *,
+ remote_data_iteration_count: typing.Optional[int] = None,
+ remote_field_traversal_path: typing.Optional[typing.Sequence[typing.Optional[typing.Any]]] = OMIT,
+ remote_method: typing.Optional[str] = OMIT,
+ remote_url_path: typing.Optional[str] = OMIT,
+ jmes_path: typing.Optional[str] = OMIT,
+ advanced_mapping_expression: typing.Optional[str] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> AsyncHttpResponse[FieldMappingInstanceResponse]:
+ """
+ Create or update existing Field Mappings for a Linked Account. Changes will be reflected after the next scheduled sync. This will cause the next sync for this Linked Account to sync **ALL** data from start.
+
+ Parameters
+ ----------
+ field_mapping_id : str
+
+ remote_data_iteration_count : typing.Optional[int]
+ Number of common model instances to iterate through when fetching remote data for field mappings. Defaults to 250 if not provided.
+
+ remote_field_traversal_path : typing.Optional[typing.Sequence[typing.Optional[typing.Any]]]
+ The field traversal path of the remote field listed when you hit the GET /remote-fields endpoint.
+
+ remote_method : typing.Optional[str]
+ The method of the remote endpoint where the remote field is coming from.
+
+ remote_url_path : typing.Optional[str]
+ The path of the remote endpoint where the remote field is coming from.
+
+ jmes_path : typing.Optional[str]
+ DEPRECATED: Use 'advanced_mapping_expression' instead.
+
+ advanced_mapping_expression : typing.Optional[str]
+ A JSONata expression used to transform the remote field data.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[FieldMappingInstanceResponse]
+
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ f"email/v1/field-mappings/{jsonable_encoder(field_mapping_id)}",
+ method="PATCH",
+ params={
+ "remote_data_iteration_count": remote_data_iteration_count,
+ },
+ json={
+ "remote_field_traversal_path": remote_field_traversal_path,
+ "remote_method": remote_method,
+ "remote_url_path": remote_url_path,
+ "jmes_path": jmes_path,
+ "advanced_mapping_expression": advanced_mapping_expression,
+ },
+ headers={
+ "content-type": "application/json",
+ },
+ request_options=request_options,
+ omit=OMIT,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ FieldMappingInstanceResponse,
+ construct_type(
+ type_=FieldMappingInstanceResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ async def remote_fields_retrieve(
+ self,
+ *,
+ common_models: typing.Optional[str] = None,
+ include_example_values: typing.Optional[str] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> AsyncHttpResponse[RemoteFieldApiResponse]:
+ """
+ Get all remote fields for a Linked Account. Remote fields are third-party fields that are accessible after initial sync if remote_data is enabled. You can use remote fields to override existing Merge fields or map a new Merge field. [Learn more](https://docs.merge.dev/supplemental-data/field-mappings/overview/).
+
+ Parameters
+ ----------
+ common_models : typing.Optional[str]
+ A comma seperated list of Common Model names. If included, will only return Remote Fields for those Common Models.
+
+ include_example_values : typing.Optional[str]
+ If true, will include example values, where available, for remote fields in the 3rd party platform. These examples come from active data from your customers.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[RemoteFieldApiResponse]
+
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ "email/v1/remote-fields",
+ method="GET",
+ params={
+ "common_models": common_models,
+ "include_example_values": include_example_values,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ RemoteFieldApiResponse,
+ construct_type(
+ type_=RemoteFieldApiResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ async def target_fields_retrieve(
+ self, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> AsyncHttpResponse[ExternalTargetFieldApiResponse]:
+ """
+ Get all organization-wide Target Fields, this will not include any Linked Account specific Target Fields. Organization-wide Target Fields are additional fields appended to the Merge Common Model for all Linked Accounts in a category. [Learn more](https://docs.merge.dev/supplemental-data/field-mappings/target-fields/).
+
+ Parameters
+ ----------
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[ExternalTargetFieldApiResponse]
+
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ "email/v1/target-fields",
+ method="GET",
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ ExternalTargetFieldApiResponse,
+ construct_type(
+ type_=ExternalTargetFieldApiResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ async def target_fields_create(
+ self,
+ *,
+ name: str,
+ common_model: str,
+ description: typing.Optional[str] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> AsyncHttpResponse[ExternalTargetFieldApiResponse]:
+ """
+ Create a new organization-wide Target Field. Target Fields are custom fields that your organization defines to collect supplemental data from integrations. [Learn more](https://docs.merge.dev/supplemental-data/field-mappings/target-fields/).
+
+ Parameters
+ ----------
+ name : str
+ The name of the target field.
+
+ common_model : str
+ The name of the Common Model to associate the target field with.
+
+ description : typing.Optional[str]
+ The description of the target field.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[ExternalTargetFieldApiResponse]
+
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ "email/v1/target-fields",
+ method="POST",
+ json={
+ "name": name,
+ "description": description,
+ "common_model": common_model,
+ },
+ headers={
+ "content-type": "application/json",
+ },
+ request_options=request_options,
+ omit=OMIT,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ ExternalTargetFieldApiResponse,
+ construct_type(
+ type_=ExternalTargetFieldApiResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
diff --git a/src/merge/resources/email/resources/folders/__init__.py b/src/merge/resources/email/resources/folders/__init__.py
new file mode 100644
index 00000000..b9307deb
--- /dev/null
+++ b/src/merge/resources/email/resources/folders/__init__.py
@@ -0,0 +1,35 @@
+# This file was auto-generated by Fern from our API Definition.
+
+# isort: skip_file
+
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .types import FoldersListRequestExpandItem, FoldersRetrieveRequestExpandItem
+_dynamic_imports: typing.Dict[str, str] = {
+ "FoldersListRequestExpandItem": ".types",
+ "FoldersRetrieveRequestExpandItem": ".types",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ result = getattr(module, attr_name)
+ return result
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
+
+__all__ = ["FoldersListRequestExpandItem", "FoldersRetrieveRequestExpandItem"]
diff --git a/src/merge/resources/email/resources/folders/client.py b/src/merge/resources/email/resources/folders/client.py
new file mode 100644
index 00000000..a44c00cf
--- /dev/null
+++ b/src/merge/resources/email/resources/folders/client.py
@@ -0,0 +1,409 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+
+from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .....core.request_options import RequestOptions
+from ...types.folder import Folder
+from ...types.paginated_folder_list import PaginatedFolderList
+from .raw_client import AsyncRawFoldersClient, RawFoldersClient
+from .types.folders_list_request_expand_item import FoldersListRequestExpandItem
+from .types.folders_retrieve_request_expand_item import FoldersRetrieveRequestExpandItem
+
+
+class FoldersClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._raw_client = RawFoldersClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> RawFoldersClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ RawFoldersClient
+ """
+ return self._raw_client
+
+ def list(
+ self,
+ *,
+ created_after: typing.Optional[dt.datetime] = None,
+ created_before: typing.Optional[dt.datetime] = None,
+ cursor: typing.Optional[str] = None,
+ expand: typing.Optional[
+ typing.Union[FoldersListRequestExpandItem, typing.Sequence[FoldersListRequestExpandItem]]
+ ] = None,
+ include_deleted_data: typing.Optional[bool] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ modified_after: typing.Optional[dt.datetime] = None,
+ modified_before: typing.Optional[dt.datetime] = None,
+ name: typing.Optional[str] = None,
+ page_size: typing.Optional[int] = None,
+ remote_id: typing.Optional[str] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> PaginatedFolderList:
+ """
+ Returns a list of `Folder` objects.
+
+ Parameters
+ ----------
+ created_after : typing.Optional[dt.datetime]
+ If provided, will only return objects created after this datetime.
+
+ created_before : typing.Optional[dt.datetime]
+ If provided, will only return objects created before this datetime.
+
+ cursor : typing.Optional[str]
+ The pagination cursor value.
+
+ expand : typing.Optional[typing.Union[FoldersListRequestExpandItem, typing.Sequence[FoldersListRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ include_deleted_data : typing.Optional[bool]
+ Indicates whether or not this object has been deleted in the third party platform. Full coverage deletion detection is a premium add-on. Native deletion detection is offered for free with limited coverage. [Learn more](https://docs.merge.dev/integrations/hris/supported-features/).
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ modified_after : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge after this date time will be returned.
+
+ modified_before : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge before this date time will be returned.
+
+ name : typing.Optional[str]
+ If provided, will only return Folders with this name.
+
+ page_size : typing.Optional[int]
+ Number of results to return per page. The maximum limit is 100.
+
+ remote_id : typing.Optional[str]
+ The API provider's ID for the given object.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ PaginatedFolderList
+
+
+ Examples
+ --------
+ import datetime
+
+ from merge import Merge
+
+ client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+ client.email.folders.list(
+ created_after=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ created_before=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ cursor="cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw",
+ include_deleted_data=True,
+ include_remote_data=True,
+ include_shell_data=True,
+ modified_after=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ modified_before=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ name="name",
+ page_size=1,
+ remote_id="remote_id",
+ )
+ """
+ _response = self._raw_client.list(
+ created_after=created_after,
+ created_before=created_before,
+ cursor=cursor,
+ expand=expand,
+ include_deleted_data=include_deleted_data,
+ include_remote_data=include_remote_data,
+ include_shell_data=include_shell_data,
+ modified_after=modified_after,
+ modified_before=modified_before,
+ name=name,
+ page_size=page_size,
+ remote_id=remote_id,
+ request_options=request_options,
+ )
+ return _response.data
+
+ def retrieve(
+ self,
+ id: str,
+ *,
+ expand: typing.Optional[
+ typing.Union[FoldersRetrieveRequestExpandItem, typing.Sequence[FoldersRetrieveRequestExpandItem]]
+ ] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> Folder:
+ """
+ Returns a `Folder` object with the given `id`.
+
+ Parameters
+ ----------
+ id : str
+
+ expand : typing.Optional[typing.Union[FoldersRetrieveRequestExpandItem, typing.Sequence[FoldersRetrieveRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ Folder
+
+
+ Examples
+ --------
+ from merge import Merge
+
+ client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+ client.email.folders.retrieve(
+ id="id",
+ include_remote_data=True,
+ include_shell_data=True,
+ )
+ """
+ _response = self._raw_client.retrieve(
+ id,
+ expand=expand,
+ include_remote_data=include_remote_data,
+ include_shell_data=include_shell_data,
+ request_options=request_options,
+ )
+ return _response.data
+
+
+class AsyncFoldersClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._raw_client = AsyncRawFoldersClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> AsyncRawFoldersClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ AsyncRawFoldersClient
+ """
+ return self._raw_client
+
+ async def list(
+ self,
+ *,
+ created_after: typing.Optional[dt.datetime] = None,
+ created_before: typing.Optional[dt.datetime] = None,
+ cursor: typing.Optional[str] = None,
+ expand: typing.Optional[
+ typing.Union[FoldersListRequestExpandItem, typing.Sequence[FoldersListRequestExpandItem]]
+ ] = None,
+ include_deleted_data: typing.Optional[bool] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ modified_after: typing.Optional[dt.datetime] = None,
+ modified_before: typing.Optional[dt.datetime] = None,
+ name: typing.Optional[str] = None,
+ page_size: typing.Optional[int] = None,
+ remote_id: typing.Optional[str] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> PaginatedFolderList:
+ """
+ Returns a list of `Folder` objects.
+
+ Parameters
+ ----------
+ created_after : typing.Optional[dt.datetime]
+ If provided, will only return objects created after this datetime.
+
+ created_before : typing.Optional[dt.datetime]
+ If provided, will only return objects created before this datetime.
+
+ cursor : typing.Optional[str]
+ The pagination cursor value.
+
+ expand : typing.Optional[typing.Union[FoldersListRequestExpandItem, typing.Sequence[FoldersListRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ include_deleted_data : typing.Optional[bool]
+ Indicates whether or not this object has been deleted in the third party platform. Full coverage deletion detection is a premium add-on. Native deletion detection is offered for free with limited coverage. [Learn more](https://docs.merge.dev/integrations/hris/supported-features/).
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ modified_after : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge after this date time will be returned.
+
+ modified_before : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge before this date time will be returned.
+
+ name : typing.Optional[str]
+ If provided, will only return Folders with this name.
+
+ page_size : typing.Optional[int]
+ Number of results to return per page. The maximum limit is 100.
+
+ remote_id : typing.Optional[str]
+ The API provider's ID for the given object.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ PaginatedFolderList
+
+
+ Examples
+ --------
+ import asyncio
+ import datetime
+
+ from merge import AsyncMerge
+
+ client = AsyncMerge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.email.folders.list(
+ created_after=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ created_before=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ cursor="cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw",
+ include_deleted_data=True,
+ include_remote_data=True,
+ include_shell_data=True,
+ modified_after=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ modified_before=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ name="name",
+ page_size=1,
+ remote_id="remote_id",
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.list(
+ created_after=created_after,
+ created_before=created_before,
+ cursor=cursor,
+ expand=expand,
+ include_deleted_data=include_deleted_data,
+ include_remote_data=include_remote_data,
+ include_shell_data=include_shell_data,
+ modified_after=modified_after,
+ modified_before=modified_before,
+ name=name,
+ page_size=page_size,
+ remote_id=remote_id,
+ request_options=request_options,
+ )
+ return _response.data
+
+ async def retrieve(
+ self,
+ id: str,
+ *,
+ expand: typing.Optional[
+ typing.Union[FoldersRetrieveRequestExpandItem, typing.Sequence[FoldersRetrieveRequestExpandItem]]
+ ] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> Folder:
+ """
+ Returns a `Folder` object with the given `id`.
+
+ Parameters
+ ----------
+ id : str
+
+ expand : typing.Optional[typing.Union[FoldersRetrieveRequestExpandItem, typing.Sequence[FoldersRetrieveRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ Folder
+
+
+ Examples
+ --------
+ import asyncio
+
+ from merge import AsyncMerge
+
+ client = AsyncMerge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.email.folders.retrieve(
+ id="id",
+ include_remote_data=True,
+ include_shell_data=True,
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.retrieve(
+ id,
+ expand=expand,
+ include_remote_data=include_remote_data,
+ include_shell_data=include_shell_data,
+ request_options=request_options,
+ )
+ return _response.data
diff --git a/src/merge/resources/email/resources/folders/raw_client.py b/src/merge/resources/email/resources/folders/raw_client.py
new file mode 100644
index 00000000..aea22255
--- /dev/null
+++ b/src/merge/resources/email/resources/folders/raw_client.py
@@ -0,0 +1,351 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+from json.decoder import JSONDecodeError
+
+from .....core.api_error import ApiError
+from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .....core.datetime_utils import serialize_datetime
+from .....core.http_response import AsyncHttpResponse, HttpResponse
+from .....core.jsonable_encoder import jsonable_encoder
+from .....core.request_options import RequestOptions
+from .....core.unchecked_base_model import construct_type
+from ...types.folder import Folder
+from ...types.paginated_folder_list import PaginatedFolderList
+from .types.folders_list_request_expand_item import FoldersListRequestExpandItem
+from .types.folders_retrieve_request_expand_item import FoldersRetrieveRequestExpandItem
+
+
+class RawFoldersClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ def list(
+ self,
+ *,
+ created_after: typing.Optional[dt.datetime] = None,
+ created_before: typing.Optional[dt.datetime] = None,
+ cursor: typing.Optional[str] = None,
+ expand: typing.Optional[
+ typing.Union[FoldersListRequestExpandItem, typing.Sequence[FoldersListRequestExpandItem]]
+ ] = None,
+ include_deleted_data: typing.Optional[bool] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ modified_after: typing.Optional[dt.datetime] = None,
+ modified_before: typing.Optional[dt.datetime] = None,
+ name: typing.Optional[str] = None,
+ page_size: typing.Optional[int] = None,
+ remote_id: typing.Optional[str] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> HttpResponse[PaginatedFolderList]:
+ """
+ Returns a list of `Folder` objects.
+
+ Parameters
+ ----------
+ created_after : typing.Optional[dt.datetime]
+ If provided, will only return objects created after this datetime.
+
+ created_before : typing.Optional[dt.datetime]
+ If provided, will only return objects created before this datetime.
+
+ cursor : typing.Optional[str]
+ The pagination cursor value.
+
+ expand : typing.Optional[typing.Union[FoldersListRequestExpandItem, typing.Sequence[FoldersListRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ include_deleted_data : typing.Optional[bool]
+ Indicates whether or not this object has been deleted in the third party platform. Full coverage deletion detection is a premium add-on. Native deletion detection is offered for free with limited coverage. [Learn more](https://docs.merge.dev/integrations/hris/supported-features/).
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ modified_after : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge after this date time will be returned.
+
+ modified_before : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge before this date time will be returned.
+
+ name : typing.Optional[str]
+ If provided, will only return Folders with this name.
+
+ page_size : typing.Optional[int]
+ Number of results to return per page. The maximum limit is 100.
+
+ remote_id : typing.Optional[str]
+ The API provider's ID for the given object.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[PaginatedFolderList]
+
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ "email/v1/folders",
+ method="GET",
+ params={
+ "created_after": serialize_datetime(created_after) if created_after is not None else None,
+ "created_before": serialize_datetime(created_before) if created_before is not None else None,
+ "cursor": cursor,
+ "expand": expand,
+ "include_deleted_data": include_deleted_data,
+ "include_remote_data": include_remote_data,
+ "include_shell_data": include_shell_data,
+ "modified_after": serialize_datetime(modified_after) if modified_after is not None else None,
+ "modified_before": serialize_datetime(modified_before) if modified_before is not None else None,
+ "name": name,
+ "page_size": page_size,
+ "remote_id": remote_id,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ PaginatedFolderList,
+ construct_type(
+ type_=PaginatedFolderList, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ def retrieve(
+ self,
+ id: str,
+ *,
+ expand: typing.Optional[
+ typing.Union[FoldersRetrieveRequestExpandItem, typing.Sequence[FoldersRetrieveRequestExpandItem]]
+ ] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> HttpResponse[Folder]:
+ """
+ Returns a `Folder` object with the given `id`.
+
+ Parameters
+ ----------
+ id : str
+
+ expand : typing.Optional[typing.Union[FoldersRetrieveRequestExpandItem, typing.Sequence[FoldersRetrieveRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[Folder]
+
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ f"email/v1/folders/{jsonable_encoder(id)}",
+ method="GET",
+ params={
+ "expand": expand,
+ "include_remote_data": include_remote_data,
+ "include_shell_data": include_shell_data,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ Folder,
+ construct_type(
+ type_=Folder, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+
+class AsyncRawFoldersClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ async def list(
+ self,
+ *,
+ created_after: typing.Optional[dt.datetime] = None,
+ created_before: typing.Optional[dt.datetime] = None,
+ cursor: typing.Optional[str] = None,
+ expand: typing.Optional[
+ typing.Union[FoldersListRequestExpandItem, typing.Sequence[FoldersListRequestExpandItem]]
+ ] = None,
+ include_deleted_data: typing.Optional[bool] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ modified_after: typing.Optional[dt.datetime] = None,
+ modified_before: typing.Optional[dt.datetime] = None,
+ name: typing.Optional[str] = None,
+ page_size: typing.Optional[int] = None,
+ remote_id: typing.Optional[str] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> AsyncHttpResponse[PaginatedFolderList]:
+ """
+ Returns a list of `Folder` objects.
+
+ Parameters
+ ----------
+ created_after : typing.Optional[dt.datetime]
+ If provided, will only return objects created after this datetime.
+
+ created_before : typing.Optional[dt.datetime]
+ If provided, will only return objects created before this datetime.
+
+ cursor : typing.Optional[str]
+ The pagination cursor value.
+
+ expand : typing.Optional[typing.Union[FoldersListRequestExpandItem, typing.Sequence[FoldersListRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ include_deleted_data : typing.Optional[bool]
+ Indicates whether or not this object has been deleted in the third party platform. Full coverage deletion detection is a premium add-on. Native deletion detection is offered for free with limited coverage. [Learn more](https://docs.merge.dev/integrations/hris/supported-features/).
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ modified_after : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge after this date time will be returned.
+
+ modified_before : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge before this date time will be returned.
+
+ name : typing.Optional[str]
+ If provided, will only return Folders with this name.
+
+ page_size : typing.Optional[int]
+ Number of results to return per page. The maximum limit is 100.
+
+ remote_id : typing.Optional[str]
+ The API provider's ID for the given object.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[PaginatedFolderList]
+
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ "email/v1/folders",
+ method="GET",
+ params={
+ "created_after": serialize_datetime(created_after) if created_after is not None else None,
+ "created_before": serialize_datetime(created_before) if created_before is not None else None,
+ "cursor": cursor,
+ "expand": expand,
+ "include_deleted_data": include_deleted_data,
+ "include_remote_data": include_remote_data,
+ "include_shell_data": include_shell_data,
+ "modified_after": serialize_datetime(modified_after) if modified_after is not None else None,
+ "modified_before": serialize_datetime(modified_before) if modified_before is not None else None,
+ "name": name,
+ "page_size": page_size,
+ "remote_id": remote_id,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ PaginatedFolderList,
+ construct_type(
+ type_=PaginatedFolderList, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ async def retrieve(
+ self,
+ id: str,
+ *,
+ expand: typing.Optional[
+ typing.Union[FoldersRetrieveRequestExpandItem, typing.Sequence[FoldersRetrieveRequestExpandItem]]
+ ] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> AsyncHttpResponse[Folder]:
+ """
+ Returns a `Folder` object with the given `id`.
+
+ Parameters
+ ----------
+ id : str
+
+ expand : typing.Optional[typing.Union[FoldersRetrieveRequestExpandItem, typing.Sequence[FoldersRetrieveRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[Folder]
+
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ f"email/v1/folders/{jsonable_encoder(id)}",
+ method="GET",
+ params={
+ "expand": expand,
+ "include_remote_data": include_remote_data,
+ "include_shell_data": include_shell_data,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ Folder,
+ construct_type(
+ type_=Folder, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
diff --git a/src/merge/resources/email/resources/folders/types/__init__.py b/src/merge/resources/email/resources/folders/types/__init__.py
new file mode 100644
index 00000000..064c3b61
--- /dev/null
+++ b/src/merge/resources/email/resources/folders/types/__init__.py
@@ -0,0 +1,36 @@
+# This file was auto-generated by Fern from our API Definition.
+
+# isort: skip_file
+
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .folders_list_request_expand_item import FoldersListRequestExpandItem
+ from .folders_retrieve_request_expand_item import FoldersRetrieveRequestExpandItem
+_dynamic_imports: typing.Dict[str, str] = {
+ "FoldersListRequestExpandItem": ".folders_list_request_expand_item",
+ "FoldersRetrieveRequestExpandItem": ".folders_retrieve_request_expand_item",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ result = getattr(module, attr_name)
+ return result
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
+
+__all__ = ["FoldersListRequestExpandItem", "FoldersRetrieveRequestExpandItem"]
diff --git a/src/merge/resources/email/resources/folders/types/folders_list_request_expand_item.py b/src/merge/resources/email/resources/folders/types/folders_list_request_expand_item.py
new file mode 100644
index 00000000..910989fe
--- /dev/null
+++ b/src/merge/resources/email/resources/folders/types/folders_list_request_expand_item.py
@@ -0,0 +1,25 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import enum
+import typing
+
+T_Result = typing.TypeVar("T_Result")
+
+
+class FoldersListRequestExpandItem(str, enum.Enum):
+ MAILBOXES = "mailboxes"
+ PARENT_FOLDER = "parent_folder"
+ PERMISSIONS = "permissions"
+
+ def visit(
+ self,
+ mailboxes: typing.Callable[[], T_Result],
+ parent_folder: typing.Callable[[], T_Result],
+ permissions: typing.Callable[[], T_Result],
+ ) -> T_Result:
+ if self is FoldersListRequestExpandItem.MAILBOXES:
+ return mailboxes()
+ if self is FoldersListRequestExpandItem.PARENT_FOLDER:
+ return parent_folder()
+ if self is FoldersListRequestExpandItem.PERMISSIONS:
+ return permissions()
diff --git a/src/merge/resources/email/resources/folders/types/folders_retrieve_request_expand_item.py b/src/merge/resources/email/resources/folders/types/folders_retrieve_request_expand_item.py
new file mode 100644
index 00000000..ee0b2375
--- /dev/null
+++ b/src/merge/resources/email/resources/folders/types/folders_retrieve_request_expand_item.py
@@ -0,0 +1,25 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import enum
+import typing
+
+T_Result = typing.TypeVar("T_Result")
+
+
+class FoldersRetrieveRequestExpandItem(str, enum.Enum):
+ MAILBOXES = "mailboxes"
+ PARENT_FOLDER = "parent_folder"
+ PERMISSIONS = "permissions"
+
+ def visit(
+ self,
+ mailboxes: typing.Callable[[], T_Result],
+ parent_folder: typing.Callable[[], T_Result],
+ permissions: typing.Callable[[], T_Result],
+ ) -> T_Result:
+ if self is FoldersRetrieveRequestExpandItem.MAILBOXES:
+ return mailboxes()
+ if self is FoldersRetrieveRequestExpandItem.PARENT_FOLDER:
+ return parent_folder()
+ if self is FoldersRetrieveRequestExpandItem.PERMISSIONS:
+ return permissions()
diff --git a/src/merge/resources/email/resources/force_resync/__init__.py b/src/merge/resources/email/resources/force_resync/__init__.py
new file mode 100644
index 00000000..5cde0202
--- /dev/null
+++ b/src/merge/resources/email/resources/force_resync/__init__.py
@@ -0,0 +1,4 @@
+# This file was auto-generated by Fern from our API Definition.
+
+# isort: skip_file
+
diff --git a/src/merge/resources/email/resources/force_resync/client.py b/src/merge/resources/email/resources/force_resync/client.py
new file mode 100644
index 00000000..43ee1ac7
--- /dev/null
+++ b/src/merge/resources/email/resources/force_resync/client.py
@@ -0,0 +1,106 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .....core.request_options import RequestOptions
+from ...types.sync_status import SyncStatus
+from .raw_client import AsyncRawForceResyncClient, RawForceResyncClient
+
+
+class ForceResyncClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._raw_client = RawForceResyncClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> RawForceResyncClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ RawForceResyncClient
+ """
+ return self._raw_client
+
+ def sync_status_resync_create(
+ self, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> typing.List[SyncStatus]:
+ """
+ Force re-sync of all models. This endpoint is available for monthly, quarterly, and highest sync frequency customers on the Professional or Enterprise plans. Doing so will consume a sync credit for the relevant linked account. Force re-syncs can also be triggered manually in the Merge Dashboard and is available for all customers.
+
+ Parameters
+ ----------
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ typing.List[SyncStatus]
+
+
+ Examples
+ --------
+ from merge import Merge
+
+ client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+ client.email.force_resync.sync_status_resync_create()
+ """
+ _response = self._raw_client.sync_status_resync_create(request_options=request_options)
+ return _response.data
+
+
+class AsyncForceResyncClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._raw_client = AsyncRawForceResyncClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> AsyncRawForceResyncClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ AsyncRawForceResyncClient
+ """
+ return self._raw_client
+
+ async def sync_status_resync_create(
+ self, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> typing.List[SyncStatus]:
+ """
+ Force re-sync of all models. This endpoint is available for monthly, quarterly, and highest sync frequency customers on the Professional or Enterprise plans. Doing so will consume a sync credit for the relevant linked account. Force re-syncs can also be triggered manually in the Merge Dashboard and is available for all customers.
+
+ Parameters
+ ----------
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ typing.List[SyncStatus]
+
+
+ Examples
+ --------
+ import asyncio
+
+ from merge import AsyncMerge
+
+ client = AsyncMerge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.email.force_resync.sync_status_resync_create()
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.sync_status_resync_create(request_options=request_options)
+ return _response.data
diff --git a/src/merge/resources/email/resources/force_resync/raw_client.py b/src/merge/resources/email/resources/force_resync/raw_client.py
new file mode 100644
index 00000000..4f83160a
--- /dev/null
+++ b/src/merge/resources/email/resources/force_resync/raw_client.py
@@ -0,0 +1,93 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+from json.decoder import JSONDecodeError
+
+from .....core.api_error import ApiError
+from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .....core.http_response import AsyncHttpResponse, HttpResponse
+from .....core.request_options import RequestOptions
+from .....core.unchecked_base_model import construct_type
+from ...types.sync_status import SyncStatus
+
+
+class RawForceResyncClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ def sync_status_resync_create(
+ self, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> HttpResponse[typing.List[SyncStatus]]:
+ """
+ Force re-sync of all models. This endpoint is available for monthly, quarterly, and highest sync frequency customers on the Professional or Enterprise plans. Doing so will consume a sync credit for the relevant linked account. Force re-syncs can also be triggered manually in the Merge Dashboard and is available for all customers.
+
+ Parameters
+ ----------
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[typing.List[SyncStatus]]
+
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ "email/v1/sync-status/resync",
+ method="POST",
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ typing.List[SyncStatus],
+ construct_type(
+ type_=typing.List[SyncStatus], # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+
+class AsyncRawForceResyncClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ async def sync_status_resync_create(
+ self, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> AsyncHttpResponse[typing.List[SyncStatus]]:
+ """
+ Force re-sync of all models. This endpoint is available for monthly, quarterly, and highest sync frequency customers on the Professional or Enterprise plans. Doing so will consume a sync credit for the relevant linked account. Force re-syncs can also be triggered manually in the Merge Dashboard and is available for all customers.
+
+ Parameters
+ ----------
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[typing.List[SyncStatus]]
+
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ "email/v1/sync-status/resync",
+ method="POST",
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ typing.List[SyncStatus],
+ construct_type(
+ type_=typing.List[SyncStatus], # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
diff --git a/src/merge/resources/email/resources/generate_key/__init__.py b/src/merge/resources/email/resources/generate_key/__init__.py
new file mode 100644
index 00000000..5cde0202
--- /dev/null
+++ b/src/merge/resources/email/resources/generate_key/__init__.py
@@ -0,0 +1,4 @@
+# This file was auto-generated by Fern from our API Definition.
+
+# isort: skip_file
+
diff --git a/src/merge/resources/email/resources/generate_key/client.py b/src/merge/resources/email/resources/generate_key/client.py
new file mode 100644
index 00000000..eefecb30
--- /dev/null
+++ b/src/merge/resources/email/resources/generate_key/client.py
@@ -0,0 +1,115 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .....core.request_options import RequestOptions
+from ...types.remote_key import RemoteKey
+from .raw_client import AsyncRawGenerateKeyClient, RawGenerateKeyClient
+
+# this is used as the default value for optional parameters
+OMIT = typing.cast(typing.Any, ...)
+
+
+class GenerateKeyClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._raw_client = RawGenerateKeyClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> RawGenerateKeyClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ RawGenerateKeyClient
+ """
+ return self._raw_client
+
+ def create(self, *, name: str, request_options: typing.Optional[RequestOptions] = None) -> RemoteKey:
+ """
+ Create a remote key.
+
+ Parameters
+ ----------
+ name : str
+ The name of the remote key
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ RemoteKey
+
+
+ Examples
+ --------
+ from merge import Merge
+
+ client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+ client.email.generate_key.create(
+ name="Remote Deployment Key 1",
+ )
+ """
+ _response = self._raw_client.create(name=name, request_options=request_options)
+ return _response.data
+
+
+class AsyncGenerateKeyClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._raw_client = AsyncRawGenerateKeyClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> AsyncRawGenerateKeyClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ AsyncRawGenerateKeyClient
+ """
+ return self._raw_client
+
+ async def create(self, *, name: str, request_options: typing.Optional[RequestOptions] = None) -> RemoteKey:
+ """
+ Create a remote key.
+
+ Parameters
+ ----------
+ name : str
+ The name of the remote key
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ RemoteKey
+
+
+ Examples
+ --------
+ import asyncio
+
+ from merge import AsyncMerge
+
+ client = AsyncMerge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.email.generate_key.create(
+ name="Remote Deployment Key 1",
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.create(name=name, request_options=request_options)
+ return _response.data
diff --git a/src/merge/resources/email/resources/generate_key/raw_client.py b/src/merge/resources/email/resources/generate_key/raw_client.py
new file mode 100644
index 00000000..3bb8c0a2
--- /dev/null
+++ b/src/merge/resources/email/resources/generate_key/raw_client.py
@@ -0,0 +1,114 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+from json.decoder import JSONDecodeError
+
+from .....core.api_error import ApiError
+from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .....core.http_response import AsyncHttpResponse, HttpResponse
+from .....core.request_options import RequestOptions
+from .....core.unchecked_base_model import construct_type
+from ...types.remote_key import RemoteKey
+
+# this is used as the default value for optional parameters
+OMIT = typing.cast(typing.Any, ...)
+
+
+class RawGenerateKeyClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ def create(self, *, name: str, request_options: typing.Optional[RequestOptions] = None) -> HttpResponse[RemoteKey]:
+ """
+ Create a remote key.
+
+ Parameters
+ ----------
+ name : str
+ The name of the remote key
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[RemoteKey]
+
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ "email/v1/generate-key",
+ method="POST",
+ json={
+ "name": name,
+ },
+ headers={
+ "content-type": "application/json",
+ },
+ request_options=request_options,
+ omit=OMIT,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ RemoteKey,
+ construct_type(
+ type_=RemoteKey, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+
+class AsyncRawGenerateKeyClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ async def create(
+ self, *, name: str, request_options: typing.Optional[RequestOptions] = None
+ ) -> AsyncHttpResponse[RemoteKey]:
+ """
+ Create a remote key.
+
+ Parameters
+ ----------
+ name : str
+ The name of the remote key
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[RemoteKey]
+
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ "email/v1/generate-key",
+ method="POST",
+ json={
+ "name": name,
+ },
+ headers={
+ "content-type": "application/json",
+ },
+ request_options=request_options,
+ omit=OMIT,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ RemoteKey,
+ construct_type(
+ type_=RemoteKey, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
diff --git a/src/merge/resources/email/resources/groups/__init__.py b/src/merge/resources/email/resources/groups/__init__.py
new file mode 100644
index 00000000..c42a8d2e
--- /dev/null
+++ b/src/merge/resources/email/resources/groups/__init__.py
@@ -0,0 +1,35 @@
+# This file was auto-generated by Fern from our API Definition.
+
+# isort: skip_file
+
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .types import GroupsListRequestExpandItem, GroupsRetrieveRequestExpandItem
+_dynamic_imports: typing.Dict[str, str] = {
+ "GroupsListRequestExpandItem": ".types",
+ "GroupsRetrieveRequestExpandItem": ".types",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ result = getattr(module, attr_name)
+ return result
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
+
+__all__ = ["GroupsListRequestExpandItem", "GroupsRetrieveRequestExpandItem"]
diff --git a/src/merge/resources/email/resources/groups/client.py b/src/merge/resources/email/resources/groups/client.py
new file mode 100644
index 00000000..85c71e98
--- /dev/null
+++ b/src/merge/resources/email/resources/groups/client.py
@@ -0,0 +1,409 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+
+from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .....core.request_options import RequestOptions
+from ...types.group import Group
+from ...types.paginated_group_list import PaginatedGroupList
+from .raw_client import AsyncRawGroupsClient, RawGroupsClient
+from .types.groups_list_request_expand_item import GroupsListRequestExpandItem
+from .types.groups_retrieve_request_expand_item import GroupsRetrieveRequestExpandItem
+
+
+class GroupsClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._raw_client = RawGroupsClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> RawGroupsClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ RawGroupsClient
+ """
+ return self._raw_client
+
+ def list(
+ self,
+ *,
+ created_after: typing.Optional[dt.datetime] = None,
+ created_before: typing.Optional[dt.datetime] = None,
+ cursor: typing.Optional[str] = None,
+ expand: typing.Optional[
+ typing.Union[GroupsListRequestExpandItem, typing.Sequence[GroupsListRequestExpandItem]]
+ ] = None,
+ include_deleted_data: typing.Optional[bool] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ modified_after: typing.Optional[dt.datetime] = None,
+ modified_before: typing.Optional[dt.datetime] = None,
+ page_size: typing.Optional[int] = None,
+ remote_id: typing.Optional[str] = None,
+ user_id: typing.Optional[str] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> PaginatedGroupList:
+ """
+ Returns a list of `Group` objects.
+
+ Parameters
+ ----------
+ created_after : typing.Optional[dt.datetime]
+ If provided, will only return objects created after this datetime.
+
+ created_before : typing.Optional[dt.datetime]
+ If provided, will only return objects created before this datetime.
+
+ cursor : typing.Optional[str]
+ The pagination cursor value.
+
+ expand : typing.Optional[typing.Union[GroupsListRequestExpandItem, typing.Sequence[GroupsListRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ include_deleted_data : typing.Optional[bool]
+ Indicates whether or not this object has been deleted in the third party platform. Full coverage deletion detection is a premium add-on. Native deletion detection is offered for free with limited coverage. [Learn more](https://docs.merge.dev/integrations/hris/supported-features/).
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ modified_after : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge after this date time will be returned.
+
+ modified_before : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge before this date time will be returned.
+
+ page_size : typing.Optional[int]
+ Number of results to return per page. The maximum limit is 100.
+
+ remote_id : typing.Optional[str]
+ The API provider's ID for the given object.
+
+ user_id : typing.Optional[str]
+ If provided, will only return Groups containing this User.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ PaginatedGroupList
+
+
+ Examples
+ --------
+ import datetime
+
+ from merge import Merge
+
+ client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+ client.email.groups.list(
+ created_after=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ created_before=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ cursor="cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw",
+ include_deleted_data=True,
+ include_remote_data=True,
+ include_shell_data=True,
+ modified_after=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ modified_before=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ page_size=1,
+ remote_id="remote_id",
+ user_id="user_id",
+ )
+ """
+ _response = self._raw_client.list(
+ created_after=created_after,
+ created_before=created_before,
+ cursor=cursor,
+ expand=expand,
+ include_deleted_data=include_deleted_data,
+ include_remote_data=include_remote_data,
+ include_shell_data=include_shell_data,
+ modified_after=modified_after,
+ modified_before=modified_before,
+ page_size=page_size,
+ remote_id=remote_id,
+ user_id=user_id,
+ request_options=request_options,
+ )
+ return _response.data
+
+ def retrieve(
+ self,
+ id: str,
+ *,
+ expand: typing.Optional[
+ typing.Union[GroupsRetrieveRequestExpandItem, typing.Sequence[GroupsRetrieveRequestExpandItem]]
+ ] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> Group:
+ """
+ Returns a `Group` object with the given `id`.
+
+ Parameters
+ ----------
+ id : str
+
+ expand : typing.Optional[typing.Union[GroupsRetrieveRequestExpandItem, typing.Sequence[GroupsRetrieveRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ Group
+
+
+ Examples
+ --------
+ from merge import Merge
+
+ client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+ client.email.groups.retrieve(
+ id="id",
+ include_remote_data=True,
+ include_shell_data=True,
+ )
+ """
+ _response = self._raw_client.retrieve(
+ id,
+ expand=expand,
+ include_remote_data=include_remote_data,
+ include_shell_data=include_shell_data,
+ request_options=request_options,
+ )
+ return _response.data
+
+
+class AsyncGroupsClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._raw_client = AsyncRawGroupsClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> AsyncRawGroupsClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ AsyncRawGroupsClient
+ """
+ return self._raw_client
+
+ async def list(
+ self,
+ *,
+ created_after: typing.Optional[dt.datetime] = None,
+ created_before: typing.Optional[dt.datetime] = None,
+ cursor: typing.Optional[str] = None,
+ expand: typing.Optional[
+ typing.Union[GroupsListRequestExpandItem, typing.Sequence[GroupsListRequestExpandItem]]
+ ] = None,
+ include_deleted_data: typing.Optional[bool] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ modified_after: typing.Optional[dt.datetime] = None,
+ modified_before: typing.Optional[dt.datetime] = None,
+ page_size: typing.Optional[int] = None,
+ remote_id: typing.Optional[str] = None,
+ user_id: typing.Optional[str] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> PaginatedGroupList:
+ """
+ Returns a list of `Group` objects.
+
+ Parameters
+ ----------
+ created_after : typing.Optional[dt.datetime]
+ If provided, will only return objects created after this datetime.
+
+ created_before : typing.Optional[dt.datetime]
+ If provided, will only return objects created before this datetime.
+
+ cursor : typing.Optional[str]
+ The pagination cursor value.
+
+ expand : typing.Optional[typing.Union[GroupsListRequestExpandItem, typing.Sequence[GroupsListRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ include_deleted_data : typing.Optional[bool]
+ Indicates whether or not this object has been deleted in the third party platform. Full coverage deletion detection is a premium add-on. Native deletion detection is offered for free with limited coverage. [Learn more](https://docs.merge.dev/integrations/hris/supported-features/).
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ modified_after : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge after this date time will be returned.
+
+ modified_before : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge before this date time will be returned.
+
+ page_size : typing.Optional[int]
+ Number of results to return per page. The maximum limit is 100.
+
+ remote_id : typing.Optional[str]
+ The API provider's ID for the given object.
+
+ user_id : typing.Optional[str]
+ If provided, will only return Groups containing this User.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ PaginatedGroupList
+
+
+ Examples
+ --------
+ import asyncio
+ import datetime
+
+ from merge import AsyncMerge
+
+ client = AsyncMerge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.email.groups.list(
+ created_after=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ created_before=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ cursor="cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw",
+ include_deleted_data=True,
+ include_remote_data=True,
+ include_shell_data=True,
+ modified_after=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ modified_before=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ page_size=1,
+ remote_id="remote_id",
+ user_id="user_id",
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.list(
+ created_after=created_after,
+ created_before=created_before,
+ cursor=cursor,
+ expand=expand,
+ include_deleted_data=include_deleted_data,
+ include_remote_data=include_remote_data,
+ include_shell_data=include_shell_data,
+ modified_after=modified_after,
+ modified_before=modified_before,
+ page_size=page_size,
+ remote_id=remote_id,
+ user_id=user_id,
+ request_options=request_options,
+ )
+ return _response.data
+
+ async def retrieve(
+ self,
+ id: str,
+ *,
+ expand: typing.Optional[
+ typing.Union[GroupsRetrieveRequestExpandItem, typing.Sequence[GroupsRetrieveRequestExpandItem]]
+ ] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> Group:
+ """
+ Returns a `Group` object with the given `id`.
+
+ Parameters
+ ----------
+ id : str
+
+ expand : typing.Optional[typing.Union[GroupsRetrieveRequestExpandItem, typing.Sequence[GroupsRetrieveRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ Group
+
+
+ Examples
+ --------
+ import asyncio
+
+ from merge import AsyncMerge
+
+ client = AsyncMerge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.email.groups.retrieve(
+ id="id",
+ include_remote_data=True,
+ include_shell_data=True,
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.retrieve(
+ id,
+ expand=expand,
+ include_remote_data=include_remote_data,
+ include_shell_data=include_shell_data,
+ request_options=request_options,
+ )
+ return _response.data
diff --git a/src/merge/resources/email/resources/groups/raw_client.py b/src/merge/resources/email/resources/groups/raw_client.py
new file mode 100644
index 00000000..c9d2e089
--- /dev/null
+++ b/src/merge/resources/email/resources/groups/raw_client.py
@@ -0,0 +1,351 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+from json.decoder import JSONDecodeError
+
+from .....core.api_error import ApiError
+from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .....core.datetime_utils import serialize_datetime
+from .....core.http_response import AsyncHttpResponse, HttpResponse
+from .....core.jsonable_encoder import jsonable_encoder
+from .....core.request_options import RequestOptions
+from .....core.unchecked_base_model import construct_type
+from ...types.group import Group
+from ...types.paginated_group_list import PaginatedGroupList
+from .types.groups_list_request_expand_item import GroupsListRequestExpandItem
+from .types.groups_retrieve_request_expand_item import GroupsRetrieveRequestExpandItem
+
+
+class RawGroupsClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ def list(
+ self,
+ *,
+ created_after: typing.Optional[dt.datetime] = None,
+ created_before: typing.Optional[dt.datetime] = None,
+ cursor: typing.Optional[str] = None,
+ expand: typing.Optional[
+ typing.Union[GroupsListRequestExpandItem, typing.Sequence[GroupsListRequestExpandItem]]
+ ] = None,
+ include_deleted_data: typing.Optional[bool] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ modified_after: typing.Optional[dt.datetime] = None,
+ modified_before: typing.Optional[dt.datetime] = None,
+ page_size: typing.Optional[int] = None,
+ remote_id: typing.Optional[str] = None,
+ user_id: typing.Optional[str] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> HttpResponse[PaginatedGroupList]:
+ """
+ Returns a list of `Group` objects.
+
+ Parameters
+ ----------
+ created_after : typing.Optional[dt.datetime]
+ If provided, will only return objects created after this datetime.
+
+ created_before : typing.Optional[dt.datetime]
+ If provided, will only return objects created before this datetime.
+
+ cursor : typing.Optional[str]
+ The pagination cursor value.
+
+ expand : typing.Optional[typing.Union[GroupsListRequestExpandItem, typing.Sequence[GroupsListRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ include_deleted_data : typing.Optional[bool]
+ Indicates whether or not this object has been deleted in the third party platform. Full coverage deletion detection is a premium add-on. Native deletion detection is offered for free with limited coverage. [Learn more](https://docs.merge.dev/integrations/hris/supported-features/).
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ modified_after : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge after this date time will be returned.
+
+ modified_before : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge before this date time will be returned.
+
+ page_size : typing.Optional[int]
+ Number of results to return per page. The maximum limit is 100.
+
+ remote_id : typing.Optional[str]
+ The API provider's ID for the given object.
+
+ user_id : typing.Optional[str]
+ If provided, will only return Groups containing this User.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[PaginatedGroupList]
+
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ "email/v1/groups",
+ method="GET",
+ params={
+ "created_after": serialize_datetime(created_after) if created_after is not None else None,
+ "created_before": serialize_datetime(created_before) if created_before is not None else None,
+ "cursor": cursor,
+ "expand": expand,
+ "include_deleted_data": include_deleted_data,
+ "include_remote_data": include_remote_data,
+ "include_shell_data": include_shell_data,
+ "modified_after": serialize_datetime(modified_after) if modified_after is not None else None,
+ "modified_before": serialize_datetime(modified_before) if modified_before is not None else None,
+ "page_size": page_size,
+ "remote_id": remote_id,
+ "user_id": user_id,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ PaginatedGroupList,
+ construct_type(
+ type_=PaginatedGroupList, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ def retrieve(
+ self,
+ id: str,
+ *,
+ expand: typing.Optional[
+ typing.Union[GroupsRetrieveRequestExpandItem, typing.Sequence[GroupsRetrieveRequestExpandItem]]
+ ] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> HttpResponse[Group]:
+ """
+ Returns a `Group` object with the given `id`.
+
+ Parameters
+ ----------
+ id : str
+
+ expand : typing.Optional[typing.Union[GroupsRetrieveRequestExpandItem, typing.Sequence[GroupsRetrieveRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[Group]
+
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ f"email/v1/groups/{jsonable_encoder(id)}",
+ method="GET",
+ params={
+ "expand": expand,
+ "include_remote_data": include_remote_data,
+ "include_shell_data": include_shell_data,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ Group,
+ construct_type(
+ type_=Group, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+
+class AsyncRawGroupsClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ async def list(
+ self,
+ *,
+ created_after: typing.Optional[dt.datetime] = None,
+ created_before: typing.Optional[dt.datetime] = None,
+ cursor: typing.Optional[str] = None,
+ expand: typing.Optional[
+ typing.Union[GroupsListRequestExpandItem, typing.Sequence[GroupsListRequestExpandItem]]
+ ] = None,
+ include_deleted_data: typing.Optional[bool] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ modified_after: typing.Optional[dt.datetime] = None,
+ modified_before: typing.Optional[dt.datetime] = None,
+ page_size: typing.Optional[int] = None,
+ remote_id: typing.Optional[str] = None,
+ user_id: typing.Optional[str] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> AsyncHttpResponse[PaginatedGroupList]:
+ """
+ Returns a list of `Group` objects.
+
+ Parameters
+ ----------
+ created_after : typing.Optional[dt.datetime]
+ If provided, will only return objects created after this datetime.
+
+ created_before : typing.Optional[dt.datetime]
+ If provided, will only return objects created before this datetime.
+
+ cursor : typing.Optional[str]
+ The pagination cursor value.
+
+ expand : typing.Optional[typing.Union[GroupsListRequestExpandItem, typing.Sequence[GroupsListRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ include_deleted_data : typing.Optional[bool]
+ Indicates whether or not this object has been deleted in the third party platform. Full coverage deletion detection is a premium add-on. Native deletion detection is offered for free with limited coverage. [Learn more](https://docs.merge.dev/integrations/hris/supported-features/).
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ modified_after : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge after this date time will be returned.
+
+ modified_before : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge before this date time will be returned.
+
+ page_size : typing.Optional[int]
+ Number of results to return per page. The maximum limit is 100.
+
+ remote_id : typing.Optional[str]
+ The API provider's ID for the given object.
+
+ user_id : typing.Optional[str]
+ If provided, will only return Groups containing this User.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[PaginatedGroupList]
+
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ "email/v1/groups",
+ method="GET",
+ params={
+ "created_after": serialize_datetime(created_after) if created_after is not None else None,
+ "created_before": serialize_datetime(created_before) if created_before is not None else None,
+ "cursor": cursor,
+ "expand": expand,
+ "include_deleted_data": include_deleted_data,
+ "include_remote_data": include_remote_data,
+ "include_shell_data": include_shell_data,
+ "modified_after": serialize_datetime(modified_after) if modified_after is not None else None,
+ "modified_before": serialize_datetime(modified_before) if modified_before is not None else None,
+ "page_size": page_size,
+ "remote_id": remote_id,
+ "user_id": user_id,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ PaginatedGroupList,
+ construct_type(
+ type_=PaginatedGroupList, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ async def retrieve(
+ self,
+ id: str,
+ *,
+ expand: typing.Optional[
+ typing.Union[GroupsRetrieveRequestExpandItem, typing.Sequence[GroupsRetrieveRequestExpandItem]]
+ ] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> AsyncHttpResponse[Group]:
+ """
+ Returns a `Group` object with the given `id`.
+
+ Parameters
+ ----------
+ id : str
+
+ expand : typing.Optional[typing.Union[GroupsRetrieveRequestExpandItem, typing.Sequence[GroupsRetrieveRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[Group]
+
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ f"email/v1/groups/{jsonable_encoder(id)}",
+ method="GET",
+ params={
+ "expand": expand,
+ "include_remote_data": include_remote_data,
+ "include_shell_data": include_shell_data,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ Group,
+ construct_type(
+ type_=Group, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
diff --git a/src/merge/resources/email/resources/groups/types/__init__.py b/src/merge/resources/email/resources/groups/types/__init__.py
new file mode 100644
index 00000000..9f5d7290
--- /dev/null
+++ b/src/merge/resources/email/resources/groups/types/__init__.py
@@ -0,0 +1,36 @@
+# This file was auto-generated by Fern from our API Definition.
+
+# isort: skip_file
+
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .groups_list_request_expand_item import GroupsListRequestExpandItem
+ from .groups_retrieve_request_expand_item import GroupsRetrieveRequestExpandItem
+_dynamic_imports: typing.Dict[str, str] = {
+ "GroupsListRequestExpandItem": ".groups_list_request_expand_item",
+ "GroupsRetrieveRequestExpandItem": ".groups_retrieve_request_expand_item",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ result = getattr(module, attr_name)
+ return result
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
+
+__all__ = ["GroupsListRequestExpandItem", "GroupsRetrieveRequestExpandItem"]
diff --git a/src/merge/resources/email/resources/groups/types/groups_list_request_expand_item.py b/src/merge/resources/email/resources/groups/types/groups_list_request_expand_item.py
new file mode 100644
index 00000000..cf07a4eb
--- /dev/null
+++ b/src/merge/resources/email/resources/groups/types/groups_list_request_expand_item.py
@@ -0,0 +1,25 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import enum
+import typing
+
+T_Result = typing.TypeVar("T_Result")
+
+
+class GroupsListRequestExpandItem(str, enum.Enum):
+ EMAIL_ADDRESSES = "email_addresses"
+ MAILBOXES = "mailboxes"
+ USERS = "users"
+
+ def visit(
+ self,
+ email_addresses: typing.Callable[[], T_Result],
+ mailboxes: typing.Callable[[], T_Result],
+ users: typing.Callable[[], T_Result],
+ ) -> T_Result:
+ if self is GroupsListRequestExpandItem.EMAIL_ADDRESSES:
+ return email_addresses()
+ if self is GroupsListRequestExpandItem.MAILBOXES:
+ return mailboxes()
+ if self is GroupsListRequestExpandItem.USERS:
+ return users()
diff --git a/src/merge/resources/email/resources/groups/types/groups_retrieve_request_expand_item.py b/src/merge/resources/email/resources/groups/types/groups_retrieve_request_expand_item.py
new file mode 100644
index 00000000..f1536887
--- /dev/null
+++ b/src/merge/resources/email/resources/groups/types/groups_retrieve_request_expand_item.py
@@ -0,0 +1,25 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import enum
+import typing
+
+T_Result = typing.TypeVar("T_Result")
+
+
+class GroupsRetrieveRequestExpandItem(str, enum.Enum):
+ EMAIL_ADDRESSES = "email_addresses"
+ MAILBOXES = "mailboxes"
+ USERS = "users"
+
+ def visit(
+ self,
+ email_addresses: typing.Callable[[], T_Result],
+ mailboxes: typing.Callable[[], T_Result],
+ users: typing.Callable[[], T_Result],
+ ) -> T_Result:
+ if self is GroupsRetrieveRequestExpandItem.EMAIL_ADDRESSES:
+ return email_addresses()
+ if self is GroupsRetrieveRequestExpandItem.MAILBOXES:
+ return mailboxes()
+ if self is GroupsRetrieveRequestExpandItem.USERS:
+ return users()
diff --git a/src/merge/resources/email/resources/issues/__init__.py b/src/merge/resources/email/resources/issues/__init__.py
new file mode 100644
index 00000000..3ca1094b
--- /dev/null
+++ b/src/merge/resources/email/resources/issues/__init__.py
@@ -0,0 +1,32 @@
+# This file was auto-generated by Fern from our API Definition.
+
+# isort: skip_file
+
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .types import IssuesListRequestStatus
+_dynamic_imports: typing.Dict[str, str] = {"IssuesListRequestStatus": ".types"}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ result = getattr(module, attr_name)
+ return result
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
+
+__all__ = ["IssuesListRequestStatus"]
diff --git a/src/merge/resources/email/resources/issues/client.py b/src/merge/resources/email/resources/issues/client.py
new file mode 100644
index 00000000..8b66a433
--- /dev/null
+++ b/src/merge/resources/email/resources/issues/client.py
@@ -0,0 +1,372 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+
+from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .....core.request_options import RequestOptions
+from ...types.issue import Issue
+from ...types.paginated_issue_list import PaginatedIssueList
+from .raw_client import AsyncRawIssuesClient, RawIssuesClient
+from .types.issues_list_request_status import IssuesListRequestStatus
+
+
+class IssuesClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._raw_client = RawIssuesClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> RawIssuesClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ RawIssuesClient
+ """
+ return self._raw_client
+
+ def list(
+ self,
+ *,
+ account_token: typing.Optional[str] = None,
+ cursor: typing.Optional[str] = None,
+ end_date: typing.Optional[str] = None,
+ end_user_organization_name: typing.Optional[str] = None,
+ first_incident_time_after: typing.Optional[dt.datetime] = None,
+ first_incident_time_before: typing.Optional[dt.datetime] = None,
+ include_muted: typing.Optional[str] = None,
+ integration_name: typing.Optional[str] = None,
+ last_incident_time_after: typing.Optional[dt.datetime] = None,
+ last_incident_time_before: typing.Optional[dt.datetime] = None,
+ linked_account_id: typing.Optional[str] = None,
+ page_size: typing.Optional[int] = None,
+ start_date: typing.Optional[str] = None,
+ status: typing.Optional[IssuesListRequestStatus] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> PaginatedIssueList:
+ """
+ Gets all issues for Organization.
+
+ Parameters
+ ----------
+ account_token : typing.Optional[str]
+
+ cursor : typing.Optional[str]
+ The pagination cursor value.
+
+ end_date : typing.Optional[str]
+ If included, will only include issues whose most recent action occurred before this time
+
+ end_user_organization_name : typing.Optional[str]
+
+ first_incident_time_after : typing.Optional[dt.datetime]
+ If provided, will only return issues whose first incident time was after this datetime.
+
+ first_incident_time_before : typing.Optional[dt.datetime]
+ If provided, will only return issues whose first incident time was before this datetime.
+
+ include_muted : typing.Optional[str]
+ If true, will include muted issues
+
+ integration_name : typing.Optional[str]
+
+ last_incident_time_after : typing.Optional[dt.datetime]
+ If provided, will only return issues whose last incident time was after this datetime.
+
+ last_incident_time_before : typing.Optional[dt.datetime]
+ If provided, will only return issues whose last incident time was before this datetime.
+
+ linked_account_id : typing.Optional[str]
+ If provided, will only include issues pertaining to the linked account passed in.
+
+ page_size : typing.Optional[int]
+ Number of results to return per page. The maximum limit is 100.
+
+ start_date : typing.Optional[str]
+ If included, will only include issues whose most recent action occurred after this time
+
+ status : typing.Optional[IssuesListRequestStatus]
+ Status of the issue.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ PaginatedIssueList
+
+
+ Examples
+ --------
+ import datetime
+
+ from merge import Merge
+ from merge.resources.email.resources.issues import IssuesListRequestStatus
+
+ client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+ client.email.issues.list(
+ account_token="account_token",
+ cursor="cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw",
+ end_date="end_date",
+ end_user_organization_name="end_user_organization_name",
+ first_incident_time_after=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ first_incident_time_before=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ include_muted="include_muted",
+ integration_name="integration_name",
+ last_incident_time_after=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ last_incident_time_before=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ linked_account_id="linked_account_id",
+ page_size=1,
+ start_date="start_date",
+ status=IssuesListRequestStatus.ONGOING,
+ )
+ """
+ _response = self._raw_client.list(
+ account_token=account_token,
+ cursor=cursor,
+ end_date=end_date,
+ end_user_organization_name=end_user_organization_name,
+ first_incident_time_after=first_incident_time_after,
+ first_incident_time_before=first_incident_time_before,
+ include_muted=include_muted,
+ integration_name=integration_name,
+ last_incident_time_after=last_incident_time_after,
+ last_incident_time_before=last_incident_time_before,
+ linked_account_id=linked_account_id,
+ page_size=page_size,
+ start_date=start_date,
+ status=status,
+ request_options=request_options,
+ )
+ return _response.data
+
+ def retrieve(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Issue:
+ """
+ Get a specific issue.
+
+ Parameters
+ ----------
+ id : str
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ Issue
+
+
+ Examples
+ --------
+ from merge import Merge
+
+ client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+ client.email.issues.retrieve(
+ id="id",
+ )
+ """
+ _response = self._raw_client.retrieve(id, request_options=request_options)
+ return _response.data
+
+
+class AsyncIssuesClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._raw_client = AsyncRawIssuesClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> AsyncRawIssuesClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ AsyncRawIssuesClient
+ """
+ return self._raw_client
+
+ async def list(
+ self,
+ *,
+ account_token: typing.Optional[str] = None,
+ cursor: typing.Optional[str] = None,
+ end_date: typing.Optional[str] = None,
+ end_user_organization_name: typing.Optional[str] = None,
+ first_incident_time_after: typing.Optional[dt.datetime] = None,
+ first_incident_time_before: typing.Optional[dt.datetime] = None,
+ include_muted: typing.Optional[str] = None,
+ integration_name: typing.Optional[str] = None,
+ last_incident_time_after: typing.Optional[dt.datetime] = None,
+ last_incident_time_before: typing.Optional[dt.datetime] = None,
+ linked_account_id: typing.Optional[str] = None,
+ page_size: typing.Optional[int] = None,
+ start_date: typing.Optional[str] = None,
+ status: typing.Optional[IssuesListRequestStatus] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> PaginatedIssueList:
+ """
+ Gets all issues for Organization.
+
+ Parameters
+ ----------
+ account_token : typing.Optional[str]
+
+ cursor : typing.Optional[str]
+ The pagination cursor value.
+
+ end_date : typing.Optional[str]
+ If included, will only include issues whose most recent action occurred before this time
+
+ end_user_organization_name : typing.Optional[str]
+
+ first_incident_time_after : typing.Optional[dt.datetime]
+ If provided, will only return issues whose first incident time was after this datetime.
+
+ first_incident_time_before : typing.Optional[dt.datetime]
+ If provided, will only return issues whose first incident time was before this datetime.
+
+ include_muted : typing.Optional[str]
+ If true, will include muted issues
+
+ integration_name : typing.Optional[str]
+
+ last_incident_time_after : typing.Optional[dt.datetime]
+ If provided, will only return issues whose last incident time was after this datetime.
+
+ last_incident_time_before : typing.Optional[dt.datetime]
+ If provided, will only return issues whose last incident time was before this datetime.
+
+ linked_account_id : typing.Optional[str]
+ If provided, will only include issues pertaining to the linked account passed in.
+
+ page_size : typing.Optional[int]
+ Number of results to return per page. The maximum limit is 100.
+
+ start_date : typing.Optional[str]
+ If included, will only include issues whose most recent action occurred after this time
+
+ status : typing.Optional[IssuesListRequestStatus]
+ Status of the issue.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ PaginatedIssueList
+
+
+ Examples
+ --------
+ import asyncio
+ import datetime
+
+ from merge import AsyncMerge
+ from merge.resources.email.resources.issues import IssuesListRequestStatus
+
+ client = AsyncMerge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.email.issues.list(
+ account_token="account_token",
+ cursor="cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw",
+ end_date="end_date",
+ end_user_organization_name="end_user_organization_name",
+ first_incident_time_after=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ first_incident_time_before=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ include_muted="include_muted",
+ integration_name="integration_name",
+ last_incident_time_after=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ last_incident_time_before=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ linked_account_id="linked_account_id",
+ page_size=1,
+ start_date="start_date",
+ status=IssuesListRequestStatus.ONGOING,
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.list(
+ account_token=account_token,
+ cursor=cursor,
+ end_date=end_date,
+ end_user_organization_name=end_user_organization_name,
+ first_incident_time_after=first_incident_time_after,
+ first_incident_time_before=first_incident_time_before,
+ include_muted=include_muted,
+ integration_name=integration_name,
+ last_incident_time_after=last_incident_time_after,
+ last_incident_time_before=last_incident_time_before,
+ linked_account_id=linked_account_id,
+ page_size=page_size,
+ start_date=start_date,
+ status=status,
+ request_options=request_options,
+ )
+ return _response.data
+
+ async def retrieve(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Issue:
+ """
+ Get a specific issue.
+
+ Parameters
+ ----------
+ id : str
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ Issue
+
+
+ Examples
+ --------
+ import asyncio
+
+ from merge import AsyncMerge
+
+ client = AsyncMerge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.email.issues.retrieve(
+ id="id",
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.retrieve(id, request_options=request_options)
+ return _response.data
diff --git a/src/merge/resources/email/resources/issues/raw_client.py b/src/merge/resources/email/resources/issues/raw_client.py
new file mode 100644
index 00000000..d35888c2
--- /dev/null
+++ b/src/merge/resources/email/resources/issues/raw_client.py
@@ -0,0 +1,330 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+from json.decoder import JSONDecodeError
+
+from .....core.api_error import ApiError
+from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .....core.datetime_utils import serialize_datetime
+from .....core.http_response import AsyncHttpResponse, HttpResponse
+from .....core.jsonable_encoder import jsonable_encoder
+from .....core.request_options import RequestOptions
+from .....core.unchecked_base_model import construct_type
+from ...types.issue import Issue
+from ...types.paginated_issue_list import PaginatedIssueList
+from .types.issues_list_request_status import IssuesListRequestStatus
+
+
+class RawIssuesClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ def list(
+ self,
+ *,
+ account_token: typing.Optional[str] = None,
+ cursor: typing.Optional[str] = None,
+ end_date: typing.Optional[str] = None,
+ end_user_organization_name: typing.Optional[str] = None,
+ first_incident_time_after: typing.Optional[dt.datetime] = None,
+ first_incident_time_before: typing.Optional[dt.datetime] = None,
+ include_muted: typing.Optional[str] = None,
+ integration_name: typing.Optional[str] = None,
+ last_incident_time_after: typing.Optional[dt.datetime] = None,
+ last_incident_time_before: typing.Optional[dt.datetime] = None,
+ linked_account_id: typing.Optional[str] = None,
+ page_size: typing.Optional[int] = None,
+ start_date: typing.Optional[str] = None,
+ status: typing.Optional[IssuesListRequestStatus] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> HttpResponse[PaginatedIssueList]:
+ """
+ Gets all issues for Organization.
+
+ Parameters
+ ----------
+ account_token : typing.Optional[str]
+
+ cursor : typing.Optional[str]
+ The pagination cursor value.
+
+ end_date : typing.Optional[str]
+ If included, will only include issues whose most recent action occurred before this time
+
+ end_user_organization_name : typing.Optional[str]
+
+ first_incident_time_after : typing.Optional[dt.datetime]
+ If provided, will only return issues whose first incident time was after this datetime.
+
+ first_incident_time_before : typing.Optional[dt.datetime]
+ If provided, will only return issues whose first incident time was before this datetime.
+
+ include_muted : typing.Optional[str]
+ If true, will include muted issues
+
+ integration_name : typing.Optional[str]
+
+ last_incident_time_after : typing.Optional[dt.datetime]
+ If provided, will only return issues whose last incident time was after this datetime.
+
+ last_incident_time_before : typing.Optional[dt.datetime]
+ If provided, will only return issues whose last incident time was before this datetime.
+
+ linked_account_id : typing.Optional[str]
+ If provided, will only include issues pertaining to the linked account passed in.
+
+ page_size : typing.Optional[int]
+ Number of results to return per page. The maximum limit is 100.
+
+ start_date : typing.Optional[str]
+ If included, will only include issues whose most recent action occurred after this time
+
+ status : typing.Optional[IssuesListRequestStatus]
+ Status of the issue.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[PaginatedIssueList]
+
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ "email/v1/issues",
+ method="GET",
+ params={
+ "account_token": account_token,
+ "cursor": cursor,
+ "end_date": end_date,
+ "end_user_organization_name": end_user_organization_name,
+ "first_incident_time_after": serialize_datetime(first_incident_time_after)
+ if first_incident_time_after is not None
+ else None,
+ "first_incident_time_before": serialize_datetime(first_incident_time_before)
+ if first_incident_time_before is not None
+ else None,
+ "include_muted": include_muted,
+ "integration_name": integration_name,
+ "last_incident_time_after": serialize_datetime(last_incident_time_after)
+ if last_incident_time_after is not None
+ else None,
+ "last_incident_time_before": serialize_datetime(last_incident_time_before)
+ if last_incident_time_before is not None
+ else None,
+ "linked_account_id": linked_account_id,
+ "page_size": page_size,
+ "start_date": start_date,
+ "status": status,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ PaginatedIssueList,
+ construct_type(
+ type_=PaginatedIssueList, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ def retrieve(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> HttpResponse[Issue]:
+ """
+ Get a specific issue.
+
+ Parameters
+ ----------
+ id : str
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[Issue]
+
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ f"email/v1/issues/{jsonable_encoder(id)}",
+ method="GET",
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ Issue,
+ construct_type(
+ type_=Issue, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+
+class AsyncRawIssuesClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ async def list(
+ self,
+ *,
+ account_token: typing.Optional[str] = None,
+ cursor: typing.Optional[str] = None,
+ end_date: typing.Optional[str] = None,
+ end_user_organization_name: typing.Optional[str] = None,
+ first_incident_time_after: typing.Optional[dt.datetime] = None,
+ first_incident_time_before: typing.Optional[dt.datetime] = None,
+ include_muted: typing.Optional[str] = None,
+ integration_name: typing.Optional[str] = None,
+ last_incident_time_after: typing.Optional[dt.datetime] = None,
+ last_incident_time_before: typing.Optional[dt.datetime] = None,
+ linked_account_id: typing.Optional[str] = None,
+ page_size: typing.Optional[int] = None,
+ start_date: typing.Optional[str] = None,
+ status: typing.Optional[IssuesListRequestStatus] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> AsyncHttpResponse[PaginatedIssueList]:
+ """
+ Gets all issues for Organization.
+
+ Parameters
+ ----------
+ account_token : typing.Optional[str]
+
+ cursor : typing.Optional[str]
+ The pagination cursor value.
+
+ end_date : typing.Optional[str]
+ If included, will only include issues whose most recent action occurred before this time
+
+ end_user_organization_name : typing.Optional[str]
+
+ first_incident_time_after : typing.Optional[dt.datetime]
+ If provided, will only return issues whose first incident time was after this datetime.
+
+ first_incident_time_before : typing.Optional[dt.datetime]
+ If provided, will only return issues whose first incident time was before this datetime.
+
+ include_muted : typing.Optional[str]
+ If true, will include muted issues
+
+ integration_name : typing.Optional[str]
+
+ last_incident_time_after : typing.Optional[dt.datetime]
+ If provided, will only return issues whose last incident time was after this datetime.
+
+ last_incident_time_before : typing.Optional[dt.datetime]
+ If provided, will only return issues whose last incident time was before this datetime.
+
+ linked_account_id : typing.Optional[str]
+ If provided, will only include issues pertaining to the linked account passed in.
+
+ page_size : typing.Optional[int]
+ Number of results to return per page. The maximum limit is 100.
+
+ start_date : typing.Optional[str]
+ If included, will only include issues whose most recent action occurred after this time
+
+ status : typing.Optional[IssuesListRequestStatus]
+ Status of the issue.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[PaginatedIssueList]
+
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ "email/v1/issues",
+ method="GET",
+ params={
+ "account_token": account_token,
+ "cursor": cursor,
+ "end_date": end_date,
+ "end_user_organization_name": end_user_organization_name,
+ "first_incident_time_after": serialize_datetime(first_incident_time_after)
+ if first_incident_time_after is not None
+ else None,
+ "first_incident_time_before": serialize_datetime(first_incident_time_before)
+ if first_incident_time_before is not None
+ else None,
+ "include_muted": include_muted,
+ "integration_name": integration_name,
+ "last_incident_time_after": serialize_datetime(last_incident_time_after)
+ if last_incident_time_after is not None
+ else None,
+ "last_incident_time_before": serialize_datetime(last_incident_time_before)
+ if last_incident_time_before is not None
+ else None,
+ "linked_account_id": linked_account_id,
+ "page_size": page_size,
+ "start_date": start_date,
+ "status": status,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ PaginatedIssueList,
+ construct_type(
+ type_=PaginatedIssueList, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ async def retrieve(
+ self, id: str, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> AsyncHttpResponse[Issue]:
+ """
+ Get a specific issue.
+
+ Parameters
+ ----------
+ id : str
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[Issue]
+
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ f"email/v1/issues/{jsonable_encoder(id)}",
+ method="GET",
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ Issue,
+ construct_type(
+ type_=Issue, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
diff --git a/src/merge/resources/email/resources/issues/types/__init__.py b/src/merge/resources/email/resources/issues/types/__init__.py
new file mode 100644
index 00000000..88fbf977
--- /dev/null
+++ b/src/merge/resources/email/resources/issues/types/__init__.py
@@ -0,0 +1,32 @@
+# This file was auto-generated by Fern from our API Definition.
+
+# isort: skip_file
+
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .issues_list_request_status import IssuesListRequestStatus
+_dynamic_imports: typing.Dict[str, str] = {"IssuesListRequestStatus": ".issues_list_request_status"}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ result = getattr(module, attr_name)
+ return result
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
+
+__all__ = ["IssuesListRequestStatus"]
diff --git a/src/merge/resources/email/resources/issues/types/issues_list_request_status.py b/src/merge/resources/email/resources/issues/types/issues_list_request_status.py
new file mode 100644
index 00000000..2bd3521e
--- /dev/null
+++ b/src/merge/resources/email/resources/issues/types/issues_list_request_status.py
@@ -0,0 +1,17 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import enum
+import typing
+
+T_Result = typing.TypeVar("T_Result")
+
+
+class IssuesListRequestStatus(str, enum.Enum):
+ ONGOING = "ONGOING"
+ RESOLVED = "RESOLVED"
+
+ def visit(self, ongoing: typing.Callable[[], T_Result], resolved: typing.Callable[[], T_Result]) -> T_Result:
+ if self is IssuesListRequestStatus.ONGOING:
+ return ongoing()
+ if self is IssuesListRequestStatus.RESOLVED:
+ return resolved()
diff --git a/src/merge/resources/email/resources/link_token/__init__.py b/src/merge/resources/email/resources/link_token/__init__.py
new file mode 100644
index 00000000..be8c3839
--- /dev/null
+++ b/src/merge/resources/email/resources/link_token/__init__.py
@@ -0,0 +1,35 @@
+# This file was auto-generated by Fern from our API Definition.
+
+# isort: skip_file
+
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .types import EndUserDetailsRequestCompletedAccountInitialScreen, EndUserDetailsRequestLanguage
+_dynamic_imports: typing.Dict[str, str] = {
+ "EndUserDetailsRequestCompletedAccountInitialScreen": ".types",
+ "EndUserDetailsRequestLanguage": ".types",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ result = getattr(module, attr_name)
+ return result
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
+
+__all__ = ["EndUserDetailsRequestCompletedAccountInitialScreen", "EndUserDetailsRequestLanguage"]
diff --git a/src/merge/resources/email/resources/link_token/client.py b/src/merge/resources/email/resources/link_token/client.py
new file mode 100644
index 00000000..a75b309d
--- /dev/null
+++ b/src/merge/resources/email/resources/link_token/client.py
@@ -0,0 +1,310 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .....core.request_options import RequestOptions
+from ...types.categories_enum import CategoriesEnum
+from ...types.common_model_scopes_body_request import CommonModelScopesBodyRequest
+from ...types.individual_common_model_scope_deserializer_request import IndividualCommonModelScopeDeserializerRequest
+from ...types.link_token import LinkToken
+from .raw_client import AsyncRawLinkTokenClient, RawLinkTokenClient
+from .types.end_user_details_request_completed_account_initial_screen import (
+ EndUserDetailsRequestCompletedAccountInitialScreen,
+)
+from .types.end_user_details_request_language import EndUserDetailsRequestLanguage
+
+# this is used as the default value for optional parameters
+OMIT = typing.cast(typing.Any, ...)
+
+
+class LinkTokenClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._raw_client = RawLinkTokenClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> RawLinkTokenClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ RawLinkTokenClient
+ """
+ return self._raw_client
+
+ def create(
+ self,
+ *,
+ end_user_email_address: str,
+ end_user_organization_name: str,
+ end_user_origin_id: str,
+ categories: typing.Sequence[CategoriesEnum],
+ integration: typing.Optional[str] = OMIT,
+ link_expiry_mins: typing.Optional[int] = OMIT,
+ should_create_magic_link_url: typing.Optional[bool] = OMIT,
+ hide_admin_magic_link: typing.Optional[bool] = OMIT,
+ common_models: typing.Optional[typing.Sequence[CommonModelScopesBodyRequest]] = OMIT,
+ category_common_model_scopes: typing.Optional[
+ typing.Dict[str, typing.Optional[typing.Sequence[IndividualCommonModelScopeDeserializerRequest]]]
+ ] = OMIT,
+ language: typing.Optional[EndUserDetailsRequestLanguage] = OMIT,
+ are_syncs_disabled: typing.Optional[bool] = OMIT,
+ integration_specific_config: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
+ completed_account_initial_screen: typing.Optional[EndUserDetailsRequestCompletedAccountInitialScreen] = OMIT,
+ linked_destination_id: typing.Optional[str] = OMIT,
+ credential_id: typing.Optional[str] = OMIT,
+ ekm_enabled: typing.Optional[bool] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> LinkToken:
+ """
+ Creates a link token to be used when linking a new end user. The link token expires after single use.
+
+ Parameters
+ ----------
+ end_user_email_address : str
+ Your end user's email address. This is purely for identification purposes - setting this value will not cause any emails to be sent.
+
+ end_user_organization_name : str
+ Your end user's organization.
+
+ end_user_origin_id : str
+ This unique identifier typically represents the ID for your end user in your product's database. This value must be distinct from other Linked Accounts' unique identifiers.
+
+ categories : typing.Sequence[CategoriesEnum]
+ The integration categories to show in Merge Link.
+
+ integration : typing.Optional[str]
+ The slug of a specific pre-selected integration for this linking flow token. For examples of slugs, see https://docs.merge.dev/guides/merge-link/single-integration/.
+
+ link_expiry_mins : typing.Optional[int]
+ An integer number of minutes between [30, 720 or 10080 if for a Magic Link URL] for how long this token is valid. Defaults to 30.
+
+ should_create_magic_link_url : typing.Optional[bool]
+ Whether to generate a Magic Link URL. Defaults to false. For more information on Magic Link, see https://merge.dev/blog/integrations-fast-say-hello-to-magic-link.
+
+ hide_admin_magic_link : typing.Optional[bool]
+ Whether to generate a Magic Link URL on the Admin Needed screen during the linking flow. Defaults to false. For more information on Magic Link, see https://merge.dev/blog/integrations-fast-say-hello-to-magic-link.
+
+ common_models : typing.Optional[typing.Sequence[CommonModelScopesBodyRequest]]
+ An array of objects to specify the models and fields that will be disabled for a given Linked Account. Each object uses model_id, enabled_actions, and disabled_fields to specify the model, method, and fields that are scoped for a given Linked Account.
+
+ category_common_model_scopes : typing.Optional[typing.Dict[str, typing.Optional[typing.Sequence[IndividualCommonModelScopeDeserializerRequest]]]]
+ When creating a Link Token, you can set permissions for Common Models that will apply to the account that is going to be linked. Any model or field not specified in link token payload will default to existing settings.
+
+ language : typing.Optional[EndUserDetailsRequestLanguage]
+ The following subset of IETF language tags can be used to configure localization.
+
+ are_syncs_disabled : typing.Optional[bool]
+ The boolean that indicates whether initial, periodic, and force syncs will be disabled.
+
+ integration_specific_config : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
+ A JSON object containing integration-specific configuration options.
+
+ completed_account_initial_screen : typing.Optional[EndUserDetailsRequestCompletedAccountInitialScreen]
+ When creating a Link token, you can specifiy the initial screen of Linking Flow for a completed Linked Account.
+
+ linked_destination_id : typing.Optional[str]
+ The UUID of the linked destination that you want this Linked Account to be tied to.
+
+ credential_id : typing.Optional[str]
+ The id of the credential that you want this Linked Account to be tied to.
+
+ ekm_enabled : typing.Optional[bool]
+ Whether to enable EKM (External Key Management) for this Linked Account.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ LinkToken
+
+
+ Examples
+ --------
+ from merge import Merge
+ from merge.resources.email import CategoriesEnum
+
+ client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+ client.email.link_token.create(
+ end_user_email_address="example@gmail.com",
+ end_user_organization_name="Test Organization",
+ end_user_origin_id="12345",
+ categories=[CategoriesEnum.HRIS, CategoriesEnum.ATS],
+ )
+ """
+ _response = self._raw_client.create(
+ end_user_email_address=end_user_email_address,
+ end_user_organization_name=end_user_organization_name,
+ end_user_origin_id=end_user_origin_id,
+ categories=categories,
+ integration=integration,
+ link_expiry_mins=link_expiry_mins,
+ should_create_magic_link_url=should_create_magic_link_url,
+ hide_admin_magic_link=hide_admin_magic_link,
+ common_models=common_models,
+ category_common_model_scopes=category_common_model_scopes,
+ language=language,
+ are_syncs_disabled=are_syncs_disabled,
+ integration_specific_config=integration_specific_config,
+ completed_account_initial_screen=completed_account_initial_screen,
+ linked_destination_id=linked_destination_id,
+ credential_id=credential_id,
+ ekm_enabled=ekm_enabled,
+ request_options=request_options,
+ )
+ return _response.data
+
+
+class AsyncLinkTokenClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._raw_client = AsyncRawLinkTokenClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> AsyncRawLinkTokenClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ AsyncRawLinkTokenClient
+ """
+ return self._raw_client
+
+ async def create(
+ self,
+ *,
+ end_user_email_address: str,
+ end_user_organization_name: str,
+ end_user_origin_id: str,
+ categories: typing.Sequence[CategoriesEnum],
+ integration: typing.Optional[str] = OMIT,
+ link_expiry_mins: typing.Optional[int] = OMIT,
+ should_create_magic_link_url: typing.Optional[bool] = OMIT,
+ hide_admin_magic_link: typing.Optional[bool] = OMIT,
+ common_models: typing.Optional[typing.Sequence[CommonModelScopesBodyRequest]] = OMIT,
+ category_common_model_scopes: typing.Optional[
+ typing.Dict[str, typing.Optional[typing.Sequence[IndividualCommonModelScopeDeserializerRequest]]]
+ ] = OMIT,
+ language: typing.Optional[EndUserDetailsRequestLanguage] = OMIT,
+ are_syncs_disabled: typing.Optional[bool] = OMIT,
+ integration_specific_config: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
+ completed_account_initial_screen: typing.Optional[EndUserDetailsRequestCompletedAccountInitialScreen] = OMIT,
+ linked_destination_id: typing.Optional[str] = OMIT,
+ credential_id: typing.Optional[str] = OMIT,
+ ekm_enabled: typing.Optional[bool] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> LinkToken:
+ """
+ Creates a link token to be used when linking a new end user. The link token expires after single use.
+
+ Parameters
+ ----------
+ end_user_email_address : str
+ Your end user's email address. This is purely for identification purposes - setting this value will not cause any emails to be sent.
+
+ end_user_organization_name : str
+ Your end user's organization.
+
+ end_user_origin_id : str
+ This unique identifier typically represents the ID for your end user in your product's database. This value must be distinct from other Linked Accounts' unique identifiers.
+
+ categories : typing.Sequence[CategoriesEnum]
+ The integration categories to show in Merge Link.
+
+ integration : typing.Optional[str]
+ The slug of a specific pre-selected integration for this linking flow token. For examples of slugs, see https://docs.merge.dev/guides/merge-link/single-integration/.
+
+ link_expiry_mins : typing.Optional[int]
+ An integer number of minutes between [30, 720 or 10080 if for a Magic Link URL] for how long this token is valid. Defaults to 30.
+
+ should_create_magic_link_url : typing.Optional[bool]
+ Whether to generate a Magic Link URL. Defaults to false. For more information on Magic Link, see https://merge.dev/blog/integrations-fast-say-hello-to-magic-link.
+
+ hide_admin_magic_link : typing.Optional[bool]
+ Whether to generate a Magic Link URL on the Admin Needed screen during the linking flow. Defaults to false. For more information on Magic Link, see https://merge.dev/blog/integrations-fast-say-hello-to-magic-link.
+
+ common_models : typing.Optional[typing.Sequence[CommonModelScopesBodyRequest]]
+ An array of objects to specify the models and fields that will be disabled for a given Linked Account. Each object uses model_id, enabled_actions, and disabled_fields to specify the model, method, and fields that are scoped for a given Linked Account.
+
+ category_common_model_scopes : typing.Optional[typing.Dict[str, typing.Optional[typing.Sequence[IndividualCommonModelScopeDeserializerRequest]]]]
+ When creating a Link Token, you can set permissions for Common Models that will apply to the account that is going to be linked. Any model or field not specified in link token payload will default to existing settings.
+
+ language : typing.Optional[EndUserDetailsRequestLanguage]
+ The following subset of IETF language tags can be used to configure localization.
+
+ are_syncs_disabled : typing.Optional[bool]
+ The boolean that indicates whether initial, periodic, and force syncs will be disabled.
+
+ integration_specific_config : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
+ A JSON object containing integration-specific configuration options.
+
+ completed_account_initial_screen : typing.Optional[EndUserDetailsRequestCompletedAccountInitialScreen]
+ When creating a Link token, you can specifiy the initial screen of Linking Flow for a completed Linked Account.
+
+ linked_destination_id : typing.Optional[str]
+ The UUID of the linked destination that you want this Linked Account to be tied to.
+
+ credential_id : typing.Optional[str]
+ The id of the credential that you want this Linked Account to be tied to.
+
+ ekm_enabled : typing.Optional[bool]
+ Whether to enable EKM (External Key Management) for this Linked Account.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ LinkToken
+
+
+ Examples
+ --------
+ import asyncio
+
+ from merge import AsyncMerge
+ from merge.resources.email import CategoriesEnum
+
+ client = AsyncMerge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.email.link_token.create(
+ end_user_email_address="example@gmail.com",
+ end_user_organization_name="Test Organization",
+ end_user_origin_id="12345",
+ categories=[CategoriesEnum.HRIS, CategoriesEnum.ATS],
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.create(
+ end_user_email_address=end_user_email_address,
+ end_user_organization_name=end_user_organization_name,
+ end_user_origin_id=end_user_origin_id,
+ categories=categories,
+ integration=integration,
+ link_expiry_mins=link_expiry_mins,
+ should_create_magic_link_url=should_create_magic_link_url,
+ hide_admin_magic_link=hide_admin_magic_link,
+ common_models=common_models,
+ category_common_model_scopes=category_common_model_scopes,
+ language=language,
+ are_syncs_disabled=are_syncs_disabled,
+ integration_specific_config=integration_specific_config,
+ completed_account_initial_screen=completed_account_initial_screen,
+ linked_destination_id=linked_destination_id,
+ credential_id=credential_id,
+ ekm_enabled=ekm_enabled,
+ request_options=request_options,
+ )
+ return _response.data
diff --git a/src/merge/resources/email/resources/link_token/raw_client.py b/src/merge/resources/email/resources/link_token/raw_client.py
new file mode 100644
index 00000000..f84602b0
--- /dev/null
+++ b/src/merge/resources/email/resources/link_token/raw_client.py
@@ -0,0 +1,293 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+from json.decoder import JSONDecodeError
+
+from .....core.api_error import ApiError
+from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .....core.http_response import AsyncHttpResponse, HttpResponse
+from .....core.request_options import RequestOptions
+from .....core.unchecked_base_model import construct_type
+from ...types.categories_enum import CategoriesEnum
+from ...types.common_model_scopes_body_request import CommonModelScopesBodyRequest
+from ...types.individual_common_model_scope_deserializer_request import IndividualCommonModelScopeDeserializerRequest
+from ...types.link_token import LinkToken
+from .types.end_user_details_request_completed_account_initial_screen import (
+ EndUserDetailsRequestCompletedAccountInitialScreen,
+)
+from .types.end_user_details_request_language import EndUserDetailsRequestLanguage
+
+# this is used as the default value for optional parameters
+OMIT = typing.cast(typing.Any, ...)
+
+
+class RawLinkTokenClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ def create(
+ self,
+ *,
+ end_user_email_address: str,
+ end_user_organization_name: str,
+ end_user_origin_id: str,
+ categories: typing.Sequence[CategoriesEnum],
+ integration: typing.Optional[str] = OMIT,
+ link_expiry_mins: typing.Optional[int] = OMIT,
+ should_create_magic_link_url: typing.Optional[bool] = OMIT,
+ hide_admin_magic_link: typing.Optional[bool] = OMIT,
+ common_models: typing.Optional[typing.Sequence[CommonModelScopesBodyRequest]] = OMIT,
+ category_common_model_scopes: typing.Optional[
+ typing.Dict[str, typing.Optional[typing.Sequence[IndividualCommonModelScopeDeserializerRequest]]]
+ ] = OMIT,
+ language: typing.Optional[EndUserDetailsRequestLanguage] = OMIT,
+ are_syncs_disabled: typing.Optional[bool] = OMIT,
+ integration_specific_config: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
+ completed_account_initial_screen: typing.Optional[EndUserDetailsRequestCompletedAccountInitialScreen] = OMIT,
+ linked_destination_id: typing.Optional[str] = OMIT,
+ credential_id: typing.Optional[str] = OMIT,
+ ekm_enabled: typing.Optional[bool] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> HttpResponse[LinkToken]:
+ """
+ Creates a link token to be used when linking a new end user. The link token expires after single use.
+
+ Parameters
+ ----------
+ end_user_email_address : str
+ Your end user's email address. This is purely for identification purposes - setting this value will not cause any emails to be sent.
+
+ end_user_organization_name : str
+ Your end user's organization.
+
+ end_user_origin_id : str
+ This unique identifier typically represents the ID for your end user in your product's database. This value must be distinct from other Linked Accounts' unique identifiers.
+
+ categories : typing.Sequence[CategoriesEnum]
+ The integration categories to show in Merge Link.
+
+ integration : typing.Optional[str]
+ The slug of a specific pre-selected integration for this linking flow token. For examples of slugs, see https://docs.merge.dev/guides/merge-link/single-integration/.
+
+ link_expiry_mins : typing.Optional[int]
+ An integer number of minutes between [30, 720 or 10080 if for a Magic Link URL] for how long this token is valid. Defaults to 30.
+
+ should_create_magic_link_url : typing.Optional[bool]
+ Whether to generate a Magic Link URL. Defaults to false. For more information on Magic Link, see https://merge.dev/blog/integrations-fast-say-hello-to-magic-link.
+
+ hide_admin_magic_link : typing.Optional[bool]
+ Whether to generate a Magic Link URL on the Admin Needed screen during the linking flow. Defaults to false. For more information on Magic Link, see https://merge.dev/blog/integrations-fast-say-hello-to-magic-link.
+
+ common_models : typing.Optional[typing.Sequence[CommonModelScopesBodyRequest]]
+ An array of objects to specify the models and fields that will be disabled for a given Linked Account. Each object uses model_id, enabled_actions, and disabled_fields to specify the model, method, and fields that are scoped for a given Linked Account.
+
+ category_common_model_scopes : typing.Optional[typing.Dict[str, typing.Optional[typing.Sequence[IndividualCommonModelScopeDeserializerRequest]]]]
+ When creating a Link Token, you can set permissions for Common Models that will apply to the account that is going to be linked. Any model or field not specified in link token payload will default to existing settings.
+
+ language : typing.Optional[EndUserDetailsRequestLanguage]
+ The following subset of IETF language tags can be used to configure localization.
+
+ are_syncs_disabled : typing.Optional[bool]
+ The boolean that indicates whether initial, periodic, and force syncs will be disabled.
+
+ integration_specific_config : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
+ A JSON object containing integration-specific configuration options.
+
+ completed_account_initial_screen : typing.Optional[EndUserDetailsRequestCompletedAccountInitialScreen]
+ When creating a Link token, you can specifiy the initial screen of Linking Flow for a completed Linked Account.
+
+ linked_destination_id : typing.Optional[str]
+ The UUID of the linked destination that you want this Linked Account to be tied to.
+
+ credential_id : typing.Optional[str]
+ The id of the credential that you want this Linked Account to be tied to.
+
+ ekm_enabled : typing.Optional[bool]
+ Whether to enable EKM (External Key Management) for this Linked Account.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[LinkToken]
+
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ "email/v1/link-token",
+ method="POST",
+ json={
+ "end_user_email_address": end_user_email_address,
+ "end_user_organization_name": end_user_organization_name,
+ "end_user_origin_id": end_user_origin_id,
+ "categories": categories,
+ "integration": integration,
+ "link_expiry_mins": link_expiry_mins,
+ "should_create_magic_link_url": should_create_magic_link_url,
+ "hide_admin_magic_link": hide_admin_magic_link,
+ "common_models": common_models,
+ "category_common_model_scopes": category_common_model_scopes,
+ "language": language,
+ "are_syncs_disabled": are_syncs_disabled,
+ "integration_specific_config": integration_specific_config,
+ "completed_account_initial_screen": completed_account_initial_screen,
+ "linked_destination_id": linked_destination_id,
+ "credential_id": credential_id,
+ "ekm_enabled": ekm_enabled,
+ },
+ headers={
+ "content-type": "application/json",
+ },
+ request_options=request_options,
+ omit=OMIT,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ LinkToken,
+ construct_type(
+ type_=LinkToken, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+
+class AsyncRawLinkTokenClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ async def create(
+ self,
+ *,
+ end_user_email_address: str,
+ end_user_organization_name: str,
+ end_user_origin_id: str,
+ categories: typing.Sequence[CategoriesEnum],
+ integration: typing.Optional[str] = OMIT,
+ link_expiry_mins: typing.Optional[int] = OMIT,
+ should_create_magic_link_url: typing.Optional[bool] = OMIT,
+ hide_admin_magic_link: typing.Optional[bool] = OMIT,
+ common_models: typing.Optional[typing.Sequence[CommonModelScopesBodyRequest]] = OMIT,
+ category_common_model_scopes: typing.Optional[
+ typing.Dict[str, typing.Optional[typing.Sequence[IndividualCommonModelScopeDeserializerRequest]]]
+ ] = OMIT,
+ language: typing.Optional[EndUserDetailsRequestLanguage] = OMIT,
+ are_syncs_disabled: typing.Optional[bool] = OMIT,
+ integration_specific_config: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
+ completed_account_initial_screen: typing.Optional[EndUserDetailsRequestCompletedAccountInitialScreen] = OMIT,
+ linked_destination_id: typing.Optional[str] = OMIT,
+ credential_id: typing.Optional[str] = OMIT,
+ ekm_enabled: typing.Optional[bool] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> AsyncHttpResponse[LinkToken]:
+ """
+ Creates a link token to be used when linking a new end user. The link token expires after single use.
+
+ Parameters
+ ----------
+ end_user_email_address : str
+ Your end user's email address. This is purely for identification purposes - setting this value will not cause any emails to be sent.
+
+ end_user_organization_name : str
+ Your end user's organization.
+
+ end_user_origin_id : str
+ This unique identifier typically represents the ID for your end user in your product's database. This value must be distinct from other Linked Accounts' unique identifiers.
+
+ categories : typing.Sequence[CategoriesEnum]
+ The integration categories to show in Merge Link.
+
+ integration : typing.Optional[str]
+ The slug of a specific pre-selected integration for this linking flow token. For examples of slugs, see https://docs.merge.dev/guides/merge-link/single-integration/.
+
+ link_expiry_mins : typing.Optional[int]
+ An integer number of minutes between [30, 720 or 10080 if for a Magic Link URL] for how long this token is valid. Defaults to 30.
+
+ should_create_magic_link_url : typing.Optional[bool]
+ Whether to generate a Magic Link URL. Defaults to false. For more information on Magic Link, see https://merge.dev/blog/integrations-fast-say-hello-to-magic-link.
+
+ hide_admin_magic_link : typing.Optional[bool]
+ Whether to generate a Magic Link URL on the Admin Needed screen during the linking flow. Defaults to false. For more information on Magic Link, see https://merge.dev/blog/integrations-fast-say-hello-to-magic-link.
+
+ common_models : typing.Optional[typing.Sequence[CommonModelScopesBodyRequest]]
+ An array of objects to specify the models and fields that will be disabled for a given Linked Account. Each object uses model_id, enabled_actions, and disabled_fields to specify the model, method, and fields that are scoped for a given Linked Account.
+
+ category_common_model_scopes : typing.Optional[typing.Dict[str, typing.Optional[typing.Sequence[IndividualCommonModelScopeDeserializerRequest]]]]
+ When creating a Link Token, you can set permissions for Common Models that will apply to the account that is going to be linked. Any model or field not specified in link token payload will default to existing settings.
+
+ language : typing.Optional[EndUserDetailsRequestLanguage]
+ The following subset of IETF language tags can be used to configure localization.
+
+ are_syncs_disabled : typing.Optional[bool]
+ The boolean that indicates whether initial, periodic, and force syncs will be disabled.
+
+ integration_specific_config : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
+ A JSON object containing integration-specific configuration options.
+
+ completed_account_initial_screen : typing.Optional[EndUserDetailsRequestCompletedAccountInitialScreen]
+ When creating a Link token, you can specifiy the initial screen of Linking Flow for a completed Linked Account.
+
+ linked_destination_id : typing.Optional[str]
+ The UUID of the linked destination that you want this Linked Account to be tied to.
+
+ credential_id : typing.Optional[str]
+ The id of the credential that you want this Linked Account to be tied to.
+
+ ekm_enabled : typing.Optional[bool]
+ Whether to enable EKM (External Key Management) for this Linked Account.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[LinkToken]
+
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ "email/v1/link-token",
+ method="POST",
+ json={
+ "end_user_email_address": end_user_email_address,
+ "end_user_organization_name": end_user_organization_name,
+ "end_user_origin_id": end_user_origin_id,
+ "categories": categories,
+ "integration": integration,
+ "link_expiry_mins": link_expiry_mins,
+ "should_create_magic_link_url": should_create_magic_link_url,
+ "hide_admin_magic_link": hide_admin_magic_link,
+ "common_models": common_models,
+ "category_common_model_scopes": category_common_model_scopes,
+ "language": language,
+ "are_syncs_disabled": are_syncs_disabled,
+ "integration_specific_config": integration_specific_config,
+ "completed_account_initial_screen": completed_account_initial_screen,
+ "linked_destination_id": linked_destination_id,
+ "credential_id": credential_id,
+ "ekm_enabled": ekm_enabled,
+ },
+ headers={
+ "content-type": "application/json",
+ },
+ request_options=request_options,
+ omit=OMIT,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ LinkToken,
+ construct_type(
+ type_=LinkToken, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
diff --git a/src/merge/resources/email/resources/link_token/types/__init__.py b/src/merge/resources/email/resources/link_token/types/__init__.py
new file mode 100644
index 00000000..55cc1d4e
--- /dev/null
+++ b/src/merge/resources/email/resources/link_token/types/__init__.py
@@ -0,0 +1,38 @@
+# This file was auto-generated by Fern from our API Definition.
+
+# isort: skip_file
+
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .end_user_details_request_completed_account_initial_screen import (
+ EndUserDetailsRequestCompletedAccountInitialScreen,
+ )
+ from .end_user_details_request_language import EndUserDetailsRequestLanguage
+_dynamic_imports: typing.Dict[str, str] = {
+ "EndUserDetailsRequestCompletedAccountInitialScreen": ".end_user_details_request_completed_account_initial_screen",
+ "EndUserDetailsRequestLanguage": ".end_user_details_request_language",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ result = getattr(module, attr_name)
+ return result
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
+
+__all__ = ["EndUserDetailsRequestCompletedAccountInitialScreen", "EndUserDetailsRequestLanguage"]
diff --git a/src/merge/resources/email/resources/link_token/types/end_user_details_request_completed_account_initial_screen.py b/src/merge/resources/email/resources/link_token/types/end_user_details_request_completed_account_initial_screen.py
new file mode 100644
index 00000000..0c5d586d
--- /dev/null
+++ b/src/merge/resources/email/resources/link_token/types/end_user_details_request_completed_account_initial_screen.py
@@ -0,0 +1,7 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+from ....types.completed_account_initial_screen_enum import CompletedAccountInitialScreenEnum
+
+EndUserDetailsRequestCompletedAccountInitialScreen = typing.Union[CompletedAccountInitialScreenEnum, str]
diff --git a/src/merge/resources/email/resources/link_token/types/end_user_details_request_language.py b/src/merge/resources/email/resources/link_token/types/end_user_details_request_language.py
new file mode 100644
index 00000000..65c4b44a
--- /dev/null
+++ b/src/merge/resources/email/resources/link_token/types/end_user_details_request_language.py
@@ -0,0 +1,7 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+from ....types.language_enum import LanguageEnum
+
+EndUserDetailsRequestLanguage = typing.Union[LanguageEnum, str]
diff --git a/src/merge/resources/email/resources/linked_accounts/__init__.py b/src/merge/resources/email/resources/linked_accounts/__init__.py
new file mode 100644
index 00000000..0b9e42b4
--- /dev/null
+++ b/src/merge/resources/email/resources/linked_accounts/__init__.py
@@ -0,0 +1,32 @@
+# This file was auto-generated by Fern from our API Definition.
+
+# isort: skip_file
+
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .types import LinkedAccountsListRequestCategory
+_dynamic_imports: typing.Dict[str, str] = {"LinkedAccountsListRequestCategory": ".types"}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ result = getattr(module, attr_name)
+ return result
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
+
+__all__ = ["LinkedAccountsListRequestCategory"]
diff --git a/src/merge/resources/email/resources/linked_accounts/client.py b/src/merge/resources/email/resources/linked_accounts/client.py
new file mode 100644
index 00000000..3170bb97
--- /dev/null
+++ b/src/merge/resources/email/resources/linked_accounts/client.py
@@ -0,0 +1,277 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .....core.request_options import RequestOptions
+from ...types.paginated_account_details_and_actions_list import PaginatedAccountDetailsAndActionsList
+from .raw_client import AsyncRawLinkedAccountsClient, RawLinkedAccountsClient
+from .types.linked_accounts_list_request_category import LinkedAccountsListRequestCategory
+
+
+class LinkedAccountsClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._raw_client = RawLinkedAccountsClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> RawLinkedAccountsClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ RawLinkedAccountsClient
+ """
+ return self._raw_client
+
+ def list(
+ self,
+ *,
+ category: typing.Optional[LinkedAccountsListRequestCategory] = None,
+ cursor: typing.Optional[str] = None,
+ end_user_email_address: typing.Optional[str] = None,
+ end_user_organization_name: typing.Optional[str] = None,
+ end_user_origin_id: typing.Optional[str] = None,
+ end_user_origin_ids: typing.Optional[str] = None,
+ id: typing.Optional[str] = None,
+ ids: typing.Optional[str] = None,
+ include_duplicates: typing.Optional[bool] = None,
+ integration_name: typing.Optional[str] = None,
+ is_test_account: typing.Optional[str] = None,
+ page_size: typing.Optional[int] = None,
+ status: typing.Optional[str] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> PaginatedAccountDetailsAndActionsList:
+ """
+ List linked accounts for your organization.
+
+ Parameters
+ ----------
+ category : typing.Optional[LinkedAccountsListRequestCategory]
+ Options: `hris`, `ats`, `accounting`, `ticketing`, `crm`, `mktg`, `filestorage`, `knowledgebase`, `chat`
+
+ cursor : typing.Optional[str]
+ The pagination cursor value.
+
+ end_user_email_address : typing.Optional[str]
+ If provided, will only return linked accounts associated with the given email address.
+
+ end_user_organization_name : typing.Optional[str]
+ If provided, will only return linked accounts associated with the given organization name.
+
+ end_user_origin_id : typing.Optional[str]
+ If provided, will only return linked accounts associated with the given origin ID.
+
+ end_user_origin_ids : typing.Optional[str]
+ Comma-separated list of EndUser origin IDs, making it possible to specify multiple EndUsers at once.
+
+ id : typing.Optional[str]
+
+ ids : typing.Optional[str]
+ Comma-separated list of LinkedAccount IDs, making it possible to specify multiple LinkedAccounts at once.
+
+ include_duplicates : typing.Optional[bool]
+ If `true`, will include complete production duplicates of the account specified by the `id` query parameter in the response. `id` must be for a complete production linked account.
+
+ integration_name : typing.Optional[str]
+ If provided, will only return linked accounts associated with the given integration name.
+
+ is_test_account : typing.Optional[str]
+ If included, will only include test linked accounts. If not included, will only include non-test linked accounts.
+
+ page_size : typing.Optional[int]
+ Number of results to return per page. The maximum limit is 100.
+
+ status : typing.Optional[str]
+ Filter by status. Options: `COMPLETE`, `IDLE`, `INCOMPLETE`, `RELINK_NEEDED`
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ PaginatedAccountDetailsAndActionsList
+
+
+ Examples
+ --------
+ from merge import Merge
+ from merge.resources.email.resources.linked_accounts import (
+ LinkedAccountsListRequestCategory,
+ )
+
+ client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+ client.email.linked_accounts.list(
+ category=LinkedAccountsListRequestCategory.ACCOUNTING,
+ cursor="cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw",
+ end_user_email_address="end_user_email_address",
+ end_user_organization_name="end_user_organization_name",
+ end_user_origin_id="end_user_origin_id",
+ end_user_origin_ids="end_user_origin_ids",
+ id="id",
+ ids="ids",
+ include_duplicates=True,
+ integration_name="integration_name",
+ is_test_account="is_test_account",
+ page_size=1,
+ status="status",
+ )
+ """
+ _response = self._raw_client.list(
+ category=category,
+ cursor=cursor,
+ end_user_email_address=end_user_email_address,
+ end_user_organization_name=end_user_organization_name,
+ end_user_origin_id=end_user_origin_id,
+ end_user_origin_ids=end_user_origin_ids,
+ id=id,
+ ids=ids,
+ include_duplicates=include_duplicates,
+ integration_name=integration_name,
+ is_test_account=is_test_account,
+ page_size=page_size,
+ status=status,
+ request_options=request_options,
+ )
+ return _response.data
+
+
+class AsyncLinkedAccountsClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._raw_client = AsyncRawLinkedAccountsClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> AsyncRawLinkedAccountsClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ AsyncRawLinkedAccountsClient
+ """
+ return self._raw_client
+
+ async def list(
+ self,
+ *,
+ category: typing.Optional[LinkedAccountsListRequestCategory] = None,
+ cursor: typing.Optional[str] = None,
+ end_user_email_address: typing.Optional[str] = None,
+ end_user_organization_name: typing.Optional[str] = None,
+ end_user_origin_id: typing.Optional[str] = None,
+ end_user_origin_ids: typing.Optional[str] = None,
+ id: typing.Optional[str] = None,
+ ids: typing.Optional[str] = None,
+ include_duplicates: typing.Optional[bool] = None,
+ integration_name: typing.Optional[str] = None,
+ is_test_account: typing.Optional[str] = None,
+ page_size: typing.Optional[int] = None,
+ status: typing.Optional[str] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> PaginatedAccountDetailsAndActionsList:
+ """
+ List linked accounts for your organization.
+
+ Parameters
+ ----------
+ category : typing.Optional[LinkedAccountsListRequestCategory]
+ Options: `hris`, `ats`, `accounting`, `ticketing`, `crm`, `mktg`, `filestorage`, `knowledgebase`, `chat`
+
+ cursor : typing.Optional[str]
+ The pagination cursor value.
+
+ end_user_email_address : typing.Optional[str]
+ If provided, will only return linked accounts associated with the given email address.
+
+ end_user_organization_name : typing.Optional[str]
+ If provided, will only return linked accounts associated with the given organization name.
+
+ end_user_origin_id : typing.Optional[str]
+ If provided, will only return linked accounts associated with the given origin ID.
+
+ end_user_origin_ids : typing.Optional[str]
+ Comma-separated list of EndUser origin IDs, making it possible to specify multiple EndUsers at once.
+
+ id : typing.Optional[str]
+
+ ids : typing.Optional[str]
+ Comma-separated list of LinkedAccount IDs, making it possible to specify multiple LinkedAccounts at once.
+
+ include_duplicates : typing.Optional[bool]
+ If `true`, will include complete production duplicates of the account specified by the `id` query parameter in the response. `id` must be for a complete production linked account.
+
+ integration_name : typing.Optional[str]
+ If provided, will only return linked accounts associated with the given integration name.
+
+ is_test_account : typing.Optional[str]
+ If included, will only include test linked accounts. If not included, will only include non-test linked accounts.
+
+ page_size : typing.Optional[int]
+ Number of results to return per page. The maximum limit is 100.
+
+ status : typing.Optional[str]
+ Filter by status. Options: `COMPLETE`, `IDLE`, `INCOMPLETE`, `RELINK_NEEDED`
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ PaginatedAccountDetailsAndActionsList
+
+
+ Examples
+ --------
+ import asyncio
+
+ from merge import AsyncMerge
+ from merge.resources.email.resources.linked_accounts import (
+ LinkedAccountsListRequestCategory,
+ )
+
+ client = AsyncMerge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.email.linked_accounts.list(
+ category=LinkedAccountsListRequestCategory.ACCOUNTING,
+ cursor="cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw",
+ end_user_email_address="end_user_email_address",
+ end_user_organization_name="end_user_organization_name",
+ end_user_origin_id="end_user_origin_id",
+ end_user_origin_ids="end_user_origin_ids",
+ id="id",
+ ids="ids",
+ include_duplicates=True,
+ integration_name="integration_name",
+ is_test_account="is_test_account",
+ page_size=1,
+ status="status",
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.list(
+ category=category,
+ cursor=cursor,
+ end_user_email_address=end_user_email_address,
+ end_user_organization_name=end_user_organization_name,
+ end_user_origin_id=end_user_origin_id,
+ end_user_origin_ids=end_user_origin_ids,
+ id=id,
+ ids=ids,
+ include_duplicates=include_duplicates,
+ integration_name=integration_name,
+ is_test_account=is_test_account,
+ page_size=page_size,
+ status=status,
+ request_options=request_options,
+ )
+ return _response.data
diff --git a/src/merge/resources/email/resources/linked_accounts/raw_client.py b/src/merge/resources/email/resources/linked_accounts/raw_client.py
new file mode 100644
index 00000000..a72a3011
--- /dev/null
+++ b/src/merge/resources/email/resources/linked_accounts/raw_client.py
@@ -0,0 +1,230 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+from json.decoder import JSONDecodeError
+
+from .....core.api_error import ApiError
+from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .....core.http_response import AsyncHttpResponse, HttpResponse
+from .....core.request_options import RequestOptions
+from .....core.unchecked_base_model import construct_type
+from ...types.paginated_account_details_and_actions_list import PaginatedAccountDetailsAndActionsList
+from .types.linked_accounts_list_request_category import LinkedAccountsListRequestCategory
+
+
+class RawLinkedAccountsClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ def list(
+ self,
+ *,
+ category: typing.Optional[LinkedAccountsListRequestCategory] = None,
+ cursor: typing.Optional[str] = None,
+ end_user_email_address: typing.Optional[str] = None,
+ end_user_organization_name: typing.Optional[str] = None,
+ end_user_origin_id: typing.Optional[str] = None,
+ end_user_origin_ids: typing.Optional[str] = None,
+ id: typing.Optional[str] = None,
+ ids: typing.Optional[str] = None,
+ include_duplicates: typing.Optional[bool] = None,
+ integration_name: typing.Optional[str] = None,
+ is_test_account: typing.Optional[str] = None,
+ page_size: typing.Optional[int] = None,
+ status: typing.Optional[str] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> HttpResponse[PaginatedAccountDetailsAndActionsList]:
+ """
+ List linked accounts for your organization.
+
+ Parameters
+ ----------
+ category : typing.Optional[LinkedAccountsListRequestCategory]
+ Options: `hris`, `ats`, `accounting`, `ticketing`, `crm`, `mktg`, `filestorage`, `knowledgebase`, `chat`
+
+ cursor : typing.Optional[str]
+ The pagination cursor value.
+
+ end_user_email_address : typing.Optional[str]
+ If provided, will only return linked accounts associated with the given email address.
+
+ end_user_organization_name : typing.Optional[str]
+ If provided, will only return linked accounts associated with the given organization name.
+
+ end_user_origin_id : typing.Optional[str]
+ If provided, will only return linked accounts associated with the given origin ID.
+
+ end_user_origin_ids : typing.Optional[str]
+ Comma-separated list of EndUser origin IDs, making it possible to specify multiple EndUsers at once.
+
+ id : typing.Optional[str]
+
+ ids : typing.Optional[str]
+ Comma-separated list of LinkedAccount IDs, making it possible to specify multiple LinkedAccounts at once.
+
+ include_duplicates : typing.Optional[bool]
+ If `true`, will include complete production duplicates of the account specified by the `id` query parameter in the response. `id` must be for a complete production linked account.
+
+ integration_name : typing.Optional[str]
+ If provided, will only return linked accounts associated with the given integration name.
+
+ is_test_account : typing.Optional[str]
+ If included, will only include test linked accounts. If not included, will only include non-test linked accounts.
+
+ page_size : typing.Optional[int]
+ Number of results to return per page. The maximum limit is 100.
+
+ status : typing.Optional[str]
+ Filter by status. Options: `COMPLETE`, `IDLE`, `INCOMPLETE`, `RELINK_NEEDED`
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[PaginatedAccountDetailsAndActionsList]
+
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ "email/v1/linked-accounts",
+ method="GET",
+ params={
+ "category": category,
+ "cursor": cursor,
+ "end_user_email_address": end_user_email_address,
+ "end_user_organization_name": end_user_organization_name,
+ "end_user_origin_id": end_user_origin_id,
+ "end_user_origin_ids": end_user_origin_ids,
+ "id": id,
+ "ids": ids,
+ "include_duplicates": include_duplicates,
+ "integration_name": integration_name,
+ "is_test_account": is_test_account,
+ "page_size": page_size,
+ "status": status,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ PaginatedAccountDetailsAndActionsList,
+ construct_type(
+ type_=PaginatedAccountDetailsAndActionsList, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+
+class AsyncRawLinkedAccountsClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ async def list(
+ self,
+ *,
+ category: typing.Optional[LinkedAccountsListRequestCategory] = None,
+ cursor: typing.Optional[str] = None,
+ end_user_email_address: typing.Optional[str] = None,
+ end_user_organization_name: typing.Optional[str] = None,
+ end_user_origin_id: typing.Optional[str] = None,
+ end_user_origin_ids: typing.Optional[str] = None,
+ id: typing.Optional[str] = None,
+ ids: typing.Optional[str] = None,
+ include_duplicates: typing.Optional[bool] = None,
+ integration_name: typing.Optional[str] = None,
+ is_test_account: typing.Optional[str] = None,
+ page_size: typing.Optional[int] = None,
+ status: typing.Optional[str] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> AsyncHttpResponse[PaginatedAccountDetailsAndActionsList]:
+ """
+ List linked accounts for your organization.
+
+ Parameters
+ ----------
+ category : typing.Optional[LinkedAccountsListRequestCategory]
+ Options: `hris`, `ats`, `accounting`, `ticketing`, `crm`, `mktg`, `filestorage`, `knowledgebase`, `chat`
+
+ cursor : typing.Optional[str]
+ The pagination cursor value.
+
+ end_user_email_address : typing.Optional[str]
+ If provided, will only return linked accounts associated with the given email address.
+
+ end_user_organization_name : typing.Optional[str]
+ If provided, will only return linked accounts associated with the given organization name.
+
+ end_user_origin_id : typing.Optional[str]
+ If provided, will only return linked accounts associated with the given origin ID.
+
+ end_user_origin_ids : typing.Optional[str]
+ Comma-separated list of EndUser origin IDs, making it possible to specify multiple EndUsers at once.
+
+ id : typing.Optional[str]
+
+ ids : typing.Optional[str]
+ Comma-separated list of LinkedAccount IDs, making it possible to specify multiple LinkedAccounts at once.
+
+ include_duplicates : typing.Optional[bool]
+ If `true`, will include complete production duplicates of the account specified by the `id` query parameter in the response. `id` must be for a complete production linked account.
+
+ integration_name : typing.Optional[str]
+ If provided, will only return linked accounts associated with the given integration name.
+
+ is_test_account : typing.Optional[str]
+ If included, will only include test linked accounts. If not included, will only include non-test linked accounts.
+
+ page_size : typing.Optional[int]
+ Number of results to return per page. The maximum limit is 100.
+
+ status : typing.Optional[str]
+ Filter by status. Options: `COMPLETE`, `IDLE`, `INCOMPLETE`, `RELINK_NEEDED`
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[PaginatedAccountDetailsAndActionsList]
+
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ "email/v1/linked-accounts",
+ method="GET",
+ params={
+ "category": category,
+ "cursor": cursor,
+ "end_user_email_address": end_user_email_address,
+ "end_user_organization_name": end_user_organization_name,
+ "end_user_origin_id": end_user_origin_id,
+ "end_user_origin_ids": end_user_origin_ids,
+ "id": id,
+ "ids": ids,
+ "include_duplicates": include_duplicates,
+ "integration_name": integration_name,
+ "is_test_account": is_test_account,
+ "page_size": page_size,
+ "status": status,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ PaginatedAccountDetailsAndActionsList,
+ construct_type(
+ type_=PaginatedAccountDetailsAndActionsList, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
diff --git a/src/merge/resources/email/resources/linked_accounts/types/__init__.py b/src/merge/resources/email/resources/linked_accounts/types/__init__.py
new file mode 100644
index 00000000..a28f38cc
--- /dev/null
+++ b/src/merge/resources/email/resources/linked_accounts/types/__init__.py
@@ -0,0 +1,34 @@
+# This file was auto-generated by Fern from our API Definition.
+
+# isort: skip_file
+
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .linked_accounts_list_request_category import LinkedAccountsListRequestCategory
+_dynamic_imports: typing.Dict[str, str] = {
+ "LinkedAccountsListRequestCategory": ".linked_accounts_list_request_category"
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ result = getattr(module, attr_name)
+ return result
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
+
+__all__ = ["LinkedAccountsListRequestCategory"]
diff --git a/src/merge/resources/email/resources/linked_accounts/types/linked_accounts_list_request_category.py b/src/merge/resources/email/resources/linked_accounts/types/linked_accounts_list_request_category.py
new file mode 100644
index 00000000..97df0150
--- /dev/null
+++ b/src/merge/resources/email/resources/linked_accounts/types/linked_accounts_list_request_category.py
@@ -0,0 +1,49 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import enum
+import typing
+
+T_Result = typing.TypeVar("T_Result")
+
+
+class LinkedAccountsListRequestCategory(str, enum.Enum):
+ ACCOUNTING = "accounting"
+ ATS = "ats"
+ CHAT = "chat"
+ CRM = "crm"
+ FILESTORAGE = "filestorage"
+ HRIS = "hris"
+ KNOWLEDGEBASE = "knowledgebase"
+ MKTG = "mktg"
+ TICKETING = "ticketing"
+
+ def visit(
+ self,
+ accounting: typing.Callable[[], T_Result],
+ ats: typing.Callable[[], T_Result],
+ chat: typing.Callable[[], T_Result],
+ crm: typing.Callable[[], T_Result],
+ filestorage: typing.Callable[[], T_Result],
+ hris: typing.Callable[[], T_Result],
+ knowledgebase: typing.Callable[[], T_Result],
+ mktg: typing.Callable[[], T_Result],
+ ticketing: typing.Callable[[], T_Result],
+ ) -> T_Result:
+ if self is LinkedAccountsListRequestCategory.ACCOUNTING:
+ return accounting()
+ if self is LinkedAccountsListRequestCategory.ATS:
+ return ats()
+ if self is LinkedAccountsListRequestCategory.CHAT:
+ return chat()
+ if self is LinkedAccountsListRequestCategory.CRM:
+ return crm()
+ if self is LinkedAccountsListRequestCategory.FILESTORAGE:
+ return filestorage()
+ if self is LinkedAccountsListRequestCategory.HRIS:
+ return hris()
+ if self is LinkedAccountsListRequestCategory.KNOWLEDGEBASE:
+ return knowledgebase()
+ if self is LinkedAccountsListRequestCategory.MKTG:
+ return mktg()
+ if self is LinkedAccountsListRequestCategory.TICKETING:
+ return ticketing()
diff --git a/src/merge/resources/email/resources/mailboxes/__init__.py b/src/merge/resources/email/resources/mailboxes/__init__.py
new file mode 100644
index 00000000..471992c1
--- /dev/null
+++ b/src/merge/resources/email/resources/mailboxes/__init__.py
@@ -0,0 +1,35 @@
+# This file was auto-generated by Fern from our API Definition.
+
+# isort: skip_file
+
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .types import MailboxesListRequestExpandItem, MailboxesRetrieveRequestExpandItem
+_dynamic_imports: typing.Dict[str, str] = {
+ "MailboxesListRequestExpandItem": ".types",
+ "MailboxesRetrieveRequestExpandItem": ".types",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ result = getattr(module, attr_name)
+ return result
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
+
+__all__ = ["MailboxesListRequestExpandItem", "MailboxesRetrieveRequestExpandItem"]
diff --git a/src/merge/resources/email/resources/mailboxes/client.py b/src/merge/resources/email/resources/mailboxes/client.py
new file mode 100644
index 00000000..7453bf33
--- /dev/null
+++ b/src/merge/resources/email/resources/mailboxes/client.py
@@ -0,0 +1,461 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+
+from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .....core.request_options import RequestOptions
+from ...types.mailbox import Mailbox
+from ...types.paginated_mailbox_list import PaginatedMailboxList
+from .raw_client import AsyncRawMailboxesClient, RawMailboxesClient
+from .types.mailboxes_list_request_expand_item import MailboxesListRequestExpandItem
+from .types.mailboxes_retrieve_request_expand_item import MailboxesRetrieveRequestExpandItem
+
+
+class MailboxesClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._raw_client = RawMailboxesClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> RawMailboxesClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ RawMailboxesClient
+ """
+ return self._raw_client
+
+ def list(
+ self,
+ *,
+ created_after: typing.Optional[dt.datetime] = None,
+ created_before: typing.Optional[dt.datetime] = None,
+ cursor: typing.Optional[str] = None,
+ expand: typing.Optional[
+ typing.Union[MailboxesListRequestExpandItem, typing.Sequence[MailboxesListRequestExpandItem]]
+ ] = None,
+ include_deleted_data: typing.Optional[bool] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ modified_after: typing.Optional[dt.datetime] = None,
+ modified_before: typing.Optional[dt.datetime] = None,
+ page_size: typing.Optional[int] = None,
+ primary_email_address_id: typing.Optional[str] = None,
+ remote_fields: typing.Optional[typing.Literal["type"]] = None,
+ remote_id: typing.Optional[str] = None,
+ show_enum_origins: typing.Optional[typing.Literal["type"]] = None,
+ user_id: typing.Optional[str] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> PaginatedMailboxList:
+ """
+ Returns a list of `Mailbox` objects.
+
+ Parameters
+ ----------
+ created_after : typing.Optional[dt.datetime]
+ If provided, will only return objects created after this datetime.
+
+ created_before : typing.Optional[dt.datetime]
+ If provided, will only return objects created before this datetime.
+
+ cursor : typing.Optional[str]
+ The pagination cursor value.
+
+ expand : typing.Optional[typing.Union[MailboxesListRequestExpandItem, typing.Sequence[MailboxesListRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ include_deleted_data : typing.Optional[bool]
+ Indicates whether or not this object has been deleted in the third party platform. Full coverage deletion detection is a premium add-on. Native deletion detection is offered for free with limited coverage. [Learn more](https://docs.merge.dev/integrations/hris/supported-features/).
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ modified_after : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge after this date time will be returned.
+
+ modified_before : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge before this date time will be returned.
+
+ page_size : typing.Optional[int]
+ Number of results to return per page. The maximum limit is 100.
+
+ primary_email_address_id : typing.Optional[str]
+ If provided, will only return Mailboxes with this primary EmailAddress.
+
+ remote_fields : typing.Optional[typing.Literal["type"]]
+ Deprecated. Use show_enum_origins.
+
+ remote_id : typing.Optional[str]
+ The API provider's ID for the given object.
+
+ show_enum_origins : typing.Optional[typing.Literal["type"]]
+ A comma separated list of enum field names for which you'd like the original values to be returned, instead of Merge's normalized enum values. [Learn more](https://help.merge.dev/en/articles/8950958-show_enum_origins-query-parameter)
+
+ user_id : typing.Optional[str]
+ If provided, will only return Mailboxes associated with this User.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ PaginatedMailboxList
+
+
+ Examples
+ --------
+ import datetime
+
+ from merge import Merge
+
+ client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+ client.email.mailboxes.list(
+ created_after=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ created_before=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ cursor="cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw",
+ include_deleted_data=True,
+ include_remote_data=True,
+ include_shell_data=True,
+ modified_after=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ modified_before=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ page_size=1,
+ primary_email_address_id="primary_email_address_id",
+ remote_id="remote_id",
+ user_id="user_id",
+ )
+ """
+ _response = self._raw_client.list(
+ created_after=created_after,
+ created_before=created_before,
+ cursor=cursor,
+ expand=expand,
+ include_deleted_data=include_deleted_data,
+ include_remote_data=include_remote_data,
+ include_shell_data=include_shell_data,
+ modified_after=modified_after,
+ modified_before=modified_before,
+ page_size=page_size,
+ primary_email_address_id=primary_email_address_id,
+ remote_fields=remote_fields,
+ remote_id=remote_id,
+ show_enum_origins=show_enum_origins,
+ user_id=user_id,
+ request_options=request_options,
+ )
+ return _response.data
+
+ def retrieve(
+ self,
+ id: str,
+ *,
+ expand: typing.Optional[
+ typing.Union[MailboxesRetrieveRequestExpandItem, typing.Sequence[MailboxesRetrieveRequestExpandItem]]
+ ] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ remote_fields: typing.Optional[typing.Literal["type"]] = None,
+ show_enum_origins: typing.Optional[typing.Literal["type"]] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> Mailbox:
+ """
+ Returns a `Mailbox` object with the given `id`.
+
+ Parameters
+ ----------
+ id : str
+
+ expand : typing.Optional[typing.Union[MailboxesRetrieveRequestExpandItem, typing.Sequence[MailboxesRetrieveRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ remote_fields : typing.Optional[typing.Literal["type"]]
+ Deprecated. Use show_enum_origins.
+
+ show_enum_origins : typing.Optional[typing.Literal["type"]]
+ A comma separated list of enum field names for which you'd like the original values to be returned, instead of Merge's normalized enum values. [Learn more](https://help.merge.dev/en/articles/8950958-show_enum_origins-query-parameter)
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ Mailbox
+
+
+ Examples
+ --------
+ from merge import Merge
+
+ client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+ client.email.mailboxes.retrieve(
+ id="id",
+ include_remote_data=True,
+ include_shell_data=True,
+ )
+ """
+ _response = self._raw_client.retrieve(
+ id,
+ expand=expand,
+ include_remote_data=include_remote_data,
+ include_shell_data=include_shell_data,
+ remote_fields=remote_fields,
+ show_enum_origins=show_enum_origins,
+ request_options=request_options,
+ )
+ return _response.data
+
+
+class AsyncMailboxesClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._raw_client = AsyncRawMailboxesClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> AsyncRawMailboxesClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ AsyncRawMailboxesClient
+ """
+ return self._raw_client
+
+ async def list(
+ self,
+ *,
+ created_after: typing.Optional[dt.datetime] = None,
+ created_before: typing.Optional[dt.datetime] = None,
+ cursor: typing.Optional[str] = None,
+ expand: typing.Optional[
+ typing.Union[MailboxesListRequestExpandItem, typing.Sequence[MailboxesListRequestExpandItem]]
+ ] = None,
+ include_deleted_data: typing.Optional[bool] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ modified_after: typing.Optional[dt.datetime] = None,
+ modified_before: typing.Optional[dt.datetime] = None,
+ page_size: typing.Optional[int] = None,
+ primary_email_address_id: typing.Optional[str] = None,
+ remote_fields: typing.Optional[typing.Literal["type"]] = None,
+ remote_id: typing.Optional[str] = None,
+ show_enum_origins: typing.Optional[typing.Literal["type"]] = None,
+ user_id: typing.Optional[str] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> PaginatedMailboxList:
+ """
+ Returns a list of `Mailbox` objects.
+
+ Parameters
+ ----------
+ created_after : typing.Optional[dt.datetime]
+ If provided, will only return objects created after this datetime.
+
+ created_before : typing.Optional[dt.datetime]
+ If provided, will only return objects created before this datetime.
+
+ cursor : typing.Optional[str]
+ The pagination cursor value.
+
+ expand : typing.Optional[typing.Union[MailboxesListRequestExpandItem, typing.Sequence[MailboxesListRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ include_deleted_data : typing.Optional[bool]
+ Indicates whether or not this object has been deleted in the third party platform. Full coverage deletion detection is a premium add-on. Native deletion detection is offered for free with limited coverage. [Learn more](https://docs.merge.dev/integrations/hris/supported-features/).
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ modified_after : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge after this date time will be returned.
+
+ modified_before : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge before this date time will be returned.
+
+ page_size : typing.Optional[int]
+ Number of results to return per page. The maximum limit is 100.
+
+ primary_email_address_id : typing.Optional[str]
+ If provided, will only return Mailboxes with this primary EmailAddress.
+
+ remote_fields : typing.Optional[typing.Literal["type"]]
+ Deprecated. Use show_enum_origins.
+
+ remote_id : typing.Optional[str]
+ The API provider's ID for the given object.
+
+ show_enum_origins : typing.Optional[typing.Literal["type"]]
+ A comma separated list of enum field names for which you'd like the original values to be returned, instead of Merge's normalized enum values. [Learn more](https://help.merge.dev/en/articles/8950958-show_enum_origins-query-parameter)
+
+ user_id : typing.Optional[str]
+ If provided, will only return Mailboxes associated with this User.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ PaginatedMailboxList
+
+
+ Examples
+ --------
+ import asyncio
+ import datetime
+
+ from merge import AsyncMerge
+
+ client = AsyncMerge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.email.mailboxes.list(
+ created_after=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ created_before=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ cursor="cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw",
+ include_deleted_data=True,
+ include_remote_data=True,
+ include_shell_data=True,
+ modified_after=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ modified_before=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ page_size=1,
+ primary_email_address_id="primary_email_address_id",
+ remote_id="remote_id",
+ user_id="user_id",
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.list(
+ created_after=created_after,
+ created_before=created_before,
+ cursor=cursor,
+ expand=expand,
+ include_deleted_data=include_deleted_data,
+ include_remote_data=include_remote_data,
+ include_shell_data=include_shell_data,
+ modified_after=modified_after,
+ modified_before=modified_before,
+ page_size=page_size,
+ primary_email_address_id=primary_email_address_id,
+ remote_fields=remote_fields,
+ remote_id=remote_id,
+ show_enum_origins=show_enum_origins,
+ user_id=user_id,
+ request_options=request_options,
+ )
+ return _response.data
+
+ async def retrieve(
+ self,
+ id: str,
+ *,
+ expand: typing.Optional[
+ typing.Union[MailboxesRetrieveRequestExpandItem, typing.Sequence[MailboxesRetrieveRequestExpandItem]]
+ ] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ remote_fields: typing.Optional[typing.Literal["type"]] = None,
+ show_enum_origins: typing.Optional[typing.Literal["type"]] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> Mailbox:
+ """
+ Returns a `Mailbox` object with the given `id`.
+
+ Parameters
+ ----------
+ id : str
+
+ expand : typing.Optional[typing.Union[MailboxesRetrieveRequestExpandItem, typing.Sequence[MailboxesRetrieveRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ remote_fields : typing.Optional[typing.Literal["type"]]
+ Deprecated. Use show_enum_origins.
+
+ show_enum_origins : typing.Optional[typing.Literal["type"]]
+ A comma separated list of enum field names for which you'd like the original values to be returned, instead of Merge's normalized enum values. [Learn more](https://help.merge.dev/en/articles/8950958-show_enum_origins-query-parameter)
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ Mailbox
+
+
+ Examples
+ --------
+ import asyncio
+
+ from merge import AsyncMerge
+
+ client = AsyncMerge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.email.mailboxes.retrieve(
+ id="id",
+ include_remote_data=True,
+ include_shell_data=True,
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.retrieve(
+ id,
+ expand=expand,
+ include_remote_data=include_remote_data,
+ include_shell_data=include_shell_data,
+ remote_fields=remote_fields,
+ show_enum_origins=show_enum_origins,
+ request_options=request_options,
+ )
+ return _response.data
diff --git a/src/merge/resources/email/resources/mailboxes/raw_client.py b/src/merge/resources/email/resources/mailboxes/raw_client.py
new file mode 100644
index 00000000..4088242a
--- /dev/null
+++ b/src/merge/resources/email/resources/mailboxes/raw_client.py
@@ -0,0 +1,401 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+from json.decoder import JSONDecodeError
+
+from .....core.api_error import ApiError
+from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .....core.datetime_utils import serialize_datetime
+from .....core.http_response import AsyncHttpResponse, HttpResponse
+from .....core.jsonable_encoder import jsonable_encoder
+from .....core.request_options import RequestOptions
+from .....core.unchecked_base_model import construct_type
+from ...types.mailbox import Mailbox
+from ...types.paginated_mailbox_list import PaginatedMailboxList
+from .types.mailboxes_list_request_expand_item import MailboxesListRequestExpandItem
+from .types.mailboxes_retrieve_request_expand_item import MailboxesRetrieveRequestExpandItem
+
+
+class RawMailboxesClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ def list(
+ self,
+ *,
+ created_after: typing.Optional[dt.datetime] = None,
+ created_before: typing.Optional[dt.datetime] = None,
+ cursor: typing.Optional[str] = None,
+ expand: typing.Optional[
+ typing.Union[MailboxesListRequestExpandItem, typing.Sequence[MailboxesListRequestExpandItem]]
+ ] = None,
+ include_deleted_data: typing.Optional[bool] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ modified_after: typing.Optional[dt.datetime] = None,
+ modified_before: typing.Optional[dt.datetime] = None,
+ page_size: typing.Optional[int] = None,
+ primary_email_address_id: typing.Optional[str] = None,
+ remote_fields: typing.Optional[typing.Literal["type"]] = None,
+ remote_id: typing.Optional[str] = None,
+ show_enum_origins: typing.Optional[typing.Literal["type"]] = None,
+ user_id: typing.Optional[str] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> HttpResponse[PaginatedMailboxList]:
+ """
+ Returns a list of `Mailbox` objects.
+
+ Parameters
+ ----------
+ created_after : typing.Optional[dt.datetime]
+ If provided, will only return objects created after this datetime.
+
+ created_before : typing.Optional[dt.datetime]
+ If provided, will only return objects created before this datetime.
+
+ cursor : typing.Optional[str]
+ The pagination cursor value.
+
+ expand : typing.Optional[typing.Union[MailboxesListRequestExpandItem, typing.Sequence[MailboxesListRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ include_deleted_data : typing.Optional[bool]
+ Indicates whether or not this object has been deleted in the third party platform. Full coverage deletion detection is a premium add-on. Native deletion detection is offered for free with limited coverage. [Learn more](https://docs.merge.dev/integrations/hris/supported-features/).
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ modified_after : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge after this date time will be returned.
+
+ modified_before : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge before this date time will be returned.
+
+ page_size : typing.Optional[int]
+ Number of results to return per page. The maximum limit is 100.
+
+ primary_email_address_id : typing.Optional[str]
+ If provided, will only return Mailboxes with this primary EmailAddress.
+
+ remote_fields : typing.Optional[typing.Literal["type"]]
+ Deprecated. Use show_enum_origins.
+
+ remote_id : typing.Optional[str]
+ The API provider's ID for the given object.
+
+ show_enum_origins : typing.Optional[typing.Literal["type"]]
+ A comma separated list of enum field names for which you'd like the original values to be returned, instead of Merge's normalized enum values. [Learn more](https://help.merge.dev/en/articles/8950958-show_enum_origins-query-parameter)
+
+ user_id : typing.Optional[str]
+ If provided, will only return Mailboxes associated with this User.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[PaginatedMailboxList]
+
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ "email/v1/mailboxes",
+ method="GET",
+ params={
+ "created_after": serialize_datetime(created_after) if created_after is not None else None,
+ "created_before": serialize_datetime(created_before) if created_before is not None else None,
+ "cursor": cursor,
+ "expand": expand,
+ "include_deleted_data": include_deleted_data,
+ "include_remote_data": include_remote_data,
+ "include_shell_data": include_shell_data,
+ "modified_after": serialize_datetime(modified_after) if modified_after is not None else None,
+ "modified_before": serialize_datetime(modified_before) if modified_before is not None else None,
+ "page_size": page_size,
+ "primary_email_address_id": primary_email_address_id,
+ "remote_fields": remote_fields,
+ "remote_id": remote_id,
+ "show_enum_origins": show_enum_origins,
+ "user_id": user_id,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ PaginatedMailboxList,
+ construct_type(
+ type_=PaginatedMailboxList, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ def retrieve(
+ self,
+ id: str,
+ *,
+ expand: typing.Optional[
+ typing.Union[MailboxesRetrieveRequestExpandItem, typing.Sequence[MailboxesRetrieveRequestExpandItem]]
+ ] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ remote_fields: typing.Optional[typing.Literal["type"]] = None,
+ show_enum_origins: typing.Optional[typing.Literal["type"]] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> HttpResponse[Mailbox]:
+ """
+ Returns a `Mailbox` object with the given `id`.
+
+ Parameters
+ ----------
+ id : str
+
+ expand : typing.Optional[typing.Union[MailboxesRetrieveRequestExpandItem, typing.Sequence[MailboxesRetrieveRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ remote_fields : typing.Optional[typing.Literal["type"]]
+ Deprecated. Use show_enum_origins.
+
+ show_enum_origins : typing.Optional[typing.Literal["type"]]
+ A comma separated list of enum field names for which you'd like the original values to be returned, instead of Merge's normalized enum values. [Learn more](https://help.merge.dev/en/articles/8950958-show_enum_origins-query-parameter)
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[Mailbox]
+
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ f"email/v1/mailboxes/{jsonable_encoder(id)}",
+ method="GET",
+ params={
+ "expand": expand,
+ "include_remote_data": include_remote_data,
+ "include_shell_data": include_shell_data,
+ "remote_fields": remote_fields,
+ "show_enum_origins": show_enum_origins,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ Mailbox,
+ construct_type(
+ type_=Mailbox, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+
+class AsyncRawMailboxesClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ async def list(
+ self,
+ *,
+ created_after: typing.Optional[dt.datetime] = None,
+ created_before: typing.Optional[dt.datetime] = None,
+ cursor: typing.Optional[str] = None,
+ expand: typing.Optional[
+ typing.Union[MailboxesListRequestExpandItem, typing.Sequence[MailboxesListRequestExpandItem]]
+ ] = None,
+ include_deleted_data: typing.Optional[bool] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ modified_after: typing.Optional[dt.datetime] = None,
+ modified_before: typing.Optional[dt.datetime] = None,
+ page_size: typing.Optional[int] = None,
+ primary_email_address_id: typing.Optional[str] = None,
+ remote_fields: typing.Optional[typing.Literal["type"]] = None,
+ remote_id: typing.Optional[str] = None,
+ show_enum_origins: typing.Optional[typing.Literal["type"]] = None,
+ user_id: typing.Optional[str] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> AsyncHttpResponse[PaginatedMailboxList]:
+ """
+ Returns a list of `Mailbox` objects.
+
+ Parameters
+ ----------
+ created_after : typing.Optional[dt.datetime]
+ If provided, will only return objects created after this datetime.
+
+ created_before : typing.Optional[dt.datetime]
+ If provided, will only return objects created before this datetime.
+
+ cursor : typing.Optional[str]
+ The pagination cursor value.
+
+ expand : typing.Optional[typing.Union[MailboxesListRequestExpandItem, typing.Sequence[MailboxesListRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ include_deleted_data : typing.Optional[bool]
+ Indicates whether or not this object has been deleted in the third party platform. Full coverage deletion detection is a premium add-on. Native deletion detection is offered for free with limited coverage. [Learn more](https://docs.merge.dev/integrations/hris/supported-features/).
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ modified_after : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge after this date time will be returned.
+
+ modified_before : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge before this date time will be returned.
+
+ page_size : typing.Optional[int]
+ Number of results to return per page. The maximum limit is 100.
+
+ primary_email_address_id : typing.Optional[str]
+ If provided, will only return Mailboxes with this primary EmailAddress.
+
+ remote_fields : typing.Optional[typing.Literal["type"]]
+ Deprecated. Use show_enum_origins.
+
+ remote_id : typing.Optional[str]
+ The API provider's ID for the given object.
+
+ show_enum_origins : typing.Optional[typing.Literal["type"]]
+ A comma separated list of enum field names for which you'd like the original values to be returned, instead of Merge's normalized enum values. [Learn more](https://help.merge.dev/en/articles/8950958-show_enum_origins-query-parameter)
+
+ user_id : typing.Optional[str]
+ If provided, will only return Mailboxes associated with this User.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[PaginatedMailboxList]
+
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ "email/v1/mailboxes",
+ method="GET",
+ params={
+ "created_after": serialize_datetime(created_after) if created_after is not None else None,
+ "created_before": serialize_datetime(created_before) if created_before is not None else None,
+ "cursor": cursor,
+ "expand": expand,
+ "include_deleted_data": include_deleted_data,
+ "include_remote_data": include_remote_data,
+ "include_shell_data": include_shell_data,
+ "modified_after": serialize_datetime(modified_after) if modified_after is not None else None,
+ "modified_before": serialize_datetime(modified_before) if modified_before is not None else None,
+ "page_size": page_size,
+ "primary_email_address_id": primary_email_address_id,
+ "remote_fields": remote_fields,
+ "remote_id": remote_id,
+ "show_enum_origins": show_enum_origins,
+ "user_id": user_id,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ PaginatedMailboxList,
+ construct_type(
+ type_=PaginatedMailboxList, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ async def retrieve(
+ self,
+ id: str,
+ *,
+ expand: typing.Optional[
+ typing.Union[MailboxesRetrieveRequestExpandItem, typing.Sequence[MailboxesRetrieveRequestExpandItem]]
+ ] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ remote_fields: typing.Optional[typing.Literal["type"]] = None,
+ show_enum_origins: typing.Optional[typing.Literal["type"]] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> AsyncHttpResponse[Mailbox]:
+ """
+ Returns a `Mailbox` object with the given `id`.
+
+ Parameters
+ ----------
+ id : str
+
+ expand : typing.Optional[typing.Union[MailboxesRetrieveRequestExpandItem, typing.Sequence[MailboxesRetrieveRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ remote_fields : typing.Optional[typing.Literal["type"]]
+ Deprecated. Use show_enum_origins.
+
+ show_enum_origins : typing.Optional[typing.Literal["type"]]
+ A comma separated list of enum field names for which you'd like the original values to be returned, instead of Merge's normalized enum values. [Learn more](https://help.merge.dev/en/articles/8950958-show_enum_origins-query-parameter)
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[Mailbox]
+
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ f"email/v1/mailboxes/{jsonable_encoder(id)}",
+ method="GET",
+ params={
+ "expand": expand,
+ "include_remote_data": include_remote_data,
+ "include_shell_data": include_shell_data,
+ "remote_fields": remote_fields,
+ "show_enum_origins": show_enum_origins,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ Mailbox,
+ construct_type(
+ type_=Mailbox, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
diff --git a/src/merge/resources/email/resources/mailboxes/types/__init__.py b/src/merge/resources/email/resources/mailboxes/types/__init__.py
new file mode 100644
index 00000000..bcefde2a
--- /dev/null
+++ b/src/merge/resources/email/resources/mailboxes/types/__init__.py
@@ -0,0 +1,36 @@
+# This file was auto-generated by Fern from our API Definition.
+
+# isort: skip_file
+
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .mailboxes_list_request_expand_item import MailboxesListRequestExpandItem
+ from .mailboxes_retrieve_request_expand_item import MailboxesRetrieveRequestExpandItem
+_dynamic_imports: typing.Dict[str, str] = {
+ "MailboxesListRequestExpandItem": ".mailboxes_list_request_expand_item",
+ "MailboxesRetrieveRequestExpandItem": ".mailboxes_retrieve_request_expand_item",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ result = getattr(module, attr_name)
+ return result
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
+
+__all__ = ["MailboxesListRequestExpandItem", "MailboxesRetrieveRequestExpandItem"]
diff --git a/src/merge/resources/email/resources/mailboxes/types/mailboxes_list_request_expand_item.py b/src/merge/resources/email/resources/mailboxes/types/mailboxes_list_request_expand_item.py
new file mode 100644
index 00000000..c8fd2ae9
--- /dev/null
+++ b/src/merge/resources/email/resources/mailboxes/types/mailboxes_list_request_expand_item.py
@@ -0,0 +1,37 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import enum
+import typing
+
+T_Result = typing.TypeVar("T_Result")
+
+
+class MailboxesListRequestExpandItem(str, enum.Enum):
+ ALIAS_EMAIL_ADDRESSES = "alias_email_addresses"
+ FOLDERS = "folders"
+ GROUPS = "groups"
+ PERMISSIONS = "permissions"
+ PRIMARY_EMAIL_ADDRESS = "primary_email_address"
+ USERS = "users"
+
+ def visit(
+ self,
+ alias_email_addresses: typing.Callable[[], T_Result],
+ folders: typing.Callable[[], T_Result],
+ groups: typing.Callable[[], T_Result],
+ permissions: typing.Callable[[], T_Result],
+ primary_email_address: typing.Callable[[], T_Result],
+ users: typing.Callable[[], T_Result],
+ ) -> T_Result:
+ if self is MailboxesListRequestExpandItem.ALIAS_EMAIL_ADDRESSES:
+ return alias_email_addresses()
+ if self is MailboxesListRequestExpandItem.FOLDERS:
+ return folders()
+ if self is MailboxesListRequestExpandItem.GROUPS:
+ return groups()
+ if self is MailboxesListRequestExpandItem.PERMISSIONS:
+ return permissions()
+ if self is MailboxesListRequestExpandItem.PRIMARY_EMAIL_ADDRESS:
+ return primary_email_address()
+ if self is MailboxesListRequestExpandItem.USERS:
+ return users()
diff --git a/src/merge/resources/email/resources/mailboxes/types/mailboxes_retrieve_request_expand_item.py b/src/merge/resources/email/resources/mailboxes/types/mailboxes_retrieve_request_expand_item.py
new file mode 100644
index 00000000..93612e43
--- /dev/null
+++ b/src/merge/resources/email/resources/mailboxes/types/mailboxes_retrieve_request_expand_item.py
@@ -0,0 +1,37 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import enum
+import typing
+
+T_Result = typing.TypeVar("T_Result")
+
+
+class MailboxesRetrieveRequestExpandItem(str, enum.Enum):
+ ALIAS_EMAIL_ADDRESSES = "alias_email_addresses"
+ FOLDERS = "folders"
+ GROUPS = "groups"
+ PERMISSIONS = "permissions"
+ PRIMARY_EMAIL_ADDRESS = "primary_email_address"
+ USERS = "users"
+
+ def visit(
+ self,
+ alias_email_addresses: typing.Callable[[], T_Result],
+ folders: typing.Callable[[], T_Result],
+ groups: typing.Callable[[], T_Result],
+ permissions: typing.Callable[[], T_Result],
+ primary_email_address: typing.Callable[[], T_Result],
+ users: typing.Callable[[], T_Result],
+ ) -> T_Result:
+ if self is MailboxesRetrieveRequestExpandItem.ALIAS_EMAIL_ADDRESSES:
+ return alias_email_addresses()
+ if self is MailboxesRetrieveRequestExpandItem.FOLDERS:
+ return folders()
+ if self is MailboxesRetrieveRequestExpandItem.GROUPS:
+ return groups()
+ if self is MailboxesRetrieveRequestExpandItem.PERMISSIONS:
+ return permissions()
+ if self is MailboxesRetrieveRequestExpandItem.PRIMARY_EMAIL_ADDRESS:
+ return primary_email_address()
+ if self is MailboxesRetrieveRequestExpandItem.USERS:
+ return users()
diff --git a/src/merge/resources/email/resources/messages/__init__.py b/src/merge/resources/email/resources/messages/__init__.py
new file mode 100644
index 00000000..73c7847d
--- /dev/null
+++ b/src/merge/resources/email/resources/messages/__init__.py
@@ -0,0 +1,35 @@
+# This file was auto-generated by Fern from our API Definition.
+
+# isort: skip_file
+
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .types import MessagesListRequestExpandItem, MessagesRetrieveRequestExpandItem
+_dynamic_imports: typing.Dict[str, str] = {
+ "MessagesListRequestExpandItem": ".types",
+ "MessagesRetrieveRequestExpandItem": ".types",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ result = getattr(module, attr_name)
+ return result
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
+
+__all__ = ["MessagesListRequestExpandItem", "MessagesRetrieveRequestExpandItem"]
diff --git a/src/merge/resources/email/resources/messages/client.py b/src/merge/resources/email/resources/messages/client.py
new file mode 100644
index 00000000..51abe88f
--- /dev/null
+++ b/src/merge/resources/email/resources/messages/client.py
@@ -0,0 +1,469 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+
+from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .....core.request_options import RequestOptions
+from ...types.message import Message
+from ...types.paginated_message_list import PaginatedMessageList
+from .raw_client import AsyncRawMessagesClient, RawMessagesClient
+from .types.messages_list_request_expand_item import MessagesListRequestExpandItem
+from .types.messages_retrieve_request_expand_item import MessagesRetrieveRequestExpandItem
+
+
+class MessagesClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._raw_client = RawMessagesClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> RawMessagesClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ RawMessagesClient
+ """
+ return self._raw_client
+
+ def list(
+ self,
+ *,
+ bcc_address_id: typing.Optional[str] = None,
+ cc_address_id: typing.Optional[str] = None,
+ created_after: typing.Optional[dt.datetime] = None,
+ created_before: typing.Optional[dt.datetime] = None,
+ cursor: typing.Optional[str] = None,
+ expand: typing.Optional[
+ typing.Union[MessagesListRequestExpandItem, typing.Sequence[MessagesListRequestExpandItem]]
+ ] = None,
+ from_address_id: typing.Optional[str] = None,
+ include_deleted_data: typing.Optional[bool] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ mailbox_id: typing.Optional[str] = None,
+ modified_after: typing.Optional[dt.datetime] = None,
+ modified_before: typing.Optional[dt.datetime] = None,
+ page_size: typing.Optional[int] = None,
+ remote_id: typing.Optional[str] = None,
+ thread_id: typing.Optional[str] = None,
+ to_address_id: typing.Optional[str] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> PaginatedMessageList:
+ """
+ Returns a list of `Message` objects.
+
+ Parameters
+ ----------
+ bcc_address_id : typing.Optional[str]
+ If provided, will only return Messages with this EmailAddress in BCC.
+
+ cc_address_id : typing.Optional[str]
+ If provided, will only return Messages with this EmailAddress in CC.
+
+ created_after : typing.Optional[dt.datetime]
+ If provided, will only return objects created after this datetime.
+
+ created_before : typing.Optional[dt.datetime]
+ If provided, will only return objects created before this datetime.
+
+ cursor : typing.Optional[str]
+ The pagination cursor value.
+
+ expand : typing.Optional[typing.Union[MessagesListRequestExpandItem, typing.Sequence[MessagesListRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ from_address_id : typing.Optional[str]
+ If provided, will only return Messages sent from this EmailAddress.
+
+ include_deleted_data : typing.Optional[bool]
+ Indicates whether or not this object has been deleted in the third party platform. Full coverage deletion detection is a premium add-on. Native deletion detection is offered for free with limited coverage. [Learn more](https://docs.merge.dev/integrations/hris/supported-features/).
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ mailbox_id : typing.Optional[str]
+ If provided, will only return Messages in this Mailbox.
+
+ modified_after : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge after this date time will be returned.
+
+ modified_before : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge before this date time will be returned.
+
+ page_size : typing.Optional[int]
+ Number of results to return per page. The maximum limit is 100.
+
+ remote_id : typing.Optional[str]
+ The API provider's ID for the given object.
+
+ thread_id : typing.Optional[str]
+ If provided, will only return Messages belonging to this Thread.
+
+ to_address_id : typing.Optional[str]
+ If provided, will only return Messages sent to this EmailAddress.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ PaginatedMessageList
+
+
+ Examples
+ --------
+ import datetime
+
+ from merge import Merge
+
+ client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+ client.email.messages.list(
+ bcc_address_id="bcc_address_id",
+ cc_address_id="cc_address_id",
+ created_after=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ created_before=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ cursor="cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw",
+ from_address_id="from_address_id",
+ include_deleted_data=True,
+ include_remote_data=True,
+ include_shell_data=True,
+ mailbox_id="mailbox_id",
+ modified_after=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ modified_before=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ page_size=1,
+ remote_id="remote_id",
+ thread_id="thread_id",
+ to_address_id="to_address_id",
+ )
+ """
+ _response = self._raw_client.list(
+ bcc_address_id=bcc_address_id,
+ cc_address_id=cc_address_id,
+ created_after=created_after,
+ created_before=created_before,
+ cursor=cursor,
+ expand=expand,
+ from_address_id=from_address_id,
+ include_deleted_data=include_deleted_data,
+ include_remote_data=include_remote_data,
+ include_shell_data=include_shell_data,
+ mailbox_id=mailbox_id,
+ modified_after=modified_after,
+ modified_before=modified_before,
+ page_size=page_size,
+ remote_id=remote_id,
+ thread_id=thread_id,
+ to_address_id=to_address_id,
+ request_options=request_options,
+ )
+ return _response.data
+
+ def retrieve(
+ self,
+ id: str,
+ *,
+ expand: typing.Optional[
+ typing.Union[MessagesRetrieveRequestExpandItem, typing.Sequence[MessagesRetrieveRequestExpandItem]]
+ ] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> Message:
+ """
+ Returns a `Message` object with the given `id`.
+
+ Parameters
+ ----------
+ id : str
+
+ expand : typing.Optional[typing.Union[MessagesRetrieveRequestExpandItem, typing.Sequence[MessagesRetrieveRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ Message
+
+
+ Examples
+ --------
+ from merge import Merge
+
+ client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+ client.email.messages.retrieve(
+ id="id",
+ include_remote_data=True,
+ include_shell_data=True,
+ )
+ """
+ _response = self._raw_client.retrieve(
+ id,
+ expand=expand,
+ include_remote_data=include_remote_data,
+ include_shell_data=include_shell_data,
+ request_options=request_options,
+ )
+ return _response.data
+
+
+class AsyncMessagesClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._raw_client = AsyncRawMessagesClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> AsyncRawMessagesClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ AsyncRawMessagesClient
+ """
+ return self._raw_client
+
+ async def list(
+ self,
+ *,
+ bcc_address_id: typing.Optional[str] = None,
+ cc_address_id: typing.Optional[str] = None,
+ created_after: typing.Optional[dt.datetime] = None,
+ created_before: typing.Optional[dt.datetime] = None,
+ cursor: typing.Optional[str] = None,
+ expand: typing.Optional[
+ typing.Union[MessagesListRequestExpandItem, typing.Sequence[MessagesListRequestExpandItem]]
+ ] = None,
+ from_address_id: typing.Optional[str] = None,
+ include_deleted_data: typing.Optional[bool] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ mailbox_id: typing.Optional[str] = None,
+ modified_after: typing.Optional[dt.datetime] = None,
+ modified_before: typing.Optional[dt.datetime] = None,
+ page_size: typing.Optional[int] = None,
+ remote_id: typing.Optional[str] = None,
+ thread_id: typing.Optional[str] = None,
+ to_address_id: typing.Optional[str] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> PaginatedMessageList:
+ """
+ Returns a list of `Message` objects.
+
+ Parameters
+ ----------
+ bcc_address_id : typing.Optional[str]
+ If provided, will only return Messages with this EmailAddress in BCC.
+
+ cc_address_id : typing.Optional[str]
+ If provided, will only return Messages with this EmailAddress in CC.
+
+ created_after : typing.Optional[dt.datetime]
+ If provided, will only return objects created after this datetime.
+
+ created_before : typing.Optional[dt.datetime]
+ If provided, will only return objects created before this datetime.
+
+ cursor : typing.Optional[str]
+ The pagination cursor value.
+
+ expand : typing.Optional[typing.Union[MessagesListRequestExpandItem, typing.Sequence[MessagesListRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ from_address_id : typing.Optional[str]
+ If provided, will only return Messages sent from this EmailAddress.
+
+ include_deleted_data : typing.Optional[bool]
+ Indicates whether or not this object has been deleted in the third party platform. Full coverage deletion detection is a premium add-on. Native deletion detection is offered for free with limited coverage. [Learn more](https://docs.merge.dev/integrations/hris/supported-features/).
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ mailbox_id : typing.Optional[str]
+ If provided, will only return Messages in this Mailbox.
+
+ modified_after : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge after this date time will be returned.
+
+ modified_before : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge before this date time will be returned.
+
+ page_size : typing.Optional[int]
+ Number of results to return per page. The maximum limit is 100.
+
+ remote_id : typing.Optional[str]
+ The API provider's ID for the given object.
+
+ thread_id : typing.Optional[str]
+ If provided, will only return Messages belonging to this Thread.
+
+ to_address_id : typing.Optional[str]
+ If provided, will only return Messages sent to this EmailAddress.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ PaginatedMessageList
+
+
+ Examples
+ --------
+ import asyncio
+ import datetime
+
+ from merge import AsyncMerge
+
+ client = AsyncMerge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.email.messages.list(
+ bcc_address_id="bcc_address_id",
+ cc_address_id="cc_address_id",
+ created_after=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ created_before=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ cursor="cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw",
+ from_address_id="from_address_id",
+ include_deleted_data=True,
+ include_remote_data=True,
+ include_shell_data=True,
+ mailbox_id="mailbox_id",
+ modified_after=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ modified_before=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ page_size=1,
+ remote_id="remote_id",
+ thread_id="thread_id",
+ to_address_id="to_address_id",
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.list(
+ bcc_address_id=bcc_address_id,
+ cc_address_id=cc_address_id,
+ created_after=created_after,
+ created_before=created_before,
+ cursor=cursor,
+ expand=expand,
+ from_address_id=from_address_id,
+ include_deleted_data=include_deleted_data,
+ include_remote_data=include_remote_data,
+ include_shell_data=include_shell_data,
+ mailbox_id=mailbox_id,
+ modified_after=modified_after,
+ modified_before=modified_before,
+ page_size=page_size,
+ remote_id=remote_id,
+ thread_id=thread_id,
+ to_address_id=to_address_id,
+ request_options=request_options,
+ )
+ return _response.data
+
+ async def retrieve(
+ self,
+ id: str,
+ *,
+ expand: typing.Optional[
+ typing.Union[MessagesRetrieveRequestExpandItem, typing.Sequence[MessagesRetrieveRequestExpandItem]]
+ ] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> Message:
+ """
+ Returns a `Message` object with the given `id`.
+
+ Parameters
+ ----------
+ id : str
+
+ expand : typing.Optional[typing.Union[MessagesRetrieveRequestExpandItem, typing.Sequence[MessagesRetrieveRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ Message
+
+
+ Examples
+ --------
+ import asyncio
+
+ from merge import AsyncMerge
+
+ client = AsyncMerge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.email.messages.retrieve(
+ id="id",
+ include_remote_data=True,
+ include_shell_data=True,
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.retrieve(
+ id,
+ expand=expand,
+ include_remote_data=include_remote_data,
+ include_shell_data=include_shell_data,
+ request_options=request_options,
+ )
+ return _response.data
diff --git a/src/merge/resources/email/resources/messages/raw_client.py b/src/merge/resources/email/resources/messages/raw_client.py
new file mode 100644
index 00000000..8e53635d
--- /dev/null
+++ b/src/merge/resources/email/resources/messages/raw_client.py
@@ -0,0 +1,401 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+from json.decoder import JSONDecodeError
+
+from .....core.api_error import ApiError
+from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .....core.datetime_utils import serialize_datetime
+from .....core.http_response import AsyncHttpResponse, HttpResponse
+from .....core.jsonable_encoder import jsonable_encoder
+from .....core.request_options import RequestOptions
+from .....core.unchecked_base_model import construct_type
+from ...types.message import Message
+from ...types.paginated_message_list import PaginatedMessageList
+from .types.messages_list_request_expand_item import MessagesListRequestExpandItem
+from .types.messages_retrieve_request_expand_item import MessagesRetrieveRequestExpandItem
+
+
+class RawMessagesClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ def list(
+ self,
+ *,
+ bcc_address_id: typing.Optional[str] = None,
+ cc_address_id: typing.Optional[str] = None,
+ created_after: typing.Optional[dt.datetime] = None,
+ created_before: typing.Optional[dt.datetime] = None,
+ cursor: typing.Optional[str] = None,
+ expand: typing.Optional[
+ typing.Union[MessagesListRequestExpandItem, typing.Sequence[MessagesListRequestExpandItem]]
+ ] = None,
+ from_address_id: typing.Optional[str] = None,
+ include_deleted_data: typing.Optional[bool] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ mailbox_id: typing.Optional[str] = None,
+ modified_after: typing.Optional[dt.datetime] = None,
+ modified_before: typing.Optional[dt.datetime] = None,
+ page_size: typing.Optional[int] = None,
+ remote_id: typing.Optional[str] = None,
+ thread_id: typing.Optional[str] = None,
+ to_address_id: typing.Optional[str] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> HttpResponse[PaginatedMessageList]:
+ """
+ Returns a list of `Message` objects.
+
+ Parameters
+ ----------
+ bcc_address_id : typing.Optional[str]
+ If provided, will only return Messages with this EmailAddress in BCC.
+
+ cc_address_id : typing.Optional[str]
+ If provided, will only return Messages with this EmailAddress in CC.
+
+ created_after : typing.Optional[dt.datetime]
+ If provided, will only return objects created after this datetime.
+
+ created_before : typing.Optional[dt.datetime]
+ If provided, will only return objects created before this datetime.
+
+ cursor : typing.Optional[str]
+ The pagination cursor value.
+
+ expand : typing.Optional[typing.Union[MessagesListRequestExpandItem, typing.Sequence[MessagesListRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ from_address_id : typing.Optional[str]
+ If provided, will only return Messages sent from this EmailAddress.
+
+ include_deleted_data : typing.Optional[bool]
+ Indicates whether or not this object has been deleted in the third party platform. Full coverage deletion detection is a premium add-on. Native deletion detection is offered for free with limited coverage. [Learn more](https://docs.merge.dev/integrations/hris/supported-features/).
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ mailbox_id : typing.Optional[str]
+ If provided, will only return Messages in this Mailbox.
+
+ modified_after : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge after this date time will be returned.
+
+ modified_before : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge before this date time will be returned.
+
+ page_size : typing.Optional[int]
+ Number of results to return per page. The maximum limit is 100.
+
+ remote_id : typing.Optional[str]
+ The API provider's ID for the given object.
+
+ thread_id : typing.Optional[str]
+ If provided, will only return Messages belonging to this Thread.
+
+ to_address_id : typing.Optional[str]
+ If provided, will only return Messages sent to this EmailAddress.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[PaginatedMessageList]
+
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ "email/v1/messages",
+ method="GET",
+ params={
+ "bcc_address_id": bcc_address_id,
+ "cc_address_id": cc_address_id,
+ "created_after": serialize_datetime(created_after) if created_after is not None else None,
+ "created_before": serialize_datetime(created_before) if created_before is not None else None,
+ "cursor": cursor,
+ "expand": expand,
+ "from_address_id": from_address_id,
+ "include_deleted_data": include_deleted_data,
+ "include_remote_data": include_remote_data,
+ "include_shell_data": include_shell_data,
+ "mailbox_id": mailbox_id,
+ "modified_after": serialize_datetime(modified_after) if modified_after is not None else None,
+ "modified_before": serialize_datetime(modified_before) if modified_before is not None else None,
+ "page_size": page_size,
+ "remote_id": remote_id,
+ "thread_id": thread_id,
+ "to_address_id": to_address_id,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ PaginatedMessageList,
+ construct_type(
+ type_=PaginatedMessageList, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ def retrieve(
+ self,
+ id: str,
+ *,
+ expand: typing.Optional[
+ typing.Union[MessagesRetrieveRequestExpandItem, typing.Sequence[MessagesRetrieveRequestExpandItem]]
+ ] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> HttpResponse[Message]:
+ """
+ Returns a `Message` object with the given `id`.
+
+ Parameters
+ ----------
+ id : str
+
+ expand : typing.Optional[typing.Union[MessagesRetrieveRequestExpandItem, typing.Sequence[MessagesRetrieveRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[Message]
+
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ f"email/v1/messages/{jsonable_encoder(id)}",
+ method="GET",
+ params={
+ "expand": expand,
+ "include_remote_data": include_remote_data,
+ "include_shell_data": include_shell_data,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ Message,
+ construct_type(
+ type_=Message, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+
+class AsyncRawMessagesClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ async def list(
+ self,
+ *,
+ bcc_address_id: typing.Optional[str] = None,
+ cc_address_id: typing.Optional[str] = None,
+ created_after: typing.Optional[dt.datetime] = None,
+ created_before: typing.Optional[dt.datetime] = None,
+ cursor: typing.Optional[str] = None,
+ expand: typing.Optional[
+ typing.Union[MessagesListRequestExpandItem, typing.Sequence[MessagesListRequestExpandItem]]
+ ] = None,
+ from_address_id: typing.Optional[str] = None,
+ include_deleted_data: typing.Optional[bool] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ mailbox_id: typing.Optional[str] = None,
+ modified_after: typing.Optional[dt.datetime] = None,
+ modified_before: typing.Optional[dt.datetime] = None,
+ page_size: typing.Optional[int] = None,
+ remote_id: typing.Optional[str] = None,
+ thread_id: typing.Optional[str] = None,
+ to_address_id: typing.Optional[str] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> AsyncHttpResponse[PaginatedMessageList]:
+ """
+ Returns a list of `Message` objects.
+
+ Parameters
+ ----------
+ bcc_address_id : typing.Optional[str]
+ If provided, will only return Messages with this EmailAddress in BCC.
+
+ cc_address_id : typing.Optional[str]
+ If provided, will only return Messages with this EmailAddress in CC.
+
+ created_after : typing.Optional[dt.datetime]
+ If provided, will only return objects created after this datetime.
+
+ created_before : typing.Optional[dt.datetime]
+ If provided, will only return objects created before this datetime.
+
+ cursor : typing.Optional[str]
+ The pagination cursor value.
+
+ expand : typing.Optional[typing.Union[MessagesListRequestExpandItem, typing.Sequence[MessagesListRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ from_address_id : typing.Optional[str]
+ If provided, will only return Messages sent from this EmailAddress.
+
+ include_deleted_data : typing.Optional[bool]
+ Indicates whether or not this object has been deleted in the third party platform. Full coverage deletion detection is a premium add-on. Native deletion detection is offered for free with limited coverage. [Learn more](https://docs.merge.dev/integrations/hris/supported-features/).
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ mailbox_id : typing.Optional[str]
+ If provided, will only return Messages in this Mailbox.
+
+ modified_after : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge after this date time will be returned.
+
+ modified_before : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge before this date time will be returned.
+
+ page_size : typing.Optional[int]
+ Number of results to return per page. The maximum limit is 100.
+
+ remote_id : typing.Optional[str]
+ The API provider's ID for the given object.
+
+ thread_id : typing.Optional[str]
+ If provided, will only return Messages belonging to this Thread.
+
+ to_address_id : typing.Optional[str]
+ If provided, will only return Messages sent to this EmailAddress.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[PaginatedMessageList]
+
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ "email/v1/messages",
+ method="GET",
+ params={
+ "bcc_address_id": bcc_address_id,
+ "cc_address_id": cc_address_id,
+ "created_after": serialize_datetime(created_after) if created_after is not None else None,
+ "created_before": serialize_datetime(created_before) if created_before is not None else None,
+ "cursor": cursor,
+ "expand": expand,
+ "from_address_id": from_address_id,
+ "include_deleted_data": include_deleted_data,
+ "include_remote_data": include_remote_data,
+ "include_shell_data": include_shell_data,
+ "mailbox_id": mailbox_id,
+ "modified_after": serialize_datetime(modified_after) if modified_after is not None else None,
+ "modified_before": serialize_datetime(modified_before) if modified_before is not None else None,
+ "page_size": page_size,
+ "remote_id": remote_id,
+ "thread_id": thread_id,
+ "to_address_id": to_address_id,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ PaginatedMessageList,
+ construct_type(
+ type_=PaginatedMessageList, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ async def retrieve(
+ self,
+ id: str,
+ *,
+ expand: typing.Optional[
+ typing.Union[MessagesRetrieveRequestExpandItem, typing.Sequence[MessagesRetrieveRequestExpandItem]]
+ ] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> AsyncHttpResponse[Message]:
+ """
+ Returns a `Message` object with the given `id`.
+
+ Parameters
+ ----------
+ id : str
+
+ expand : typing.Optional[typing.Union[MessagesRetrieveRequestExpandItem, typing.Sequence[MessagesRetrieveRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[Message]
+
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ f"email/v1/messages/{jsonable_encoder(id)}",
+ method="GET",
+ params={
+ "expand": expand,
+ "include_remote_data": include_remote_data,
+ "include_shell_data": include_shell_data,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ Message,
+ construct_type(
+ type_=Message, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
diff --git a/src/merge/resources/email/resources/messages/types/__init__.py b/src/merge/resources/email/resources/messages/types/__init__.py
new file mode 100644
index 00000000..ad26b1b4
--- /dev/null
+++ b/src/merge/resources/email/resources/messages/types/__init__.py
@@ -0,0 +1,36 @@
+# This file was auto-generated by Fern from our API Definition.
+
+# isort: skip_file
+
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .messages_list_request_expand_item import MessagesListRequestExpandItem
+ from .messages_retrieve_request_expand_item import MessagesRetrieveRequestExpandItem
+_dynamic_imports: typing.Dict[str, str] = {
+ "MessagesListRequestExpandItem": ".messages_list_request_expand_item",
+ "MessagesRetrieveRequestExpandItem": ".messages_retrieve_request_expand_item",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ result = getattr(module, attr_name)
+ return result
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
+
+__all__ = ["MessagesListRequestExpandItem", "MessagesRetrieveRequestExpandItem"]
diff --git a/src/merge/resources/email/resources/messages/types/messages_list_request_expand_item.py b/src/merge/resources/email/resources/messages/types/messages_list_request_expand_item.py
new file mode 100644
index 00000000..3355289d
--- /dev/null
+++ b/src/merge/resources/email/resources/messages/types/messages_list_request_expand_item.py
@@ -0,0 +1,45 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import enum
+import typing
+
+T_Result = typing.TypeVar("T_Result")
+
+
+class MessagesListRequestExpandItem(str, enum.Enum):
+ BCC = "bcc"
+ CC = "cc"
+ FOLDER = "folder"
+ FROM_ADDRESS = "from_address"
+ MAILBOXES = "mailboxes"
+ PERMISSIONS = "permissions"
+ THREAD = "thread"
+ TO = "to"
+
+ def visit(
+ self,
+ bcc: typing.Callable[[], T_Result],
+ cc: typing.Callable[[], T_Result],
+ folder: typing.Callable[[], T_Result],
+ from_address: typing.Callable[[], T_Result],
+ mailboxes: typing.Callable[[], T_Result],
+ permissions: typing.Callable[[], T_Result],
+ thread: typing.Callable[[], T_Result],
+ to: typing.Callable[[], T_Result],
+ ) -> T_Result:
+ if self is MessagesListRequestExpandItem.BCC:
+ return bcc()
+ if self is MessagesListRequestExpandItem.CC:
+ return cc()
+ if self is MessagesListRequestExpandItem.FOLDER:
+ return folder()
+ if self is MessagesListRequestExpandItem.FROM_ADDRESS:
+ return from_address()
+ if self is MessagesListRequestExpandItem.MAILBOXES:
+ return mailboxes()
+ if self is MessagesListRequestExpandItem.PERMISSIONS:
+ return permissions()
+ if self is MessagesListRequestExpandItem.THREAD:
+ return thread()
+ if self is MessagesListRequestExpandItem.TO:
+ return to()
diff --git a/src/merge/resources/email/resources/messages/types/messages_retrieve_request_expand_item.py b/src/merge/resources/email/resources/messages/types/messages_retrieve_request_expand_item.py
new file mode 100644
index 00000000..0ca4389f
--- /dev/null
+++ b/src/merge/resources/email/resources/messages/types/messages_retrieve_request_expand_item.py
@@ -0,0 +1,45 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import enum
+import typing
+
+T_Result = typing.TypeVar("T_Result")
+
+
+class MessagesRetrieveRequestExpandItem(str, enum.Enum):
+ BCC = "bcc"
+ CC = "cc"
+ FOLDER = "folder"
+ FROM_ADDRESS = "from_address"
+ MAILBOXES = "mailboxes"
+ PERMISSIONS = "permissions"
+ THREAD = "thread"
+ TO = "to"
+
+ def visit(
+ self,
+ bcc: typing.Callable[[], T_Result],
+ cc: typing.Callable[[], T_Result],
+ folder: typing.Callable[[], T_Result],
+ from_address: typing.Callable[[], T_Result],
+ mailboxes: typing.Callable[[], T_Result],
+ permissions: typing.Callable[[], T_Result],
+ thread: typing.Callable[[], T_Result],
+ to: typing.Callable[[], T_Result],
+ ) -> T_Result:
+ if self is MessagesRetrieveRequestExpandItem.BCC:
+ return bcc()
+ if self is MessagesRetrieveRequestExpandItem.CC:
+ return cc()
+ if self is MessagesRetrieveRequestExpandItem.FOLDER:
+ return folder()
+ if self is MessagesRetrieveRequestExpandItem.FROM_ADDRESS:
+ return from_address()
+ if self is MessagesRetrieveRequestExpandItem.MAILBOXES:
+ return mailboxes()
+ if self is MessagesRetrieveRequestExpandItem.PERMISSIONS:
+ return permissions()
+ if self is MessagesRetrieveRequestExpandItem.THREAD:
+ return thread()
+ if self is MessagesRetrieveRequestExpandItem.TO:
+ return to()
diff --git a/src/merge/resources/email/resources/passthrough/__init__.py b/src/merge/resources/email/resources/passthrough/__init__.py
new file mode 100644
index 00000000..5cde0202
--- /dev/null
+++ b/src/merge/resources/email/resources/passthrough/__init__.py
@@ -0,0 +1,4 @@
+# This file was auto-generated by Fern from our API Definition.
+
+# isort: skip_file
+
diff --git a/src/merge/resources/email/resources/passthrough/client.py b/src/merge/resources/email/resources/passthrough/client.py
new file mode 100644
index 00000000..c26cbd38
--- /dev/null
+++ b/src/merge/resources/email/resources/passthrough/client.py
@@ -0,0 +1,126 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .....core.request_options import RequestOptions
+from ...types.data_passthrough_request import DataPassthroughRequest
+from ...types.remote_response import RemoteResponse
+from .raw_client import AsyncRawPassthroughClient, RawPassthroughClient
+
+# this is used as the default value for optional parameters
+OMIT = typing.cast(typing.Any, ...)
+
+
+class PassthroughClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._raw_client = RawPassthroughClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> RawPassthroughClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ RawPassthroughClient
+ """
+ return self._raw_client
+
+ def create(
+ self, *, request: DataPassthroughRequest, request_options: typing.Optional[RequestOptions] = None
+ ) -> RemoteResponse:
+ """
+ Pull data from an endpoint not currently supported by Merge.
+
+ Parameters
+ ----------
+ request : DataPassthroughRequest
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ RemoteResponse
+
+
+ Examples
+ --------
+ from merge import Merge
+ from merge.resources.email import DataPassthroughRequest, MethodEnum
+
+ client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+ client.email.passthrough.create(
+ request=DataPassthroughRequest(
+ method=MethodEnum.GET,
+ path="/scooters",
+ ),
+ )
+ """
+ _response = self._raw_client.create(request=request, request_options=request_options)
+ return _response.data
+
+
+class AsyncPassthroughClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._raw_client = AsyncRawPassthroughClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> AsyncRawPassthroughClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ AsyncRawPassthroughClient
+ """
+ return self._raw_client
+
+ async def create(
+ self, *, request: DataPassthroughRequest, request_options: typing.Optional[RequestOptions] = None
+ ) -> RemoteResponse:
+ """
+ Pull data from an endpoint not currently supported by Merge.
+
+ Parameters
+ ----------
+ request : DataPassthroughRequest
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ RemoteResponse
+
+
+ Examples
+ --------
+ import asyncio
+
+ from merge import AsyncMerge
+ from merge.resources.email import DataPassthroughRequest, MethodEnum
+
+ client = AsyncMerge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.email.passthrough.create(
+ request=DataPassthroughRequest(
+ method=MethodEnum.GET,
+ path="/scooters",
+ ),
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.create(request=request, request_options=request_options)
+ return _response.data
diff --git a/src/merge/resources/email/resources/passthrough/raw_client.py b/src/merge/resources/email/resources/passthrough/raw_client.py
new file mode 100644
index 00000000..b3a38470
--- /dev/null
+++ b/src/merge/resources/email/resources/passthrough/raw_client.py
@@ -0,0 +1,111 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+from json.decoder import JSONDecodeError
+
+from .....core.api_error import ApiError
+from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .....core.http_response import AsyncHttpResponse, HttpResponse
+from .....core.request_options import RequestOptions
+from .....core.unchecked_base_model import construct_type
+from ...types.data_passthrough_request import DataPassthroughRequest
+from ...types.remote_response import RemoteResponse
+
+# this is used as the default value for optional parameters
+OMIT = typing.cast(typing.Any, ...)
+
+
+class RawPassthroughClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ def create(
+ self, *, request: DataPassthroughRequest, request_options: typing.Optional[RequestOptions] = None
+ ) -> HttpResponse[RemoteResponse]:
+ """
+ Pull data from an endpoint not currently supported by Merge.
+
+ Parameters
+ ----------
+ request : DataPassthroughRequest
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[RemoteResponse]
+
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ "email/v1/passthrough",
+ method="POST",
+ json=request,
+ headers={
+ "content-type": "application/json",
+ },
+ request_options=request_options,
+ omit=OMIT,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ RemoteResponse,
+ construct_type(
+ type_=RemoteResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+
+class AsyncRawPassthroughClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ async def create(
+ self, *, request: DataPassthroughRequest, request_options: typing.Optional[RequestOptions] = None
+ ) -> AsyncHttpResponse[RemoteResponse]:
+ """
+ Pull data from an endpoint not currently supported by Merge.
+
+ Parameters
+ ----------
+ request : DataPassthroughRequest
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[RemoteResponse]
+
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ "email/v1/passthrough",
+ method="POST",
+ json=request,
+ headers={
+ "content-type": "application/json",
+ },
+ request_options=request_options,
+ omit=OMIT,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ RemoteResponse,
+ construct_type(
+ type_=RemoteResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
diff --git a/src/merge/resources/email/resources/regenerate_key/__init__.py b/src/merge/resources/email/resources/regenerate_key/__init__.py
new file mode 100644
index 00000000..5cde0202
--- /dev/null
+++ b/src/merge/resources/email/resources/regenerate_key/__init__.py
@@ -0,0 +1,4 @@
+# This file was auto-generated by Fern from our API Definition.
+
+# isort: skip_file
+
diff --git a/src/merge/resources/email/resources/regenerate_key/client.py b/src/merge/resources/email/resources/regenerate_key/client.py
new file mode 100644
index 00000000..f6cdb45e
--- /dev/null
+++ b/src/merge/resources/email/resources/regenerate_key/client.py
@@ -0,0 +1,115 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .....core.request_options import RequestOptions
+from ...types.remote_key import RemoteKey
+from .raw_client import AsyncRawRegenerateKeyClient, RawRegenerateKeyClient
+
+# this is used as the default value for optional parameters
+OMIT = typing.cast(typing.Any, ...)
+
+
+class RegenerateKeyClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._raw_client = RawRegenerateKeyClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> RawRegenerateKeyClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ RawRegenerateKeyClient
+ """
+ return self._raw_client
+
+ def create(self, *, name: str, request_options: typing.Optional[RequestOptions] = None) -> RemoteKey:
+ """
+ Exchange remote keys.
+
+ Parameters
+ ----------
+ name : str
+ The name of the remote key
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ RemoteKey
+
+
+ Examples
+ --------
+ from merge import Merge
+
+ client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+ client.email.regenerate_key.create(
+ name="Remote Deployment Key 1",
+ )
+ """
+ _response = self._raw_client.create(name=name, request_options=request_options)
+ return _response.data
+
+
+class AsyncRegenerateKeyClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._raw_client = AsyncRawRegenerateKeyClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> AsyncRawRegenerateKeyClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ AsyncRawRegenerateKeyClient
+ """
+ return self._raw_client
+
+ async def create(self, *, name: str, request_options: typing.Optional[RequestOptions] = None) -> RemoteKey:
+ """
+ Exchange remote keys.
+
+ Parameters
+ ----------
+ name : str
+ The name of the remote key
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ RemoteKey
+
+
+ Examples
+ --------
+ import asyncio
+
+ from merge import AsyncMerge
+
+ client = AsyncMerge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.email.regenerate_key.create(
+ name="Remote Deployment Key 1",
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.create(name=name, request_options=request_options)
+ return _response.data
diff --git a/src/merge/resources/email/resources/regenerate_key/raw_client.py b/src/merge/resources/email/resources/regenerate_key/raw_client.py
new file mode 100644
index 00000000..95a929dc
--- /dev/null
+++ b/src/merge/resources/email/resources/regenerate_key/raw_client.py
@@ -0,0 +1,114 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+from json.decoder import JSONDecodeError
+
+from .....core.api_error import ApiError
+from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .....core.http_response import AsyncHttpResponse, HttpResponse
+from .....core.request_options import RequestOptions
+from .....core.unchecked_base_model import construct_type
+from ...types.remote_key import RemoteKey
+
+# this is used as the default value for optional parameters
+OMIT = typing.cast(typing.Any, ...)
+
+
+class RawRegenerateKeyClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ def create(self, *, name: str, request_options: typing.Optional[RequestOptions] = None) -> HttpResponse[RemoteKey]:
+ """
+ Exchange remote keys.
+
+ Parameters
+ ----------
+ name : str
+ The name of the remote key
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[RemoteKey]
+
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ "email/v1/regenerate-key",
+ method="POST",
+ json={
+ "name": name,
+ },
+ headers={
+ "content-type": "application/json",
+ },
+ request_options=request_options,
+ omit=OMIT,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ RemoteKey,
+ construct_type(
+ type_=RemoteKey, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+
+class AsyncRawRegenerateKeyClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ async def create(
+ self, *, name: str, request_options: typing.Optional[RequestOptions] = None
+ ) -> AsyncHttpResponse[RemoteKey]:
+ """
+ Exchange remote keys.
+
+ Parameters
+ ----------
+ name : str
+ The name of the remote key
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[RemoteKey]
+
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ "email/v1/regenerate-key",
+ method="POST",
+ json={
+ "name": name,
+ },
+ headers={
+ "content-type": "application/json",
+ },
+ request_options=request_options,
+ omit=OMIT,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ RemoteKey,
+ construct_type(
+ type_=RemoteKey, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
diff --git a/src/merge/resources/email/resources/scopes/__init__.py b/src/merge/resources/email/resources/scopes/__init__.py
new file mode 100644
index 00000000..5cde0202
--- /dev/null
+++ b/src/merge/resources/email/resources/scopes/__init__.py
@@ -0,0 +1,4 @@
+# This file was auto-generated by Fern from our API Definition.
+
+# isort: skip_file
+
diff --git a/src/merge/resources/email/resources/scopes/client.py b/src/merge/resources/email/resources/scopes/client.py
new file mode 100644
index 00000000..e05398de
--- /dev/null
+++ b/src/merge/resources/email/resources/scopes/client.py
@@ -0,0 +1,320 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .....core.request_options import RequestOptions
+from ...types.common_model_scope_api import CommonModelScopeApi
+from ...types.individual_common_model_scope_deserializer_request import IndividualCommonModelScopeDeserializerRequest
+from .raw_client import AsyncRawScopesClient, RawScopesClient
+
+# this is used as the default value for optional parameters
+OMIT = typing.cast(typing.Any, ...)
+
+
+class ScopesClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._raw_client = RawScopesClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> RawScopesClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ RawScopesClient
+ """
+ return self._raw_client
+
+ def default_scopes_retrieve(
+ self, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> CommonModelScopeApi:
+ """
+ Get the default permissions for Merge Common Models and fields across all Linked Accounts of a given category. [Learn more](https://help.merge.dev/en/articles/5950052-common-model-and-field-scopes).
+
+ Parameters
+ ----------
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ CommonModelScopeApi
+
+
+ Examples
+ --------
+ from merge import Merge
+
+ client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+ client.email.scopes.default_scopes_retrieve()
+ """
+ _response = self._raw_client.default_scopes_retrieve(request_options=request_options)
+ return _response.data
+
+ def linked_account_scopes_retrieve(
+ self, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> CommonModelScopeApi:
+ """
+ Get all available permissions for Merge Common Models and fields for a single Linked Account. [Learn more](https://help.merge.dev/en/articles/5950052-common-model-and-field-scopes).
+
+ Parameters
+ ----------
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ CommonModelScopeApi
+
+
+ Examples
+ --------
+ from merge import Merge
+
+ client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+ client.email.scopes.linked_account_scopes_retrieve()
+ """
+ _response = self._raw_client.linked_account_scopes_retrieve(request_options=request_options)
+ return _response.data
+
+ def linked_account_scopes_create(
+ self,
+ *,
+ common_models: typing.Sequence[IndividualCommonModelScopeDeserializerRequest],
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> CommonModelScopeApi:
+ """
+ Update permissions for any Common Model or field for a single Linked Account. Any Scopes not set in this POST request will inherit the default Scopes. [Learn more](https://help.merge.dev/en/articles/5950052-common-model-and-field-scopes)
+
+ Parameters
+ ----------
+ common_models : typing.Sequence[IndividualCommonModelScopeDeserializerRequest]
+ The common models you want to update the scopes for
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ CommonModelScopeApi
+
+
+ Examples
+ --------
+ from merge import Merge
+ from merge.resources.email import (
+ FieldPermissionDeserializerRequest,
+ IndividualCommonModelScopeDeserializerRequest,
+ ModelPermissionDeserializerRequest,
+ )
+
+ client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+ client.email.scopes.linked_account_scopes_create(
+ common_models=[
+ IndividualCommonModelScopeDeserializerRequest(
+ model_name="Employee",
+ model_permissions={
+ "READ": ModelPermissionDeserializerRequest(
+ is_enabled=True,
+ ),
+ "WRITE": ModelPermissionDeserializerRequest(
+ is_enabled=False,
+ ),
+ },
+ field_permissions=FieldPermissionDeserializerRequest(
+ enabled_fields=["avatar", "home_location"],
+ disabled_fields=["work_location"],
+ ),
+ ),
+ IndividualCommonModelScopeDeserializerRequest(
+ model_name="Benefit",
+ model_permissions={
+ "WRITE": ModelPermissionDeserializerRequest(
+ is_enabled=False,
+ )
+ },
+ ),
+ ],
+ )
+ """
+ _response = self._raw_client.linked_account_scopes_create(
+ common_models=common_models, request_options=request_options
+ )
+ return _response.data
+
+
+class AsyncScopesClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._raw_client = AsyncRawScopesClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> AsyncRawScopesClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ AsyncRawScopesClient
+ """
+ return self._raw_client
+
+ async def default_scopes_retrieve(
+ self, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> CommonModelScopeApi:
+ """
+ Get the default permissions for Merge Common Models and fields across all Linked Accounts of a given category. [Learn more](https://help.merge.dev/en/articles/5950052-common-model-and-field-scopes).
+
+ Parameters
+ ----------
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ CommonModelScopeApi
+
+
+ Examples
+ --------
+ import asyncio
+
+ from merge import AsyncMerge
+
+ client = AsyncMerge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.email.scopes.default_scopes_retrieve()
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.default_scopes_retrieve(request_options=request_options)
+ return _response.data
+
+ async def linked_account_scopes_retrieve(
+ self, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> CommonModelScopeApi:
+ """
+ Get all available permissions for Merge Common Models and fields for a single Linked Account. [Learn more](https://help.merge.dev/en/articles/5950052-common-model-and-field-scopes).
+
+ Parameters
+ ----------
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ CommonModelScopeApi
+
+
+ Examples
+ --------
+ import asyncio
+
+ from merge import AsyncMerge
+
+ client = AsyncMerge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.email.scopes.linked_account_scopes_retrieve()
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.linked_account_scopes_retrieve(request_options=request_options)
+ return _response.data
+
+ async def linked_account_scopes_create(
+ self,
+ *,
+ common_models: typing.Sequence[IndividualCommonModelScopeDeserializerRequest],
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> CommonModelScopeApi:
+ """
+ Update permissions for any Common Model or field for a single Linked Account. Any Scopes not set in this POST request will inherit the default Scopes. [Learn more](https://help.merge.dev/en/articles/5950052-common-model-and-field-scopes)
+
+ Parameters
+ ----------
+ common_models : typing.Sequence[IndividualCommonModelScopeDeserializerRequest]
+ The common models you want to update the scopes for
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ CommonModelScopeApi
+
+
+ Examples
+ --------
+ import asyncio
+
+ from merge import AsyncMerge
+ from merge.resources.email import (
+ FieldPermissionDeserializerRequest,
+ IndividualCommonModelScopeDeserializerRequest,
+ ModelPermissionDeserializerRequest,
+ )
+
+ client = AsyncMerge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.email.scopes.linked_account_scopes_create(
+ common_models=[
+ IndividualCommonModelScopeDeserializerRequest(
+ model_name="Employee",
+ model_permissions={
+ "READ": ModelPermissionDeserializerRequest(
+ is_enabled=True,
+ ),
+ "WRITE": ModelPermissionDeserializerRequest(
+ is_enabled=False,
+ ),
+ },
+ field_permissions=FieldPermissionDeserializerRequest(
+ enabled_fields=["avatar", "home_location"],
+ disabled_fields=["work_location"],
+ ),
+ ),
+ IndividualCommonModelScopeDeserializerRequest(
+ model_name="Benefit",
+ model_permissions={
+ "WRITE": ModelPermissionDeserializerRequest(
+ is_enabled=False,
+ )
+ },
+ ),
+ ],
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.linked_account_scopes_create(
+ common_models=common_models, request_options=request_options
+ )
+ return _response.data
diff --git a/src/merge/resources/email/resources/scopes/raw_client.py b/src/merge/resources/email/resources/scopes/raw_client.py
new file mode 100644
index 00000000..06ed7503
--- /dev/null
+++ b/src/merge/resources/email/resources/scopes/raw_client.py
@@ -0,0 +1,267 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+from json.decoder import JSONDecodeError
+
+from .....core.api_error import ApiError
+from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .....core.http_response import AsyncHttpResponse, HttpResponse
+from .....core.request_options import RequestOptions
+from .....core.unchecked_base_model import construct_type
+from ...types.common_model_scope_api import CommonModelScopeApi
+from ...types.individual_common_model_scope_deserializer_request import IndividualCommonModelScopeDeserializerRequest
+
+# this is used as the default value for optional parameters
+OMIT = typing.cast(typing.Any, ...)
+
+
+class RawScopesClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ def default_scopes_retrieve(
+ self, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> HttpResponse[CommonModelScopeApi]:
+ """
+ Get the default permissions for Merge Common Models and fields across all Linked Accounts of a given category. [Learn more](https://help.merge.dev/en/articles/5950052-common-model-and-field-scopes).
+
+ Parameters
+ ----------
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[CommonModelScopeApi]
+
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ "email/v1/default-scopes",
+ method="GET",
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ CommonModelScopeApi,
+ construct_type(
+ type_=CommonModelScopeApi, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ def linked_account_scopes_retrieve(
+ self, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> HttpResponse[CommonModelScopeApi]:
+ """
+ Get all available permissions for Merge Common Models and fields for a single Linked Account. [Learn more](https://help.merge.dev/en/articles/5950052-common-model-and-field-scopes).
+
+ Parameters
+ ----------
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[CommonModelScopeApi]
+
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ "email/v1/linked-account-scopes",
+ method="GET",
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ CommonModelScopeApi,
+ construct_type(
+ type_=CommonModelScopeApi, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ def linked_account_scopes_create(
+ self,
+ *,
+ common_models: typing.Sequence[IndividualCommonModelScopeDeserializerRequest],
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> HttpResponse[CommonModelScopeApi]:
+ """
+ Update permissions for any Common Model or field for a single Linked Account. Any Scopes not set in this POST request will inherit the default Scopes. [Learn more](https://help.merge.dev/en/articles/5950052-common-model-and-field-scopes)
+
+ Parameters
+ ----------
+ common_models : typing.Sequence[IndividualCommonModelScopeDeserializerRequest]
+ The common models you want to update the scopes for
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[CommonModelScopeApi]
+
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ "email/v1/linked-account-scopes",
+ method="POST",
+ json={
+ "common_models": common_models,
+ },
+ headers={
+ "content-type": "application/json",
+ },
+ request_options=request_options,
+ omit=OMIT,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ CommonModelScopeApi,
+ construct_type(
+ type_=CommonModelScopeApi, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+
+class AsyncRawScopesClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ async def default_scopes_retrieve(
+ self, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> AsyncHttpResponse[CommonModelScopeApi]:
+ """
+ Get the default permissions for Merge Common Models and fields across all Linked Accounts of a given category. [Learn more](https://help.merge.dev/en/articles/5950052-common-model-and-field-scopes).
+
+ Parameters
+ ----------
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[CommonModelScopeApi]
+
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ "email/v1/default-scopes",
+ method="GET",
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ CommonModelScopeApi,
+ construct_type(
+ type_=CommonModelScopeApi, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ async def linked_account_scopes_retrieve(
+ self, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> AsyncHttpResponse[CommonModelScopeApi]:
+ """
+ Get all available permissions for Merge Common Models and fields for a single Linked Account. [Learn more](https://help.merge.dev/en/articles/5950052-common-model-and-field-scopes).
+
+ Parameters
+ ----------
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[CommonModelScopeApi]
+
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ "email/v1/linked-account-scopes",
+ method="GET",
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ CommonModelScopeApi,
+ construct_type(
+ type_=CommonModelScopeApi, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ async def linked_account_scopes_create(
+ self,
+ *,
+ common_models: typing.Sequence[IndividualCommonModelScopeDeserializerRequest],
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> AsyncHttpResponse[CommonModelScopeApi]:
+ """
+ Update permissions for any Common Model or field for a single Linked Account. Any Scopes not set in this POST request will inherit the default Scopes. [Learn more](https://help.merge.dev/en/articles/5950052-common-model-and-field-scopes)
+
+ Parameters
+ ----------
+ common_models : typing.Sequence[IndividualCommonModelScopeDeserializerRequest]
+ The common models you want to update the scopes for
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[CommonModelScopeApi]
+
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ "email/v1/linked-account-scopes",
+ method="POST",
+ json={
+ "common_models": common_models,
+ },
+ headers={
+ "content-type": "application/json",
+ },
+ request_options=request_options,
+ omit=OMIT,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ CommonModelScopeApi,
+ construct_type(
+ type_=CommonModelScopeApi, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
diff --git a/src/merge/resources/email/resources/sync_status/__init__.py b/src/merge/resources/email/resources/sync_status/__init__.py
new file mode 100644
index 00000000..5cde0202
--- /dev/null
+++ b/src/merge/resources/email/resources/sync_status/__init__.py
@@ -0,0 +1,4 @@
+# This file was auto-generated by Fern from our API Definition.
+
+# isort: skip_file
+
diff --git a/src/merge/resources/email/resources/sync_status/client.py b/src/merge/resources/email/resources/sync_status/client.py
new file mode 100644
index 00000000..11097cc2
--- /dev/null
+++ b/src/merge/resources/email/resources/sync_status/client.py
@@ -0,0 +1,132 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .....core.request_options import RequestOptions
+from ...types.paginated_sync_status_list import PaginatedSyncStatusList
+from .raw_client import AsyncRawSyncStatusClient, RawSyncStatusClient
+
+
+class SyncStatusClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._raw_client = RawSyncStatusClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> RawSyncStatusClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ RawSyncStatusClient
+ """
+ return self._raw_client
+
+ def list(
+ self,
+ *,
+ cursor: typing.Optional[str] = None,
+ page_size: typing.Optional[int] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> PaginatedSyncStatusList:
+ """
+ Get sync status for the current sync and the most recently finished sync. `last_sync_start` represents the most recent time any sync began. `last_sync_finished` represents the most recent time any sync completed. These timestamps may correspond to different sync instances which may result in a sync start time being later than a separate sync completed time. To ensure you are retrieving the latest available data reference the `last_sync_finished` timestamp where `last_sync_result` is `DONE`. Possible values for `status` and `last_sync_result` are `DISABLED`, `DONE`, `FAILED`, `PARTIALLY_SYNCED`, `PAUSED`, `SYNCING`. Learn more about sync status in our [Help Center](https://help.merge.dev/en/articles/8184193-merge-sync-statuses).
+
+ Parameters
+ ----------
+ cursor : typing.Optional[str]
+ The pagination cursor value.
+
+ page_size : typing.Optional[int]
+ Number of results to return per page. The maximum limit is 100.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ PaginatedSyncStatusList
+
+
+ Examples
+ --------
+ from merge import Merge
+
+ client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+ client.email.sync_status.list(
+ cursor="cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw",
+ page_size=1,
+ )
+ """
+ _response = self._raw_client.list(cursor=cursor, page_size=page_size, request_options=request_options)
+ return _response.data
+
+
+class AsyncSyncStatusClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._raw_client = AsyncRawSyncStatusClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> AsyncRawSyncStatusClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ AsyncRawSyncStatusClient
+ """
+ return self._raw_client
+
+ async def list(
+ self,
+ *,
+ cursor: typing.Optional[str] = None,
+ page_size: typing.Optional[int] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> PaginatedSyncStatusList:
+ """
+ Get sync status for the current sync and the most recently finished sync. `last_sync_start` represents the most recent time any sync began. `last_sync_finished` represents the most recent time any sync completed. These timestamps may correspond to different sync instances which may result in a sync start time being later than a separate sync completed time. To ensure you are retrieving the latest available data reference the `last_sync_finished` timestamp where `last_sync_result` is `DONE`. Possible values for `status` and `last_sync_result` are `DISABLED`, `DONE`, `FAILED`, `PARTIALLY_SYNCED`, `PAUSED`, `SYNCING`. Learn more about sync status in our [Help Center](https://help.merge.dev/en/articles/8184193-merge-sync-statuses).
+
+ Parameters
+ ----------
+ cursor : typing.Optional[str]
+ The pagination cursor value.
+
+ page_size : typing.Optional[int]
+ Number of results to return per page. The maximum limit is 100.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ PaginatedSyncStatusList
+
+
+ Examples
+ --------
+ import asyncio
+
+ from merge import AsyncMerge
+
+ client = AsyncMerge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.email.sync_status.list(
+ cursor="cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw",
+ page_size=1,
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.list(cursor=cursor, page_size=page_size, request_options=request_options)
+ return _response.data
diff --git a/src/merge/resources/email/resources/sync_status/raw_client.py b/src/merge/resources/email/resources/sync_status/raw_client.py
new file mode 100644
index 00000000..3bcee066
--- /dev/null
+++ b/src/merge/resources/email/resources/sync_status/raw_client.py
@@ -0,0 +1,121 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+from json.decoder import JSONDecodeError
+
+from .....core.api_error import ApiError
+from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .....core.http_response import AsyncHttpResponse, HttpResponse
+from .....core.request_options import RequestOptions
+from .....core.unchecked_base_model import construct_type
+from ...types.paginated_sync_status_list import PaginatedSyncStatusList
+
+
+class RawSyncStatusClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ def list(
+ self,
+ *,
+ cursor: typing.Optional[str] = None,
+ page_size: typing.Optional[int] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> HttpResponse[PaginatedSyncStatusList]:
+ """
+ Get sync status for the current sync and the most recently finished sync. `last_sync_start` represents the most recent time any sync began. `last_sync_finished` represents the most recent time any sync completed. These timestamps may correspond to different sync instances which may result in a sync start time being later than a separate sync completed time. To ensure you are retrieving the latest available data reference the `last_sync_finished` timestamp where `last_sync_result` is `DONE`. Possible values for `status` and `last_sync_result` are `DISABLED`, `DONE`, `FAILED`, `PARTIALLY_SYNCED`, `PAUSED`, `SYNCING`. Learn more about sync status in our [Help Center](https://help.merge.dev/en/articles/8184193-merge-sync-statuses).
+
+ Parameters
+ ----------
+ cursor : typing.Optional[str]
+ The pagination cursor value.
+
+ page_size : typing.Optional[int]
+ Number of results to return per page. The maximum limit is 100.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[PaginatedSyncStatusList]
+
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ "email/v1/sync-status",
+ method="GET",
+ params={
+ "cursor": cursor,
+ "page_size": page_size,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ PaginatedSyncStatusList,
+ construct_type(
+ type_=PaginatedSyncStatusList, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+
+class AsyncRawSyncStatusClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ async def list(
+ self,
+ *,
+ cursor: typing.Optional[str] = None,
+ page_size: typing.Optional[int] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> AsyncHttpResponse[PaginatedSyncStatusList]:
+ """
+ Get sync status for the current sync and the most recently finished sync. `last_sync_start` represents the most recent time any sync began. `last_sync_finished` represents the most recent time any sync completed. These timestamps may correspond to different sync instances which may result in a sync start time being later than a separate sync completed time. To ensure you are retrieving the latest available data reference the `last_sync_finished` timestamp where `last_sync_result` is `DONE`. Possible values for `status` and `last_sync_result` are `DISABLED`, `DONE`, `FAILED`, `PARTIALLY_SYNCED`, `PAUSED`, `SYNCING`. Learn more about sync status in our [Help Center](https://help.merge.dev/en/articles/8184193-merge-sync-statuses).
+
+ Parameters
+ ----------
+ cursor : typing.Optional[str]
+ The pagination cursor value.
+
+ page_size : typing.Optional[int]
+ Number of results to return per page. The maximum limit is 100.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[PaginatedSyncStatusList]
+
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ "email/v1/sync-status",
+ method="GET",
+ params={
+ "cursor": cursor,
+ "page_size": page_size,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ PaginatedSyncStatusList,
+ construct_type(
+ type_=PaginatedSyncStatusList, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
diff --git a/src/merge/resources/email/resources/users/__init__.py b/src/merge/resources/email/resources/users/__init__.py
new file mode 100644
index 00000000..8e4fa9ff
--- /dev/null
+++ b/src/merge/resources/email/resources/users/__init__.py
@@ -0,0 +1,35 @@
+# This file was auto-generated by Fern from our API Definition.
+
+# isort: skip_file
+
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .types import UsersListRequestExpandItem, UsersRetrieveRequestExpandItem
+_dynamic_imports: typing.Dict[str, str] = {
+ "UsersListRequestExpandItem": ".types",
+ "UsersRetrieveRequestExpandItem": ".types",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ result = getattr(module, attr_name)
+ return result
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
+
+__all__ = ["UsersListRequestExpandItem", "UsersRetrieveRequestExpandItem"]
diff --git a/src/merge/resources/email/resources/users/client.py b/src/merge/resources/email/resources/users/client.py
new file mode 100644
index 00000000..8228a09e
--- /dev/null
+++ b/src/merge/resources/email/resources/users/client.py
@@ -0,0 +1,473 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+
+from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .....core.request_options import RequestOptions
+from ...types.paginated_user_list import PaginatedUserList
+from ...types.user import User
+from .raw_client import AsyncRawUsersClient, RawUsersClient
+from .types.users_list_request_expand_item import UsersListRequestExpandItem
+from .types.users_retrieve_request_expand_item import UsersRetrieveRequestExpandItem
+
+
+class UsersClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._raw_client = RawUsersClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> RawUsersClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ RawUsersClient
+ """
+ return self._raw_client
+
+ def list(
+ self,
+ *,
+ created_after: typing.Optional[dt.datetime] = None,
+ created_before: typing.Optional[dt.datetime] = None,
+ cursor: typing.Optional[str] = None,
+ email_address_id: typing.Optional[str] = None,
+ expand: typing.Optional[
+ typing.Union[UsersListRequestExpandItem, typing.Sequence[UsersListRequestExpandItem]]
+ ] = None,
+ group_id: typing.Optional[str] = None,
+ include_deleted_data: typing.Optional[bool] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ mailbox_id: typing.Optional[str] = None,
+ modified_after: typing.Optional[dt.datetime] = None,
+ modified_before: typing.Optional[dt.datetime] = None,
+ page_size: typing.Optional[int] = None,
+ remote_fields: typing.Optional[typing.Literal["type"]] = None,
+ remote_id: typing.Optional[str] = None,
+ show_enum_origins: typing.Optional[typing.Literal["type"]] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> PaginatedUserList:
+ """
+ Returns a list of `User` objects.
+
+ Parameters
+ ----------
+ created_after : typing.Optional[dt.datetime]
+ If provided, will only return objects created after this datetime.
+
+ created_before : typing.Optional[dt.datetime]
+ If provided, will only return objects created before this datetime.
+
+ cursor : typing.Optional[str]
+ The pagination cursor value.
+
+ email_address_id : typing.Optional[str]
+ If provided, will only return Users with this EmailAddress.
+
+ expand : typing.Optional[typing.Union[UsersListRequestExpandItem, typing.Sequence[UsersListRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ group_id : typing.Optional[str]
+ If provided, will only return Users belonging to this Group.
+
+ include_deleted_data : typing.Optional[bool]
+ Indicates whether or not this object has been deleted in the third party platform. Full coverage deletion detection is a premium add-on. Native deletion detection is offered for free with limited coverage. [Learn more](https://docs.merge.dev/integrations/hris/supported-features/).
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ mailbox_id : typing.Optional[str]
+ If provided, will only return Users associated with this Mailbox.
+
+ modified_after : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge after this date time will be returned.
+
+ modified_before : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge before this date time will be returned.
+
+ page_size : typing.Optional[int]
+ Number of results to return per page. The maximum limit is 100.
+
+ remote_fields : typing.Optional[typing.Literal["type"]]
+ Deprecated. Use show_enum_origins.
+
+ remote_id : typing.Optional[str]
+ The API provider's ID for the given object.
+
+ show_enum_origins : typing.Optional[typing.Literal["type"]]
+ A comma separated list of enum field names for which you'd like the original values to be returned, instead of Merge's normalized enum values. [Learn more](https://help.merge.dev/en/articles/8950958-show_enum_origins-query-parameter)
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ PaginatedUserList
+
+
+ Examples
+ --------
+ import datetime
+
+ from merge import Merge
+
+ client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+ client.email.users.list(
+ created_after=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ created_before=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ cursor="cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw",
+ email_address_id="email_address_id",
+ group_id="group_id",
+ include_deleted_data=True,
+ include_remote_data=True,
+ include_shell_data=True,
+ mailbox_id="mailbox_id",
+ modified_after=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ modified_before=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ page_size=1,
+ remote_id="remote_id",
+ )
+ """
+ _response = self._raw_client.list(
+ created_after=created_after,
+ created_before=created_before,
+ cursor=cursor,
+ email_address_id=email_address_id,
+ expand=expand,
+ group_id=group_id,
+ include_deleted_data=include_deleted_data,
+ include_remote_data=include_remote_data,
+ include_shell_data=include_shell_data,
+ mailbox_id=mailbox_id,
+ modified_after=modified_after,
+ modified_before=modified_before,
+ page_size=page_size,
+ remote_fields=remote_fields,
+ remote_id=remote_id,
+ show_enum_origins=show_enum_origins,
+ request_options=request_options,
+ )
+ return _response.data
+
+ def retrieve(
+ self,
+ id: str,
+ *,
+ expand: typing.Optional[
+ typing.Union[UsersRetrieveRequestExpandItem, typing.Sequence[UsersRetrieveRequestExpandItem]]
+ ] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ remote_fields: typing.Optional[typing.Literal["type"]] = None,
+ show_enum_origins: typing.Optional[typing.Literal["type"]] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> User:
+ """
+ Returns a `User` object with the given `id`.
+
+ Parameters
+ ----------
+ id : str
+
+ expand : typing.Optional[typing.Union[UsersRetrieveRequestExpandItem, typing.Sequence[UsersRetrieveRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ remote_fields : typing.Optional[typing.Literal["type"]]
+ Deprecated. Use show_enum_origins.
+
+ show_enum_origins : typing.Optional[typing.Literal["type"]]
+ A comma separated list of enum field names for which you'd like the original values to be returned, instead of Merge's normalized enum values. [Learn more](https://help.merge.dev/en/articles/8950958-show_enum_origins-query-parameter)
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ User
+
+
+ Examples
+ --------
+ from merge import Merge
+
+ client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+ client.email.users.retrieve(
+ id="id",
+ include_remote_data=True,
+ include_shell_data=True,
+ )
+ """
+ _response = self._raw_client.retrieve(
+ id,
+ expand=expand,
+ include_remote_data=include_remote_data,
+ include_shell_data=include_shell_data,
+ remote_fields=remote_fields,
+ show_enum_origins=show_enum_origins,
+ request_options=request_options,
+ )
+ return _response.data
+
+
+class AsyncUsersClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._raw_client = AsyncRawUsersClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> AsyncRawUsersClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ AsyncRawUsersClient
+ """
+ return self._raw_client
+
+ async def list(
+ self,
+ *,
+ created_after: typing.Optional[dt.datetime] = None,
+ created_before: typing.Optional[dt.datetime] = None,
+ cursor: typing.Optional[str] = None,
+ email_address_id: typing.Optional[str] = None,
+ expand: typing.Optional[
+ typing.Union[UsersListRequestExpandItem, typing.Sequence[UsersListRequestExpandItem]]
+ ] = None,
+ group_id: typing.Optional[str] = None,
+ include_deleted_data: typing.Optional[bool] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ mailbox_id: typing.Optional[str] = None,
+ modified_after: typing.Optional[dt.datetime] = None,
+ modified_before: typing.Optional[dt.datetime] = None,
+ page_size: typing.Optional[int] = None,
+ remote_fields: typing.Optional[typing.Literal["type"]] = None,
+ remote_id: typing.Optional[str] = None,
+ show_enum_origins: typing.Optional[typing.Literal["type"]] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> PaginatedUserList:
+ """
+ Returns a list of `User` objects.
+
+ Parameters
+ ----------
+ created_after : typing.Optional[dt.datetime]
+ If provided, will only return objects created after this datetime.
+
+ created_before : typing.Optional[dt.datetime]
+ If provided, will only return objects created before this datetime.
+
+ cursor : typing.Optional[str]
+ The pagination cursor value.
+
+ email_address_id : typing.Optional[str]
+ If provided, will only return Users with this EmailAddress.
+
+ expand : typing.Optional[typing.Union[UsersListRequestExpandItem, typing.Sequence[UsersListRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ group_id : typing.Optional[str]
+ If provided, will only return Users belonging to this Group.
+
+ include_deleted_data : typing.Optional[bool]
+ Indicates whether or not this object has been deleted in the third party platform. Full coverage deletion detection is a premium add-on. Native deletion detection is offered for free with limited coverage. [Learn more](https://docs.merge.dev/integrations/hris/supported-features/).
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ mailbox_id : typing.Optional[str]
+ If provided, will only return Users associated with this Mailbox.
+
+ modified_after : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge after this date time will be returned.
+
+ modified_before : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge before this date time will be returned.
+
+ page_size : typing.Optional[int]
+ Number of results to return per page. The maximum limit is 100.
+
+ remote_fields : typing.Optional[typing.Literal["type"]]
+ Deprecated. Use show_enum_origins.
+
+ remote_id : typing.Optional[str]
+ The API provider's ID for the given object.
+
+ show_enum_origins : typing.Optional[typing.Literal["type"]]
+ A comma separated list of enum field names for which you'd like the original values to be returned, instead of Merge's normalized enum values. [Learn more](https://help.merge.dev/en/articles/8950958-show_enum_origins-query-parameter)
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ PaginatedUserList
+
+
+ Examples
+ --------
+ import asyncio
+ import datetime
+
+ from merge import AsyncMerge
+
+ client = AsyncMerge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.email.users.list(
+ created_after=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ created_before=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ cursor="cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw",
+ email_address_id="email_address_id",
+ group_id="group_id",
+ include_deleted_data=True,
+ include_remote_data=True,
+ include_shell_data=True,
+ mailbox_id="mailbox_id",
+ modified_after=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ modified_before=datetime.datetime.fromisoformat(
+ "2024-01-15 09:30:00+00:00",
+ ),
+ page_size=1,
+ remote_id="remote_id",
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.list(
+ created_after=created_after,
+ created_before=created_before,
+ cursor=cursor,
+ email_address_id=email_address_id,
+ expand=expand,
+ group_id=group_id,
+ include_deleted_data=include_deleted_data,
+ include_remote_data=include_remote_data,
+ include_shell_data=include_shell_data,
+ mailbox_id=mailbox_id,
+ modified_after=modified_after,
+ modified_before=modified_before,
+ page_size=page_size,
+ remote_fields=remote_fields,
+ remote_id=remote_id,
+ show_enum_origins=show_enum_origins,
+ request_options=request_options,
+ )
+ return _response.data
+
+ async def retrieve(
+ self,
+ id: str,
+ *,
+ expand: typing.Optional[
+ typing.Union[UsersRetrieveRequestExpandItem, typing.Sequence[UsersRetrieveRequestExpandItem]]
+ ] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ remote_fields: typing.Optional[typing.Literal["type"]] = None,
+ show_enum_origins: typing.Optional[typing.Literal["type"]] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> User:
+ """
+ Returns a `User` object with the given `id`.
+
+ Parameters
+ ----------
+ id : str
+
+ expand : typing.Optional[typing.Union[UsersRetrieveRequestExpandItem, typing.Sequence[UsersRetrieveRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ remote_fields : typing.Optional[typing.Literal["type"]]
+ Deprecated. Use show_enum_origins.
+
+ show_enum_origins : typing.Optional[typing.Literal["type"]]
+ A comma separated list of enum field names for which you'd like the original values to be returned, instead of Merge's normalized enum values. [Learn more](https://help.merge.dev/en/articles/8950958-show_enum_origins-query-parameter)
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ User
+
+
+ Examples
+ --------
+ import asyncio
+
+ from merge import AsyncMerge
+
+ client = AsyncMerge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.email.users.retrieve(
+ id="id",
+ include_remote_data=True,
+ include_shell_data=True,
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.retrieve(
+ id,
+ expand=expand,
+ include_remote_data=include_remote_data,
+ include_shell_data=include_shell_data,
+ remote_fields=remote_fields,
+ show_enum_origins=show_enum_origins,
+ request_options=request_options,
+ )
+ return _response.data
diff --git a/src/merge/resources/email/resources/users/raw_client.py b/src/merge/resources/email/resources/users/raw_client.py
new file mode 100644
index 00000000..fbee541a
--- /dev/null
+++ b/src/merge/resources/email/resources/users/raw_client.py
@@ -0,0 +1,411 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+from json.decoder import JSONDecodeError
+
+from .....core.api_error import ApiError
+from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .....core.datetime_utils import serialize_datetime
+from .....core.http_response import AsyncHttpResponse, HttpResponse
+from .....core.jsonable_encoder import jsonable_encoder
+from .....core.request_options import RequestOptions
+from .....core.unchecked_base_model import construct_type
+from ...types.paginated_user_list import PaginatedUserList
+from ...types.user import User
+from .types.users_list_request_expand_item import UsersListRequestExpandItem
+from .types.users_retrieve_request_expand_item import UsersRetrieveRequestExpandItem
+
+
+class RawUsersClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ def list(
+ self,
+ *,
+ created_after: typing.Optional[dt.datetime] = None,
+ created_before: typing.Optional[dt.datetime] = None,
+ cursor: typing.Optional[str] = None,
+ email_address_id: typing.Optional[str] = None,
+ expand: typing.Optional[
+ typing.Union[UsersListRequestExpandItem, typing.Sequence[UsersListRequestExpandItem]]
+ ] = None,
+ group_id: typing.Optional[str] = None,
+ include_deleted_data: typing.Optional[bool] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ mailbox_id: typing.Optional[str] = None,
+ modified_after: typing.Optional[dt.datetime] = None,
+ modified_before: typing.Optional[dt.datetime] = None,
+ page_size: typing.Optional[int] = None,
+ remote_fields: typing.Optional[typing.Literal["type"]] = None,
+ remote_id: typing.Optional[str] = None,
+ show_enum_origins: typing.Optional[typing.Literal["type"]] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> HttpResponse[PaginatedUserList]:
+ """
+ Returns a list of `User` objects.
+
+ Parameters
+ ----------
+ created_after : typing.Optional[dt.datetime]
+ If provided, will only return objects created after this datetime.
+
+ created_before : typing.Optional[dt.datetime]
+ If provided, will only return objects created before this datetime.
+
+ cursor : typing.Optional[str]
+ The pagination cursor value.
+
+ email_address_id : typing.Optional[str]
+ If provided, will only return Users with this EmailAddress.
+
+ expand : typing.Optional[typing.Union[UsersListRequestExpandItem, typing.Sequence[UsersListRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ group_id : typing.Optional[str]
+ If provided, will only return Users belonging to this Group.
+
+ include_deleted_data : typing.Optional[bool]
+ Indicates whether or not this object has been deleted in the third party platform. Full coverage deletion detection is a premium add-on. Native deletion detection is offered for free with limited coverage. [Learn more](https://docs.merge.dev/integrations/hris/supported-features/).
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ mailbox_id : typing.Optional[str]
+ If provided, will only return Users associated with this Mailbox.
+
+ modified_after : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge after this date time will be returned.
+
+ modified_before : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge before this date time will be returned.
+
+ page_size : typing.Optional[int]
+ Number of results to return per page. The maximum limit is 100.
+
+ remote_fields : typing.Optional[typing.Literal["type"]]
+ Deprecated. Use show_enum_origins.
+
+ remote_id : typing.Optional[str]
+ The API provider's ID for the given object.
+
+ show_enum_origins : typing.Optional[typing.Literal["type"]]
+ A comma separated list of enum field names for which you'd like the original values to be returned, instead of Merge's normalized enum values. [Learn more](https://help.merge.dev/en/articles/8950958-show_enum_origins-query-parameter)
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[PaginatedUserList]
+
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ "email/v1/users",
+ method="GET",
+ params={
+ "created_after": serialize_datetime(created_after) if created_after is not None else None,
+ "created_before": serialize_datetime(created_before) if created_before is not None else None,
+ "cursor": cursor,
+ "email_address_id": email_address_id,
+ "expand": expand,
+ "group_id": group_id,
+ "include_deleted_data": include_deleted_data,
+ "include_remote_data": include_remote_data,
+ "include_shell_data": include_shell_data,
+ "mailbox_id": mailbox_id,
+ "modified_after": serialize_datetime(modified_after) if modified_after is not None else None,
+ "modified_before": serialize_datetime(modified_before) if modified_before is not None else None,
+ "page_size": page_size,
+ "remote_fields": remote_fields,
+ "remote_id": remote_id,
+ "show_enum_origins": show_enum_origins,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ PaginatedUserList,
+ construct_type(
+ type_=PaginatedUserList, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ def retrieve(
+ self,
+ id: str,
+ *,
+ expand: typing.Optional[
+ typing.Union[UsersRetrieveRequestExpandItem, typing.Sequence[UsersRetrieveRequestExpandItem]]
+ ] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ remote_fields: typing.Optional[typing.Literal["type"]] = None,
+ show_enum_origins: typing.Optional[typing.Literal["type"]] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> HttpResponse[User]:
+ """
+ Returns a `User` object with the given `id`.
+
+ Parameters
+ ----------
+ id : str
+
+ expand : typing.Optional[typing.Union[UsersRetrieveRequestExpandItem, typing.Sequence[UsersRetrieveRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ remote_fields : typing.Optional[typing.Literal["type"]]
+ Deprecated. Use show_enum_origins.
+
+ show_enum_origins : typing.Optional[typing.Literal["type"]]
+ A comma separated list of enum field names for which you'd like the original values to be returned, instead of Merge's normalized enum values. [Learn more](https://help.merge.dev/en/articles/8950958-show_enum_origins-query-parameter)
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[User]
+
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ f"email/v1/users/{jsonable_encoder(id)}",
+ method="GET",
+ params={
+ "expand": expand,
+ "include_remote_data": include_remote_data,
+ "include_shell_data": include_shell_data,
+ "remote_fields": remote_fields,
+ "show_enum_origins": show_enum_origins,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ User,
+ construct_type(
+ type_=User, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+
+class AsyncRawUsersClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ async def list(
+ self,
+ *,
+ created_after: typing.Optional[dt.datetime] = None,
+ created_before: typing.Optional[dt.datetime] = None,
+ cursor: typing.Optional[str] = None,
+ email_address_id: typing.Optional[str] = None,
+ expand: typing.Optional[
+ typing.Union[UsersListRequestExpandItem, typing.Sequence[UsersListRequestExpandItem]]
+ ] = None,
+ group_id: typing.Optional[str] = None,
+ include_deleted_data: typing.Optional[bool] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ mailbox_id: typing.Optional[str] = None,
+ modified_after: typing.Optional[dt.datetime] = None,
+ modified_before: typing.Optional[dt.datetime] = None,
+ page_size: typing.Optional[int] = None,
+ remote_fields: typing.Optional[typing.Literal["type"]] = None,
+ remote_id: typing.Optional[str] = None,
+ show_enum_origins: typing.Optional[typing.Literal["type"]] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> AsyncHttpResponse[PaginatedUserList]:
+ """
+ Returns a list of `User` objects.
+
+ Parameters
+ ----------
+ created_after : typing.Optional[dt.datetime]
+ If provided, will only return objects created after this datetime.
+
+ created_before : typing.Optional[dt.datetime]
+ If provided, will only return objects created before this datetime.
+
+ cursor : typing.Optional[str]
+ The pagination cursor value.
+
+ email_address_id : typing.Optional[str]
+ If provided, will only return Users with this EmailAddress.
+
+ expand : typing.Optional[typing.Union[UsersListRequestExpandItem, typing.Sequence[UsersListRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ group_id : typing.Optional[str]
+ If provided, will only return Users belonging to this Group.
+
+ include_deleted_data : typing.Optional[bool]
+ Indicates whether or not this object has been deleted in the third party platform. Full coverage deletion detection is a premium add-on. Native deletion detection is offered for free with limited coverage. [Learn more](https://docs.merge.dev/integrations/hris/supported-features/).
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ mailbox_id : typing.Optional[str]
+ If provided, will only return Users associated with this Mailbox.
+
+ modified_after : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge after this date time will be returned.
+
+ modified_before : typing.Optional[dt.datetime]
+ If provided, only objects synced by Merge before this date time will be returned.
+
+ page_size : typing.Optional[int]
+ Number of results to return per page. The maximum limit is 100.
+
+ remote_fields : typing.Optional[typing.Literal["type"]]
+ Deprecated. Use show_enum_origins.
+
+ remote_id : typing.Optional[str]
+ The API provider's ID for the given object.
+
+ show_enum_origins : typing.Optional[typing.Literal["type"]]
+ A comma separated list of enum field names for which you'd like the original values to be returned, instead of Merge's normalized enum values. [Learn more](https://help.merge.dev/en/articles/8950958-show_enum_origins-query-parameter)
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[PaginatedUserList]
+
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ "email/v1/users",
+ method="GET",
+ params={
+ "created_after": serialize_datetime(created_after) if created_after is not None else None,
+ "created_before": serialize_datetime(created_before) if created_before is not None else None,
+ "cursor": cursor,
+ "email_address_id": email_address_id,
+ "expand": expand,
+ "group_id": group_id,
+ "include_deleted_data": include_deleted_data,
+ "include_remote_data": include_remote_data,
+ "include_shell_data": include_shell_data,
+ "mailbox_id": mailbox_id,
+ "modified_after": serialize_datetime(modified_after) if modified_after is not None else None,
+ "modified_before": serialize_datetime(modified_before) if modified_before is not None else None,
+ "page_size": page_size,
+ "remote_fields": remote_fields,
+ "remote_id": remote_id,
+ "show_enum_origins": show_enum_origins,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ PaginatedUserList,
+ construct_type(
+ type_=PaginatedUserList, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ async def retrieve(
+ self,
+ id: str,
+ *,
+ expand: typing.Optional[
+ typing.Union[UsersRetrieveRequestExpandItem, typing.Sequence[UsersRetrieveRequestExpandItem]]
+ ] = None,
+ include_remote_data: typing.Optional[bool] = None,
+ include_shell_data: typing.Optional[bool] = None,
+ remote_fields: typing.Optional[typing.Literal["type"]] = None,
+ show_enum_origins: typing.Optional[typing.Literal["type"]] = None,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> AsyncHttpResponse[User]:
+ """
+ Returns a `User` object with the given `id`.
+
+ Parameters
+ ----------
+ id : str
+
+ expand : typing.Optional[typing.Union[UsersRetrieveRequestExpandItem, typing.Sequence[UsersRetrieveRequestExpandItem]]]
+ Which relations should be returned in expanded form. Multiple relation names should be comma separated without spaces.
+
+ include_remote_data : typing.Optional[bool]
+ Whether to include the original data Merge fetched from the third-party to produce these models.
+
+ include_shell_data : typing.Optional[bool]
+ Whether to include shell records. Shell records are empty records (they may contain some metadata but all other fields are null).
+
+ remote_fields : typing.Optional[typing.Literal["type"]]
+ Deprecated. Use show_enum_origins.
+
+ show_enum_origins : typing.Optional[typing.Literal["type"]]
+ A comma separated list of enum field names for which you'd like the original values to be returned, instead of Merge's normalized enum values. [Learn more](https://help.merge.dev/en/articles/8950958-show_enum_origins-query-parameter)
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[User]
+
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ f"email/v1/users/{jsonable_encoder(id)}",
+ method="GET",
+ params={
+ "expand": expand,
+ "include_remote_data": include_remote_data,
+ "include_shell_data": include_shell_data,
+ "remote_fields": remote_fields,
+ "show_enum_origins": show_enum_origins,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ User,
+ construct_type(
+ type_=User, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
diff --git a/src/merge/resources/email/resources/users/types/__init__.py b/src/merge/resources/email/resources/users/types/__init__.py
new file mode 100644
index 00000000..e7ba722e
--- /dev/null
+++ b/src/merge/resources/email/resources/users/types/__init__.py
@@ -0,0 +1,36 @@
+# This file was auto-generated by Fern from our API Definition.
+
+# isort: skip_file
+
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .users_list_request_expand_item import UsersListRequestExpandItem
+ from .users_retrieve_request_expand_item import UsersRetrieveRequestExpandItem
+_dynamic_imports: typing.Dict[str, str] = {
+ "UsersListRequestExpandItem": ".users_list_request_expand_item",
+ "UsersRetrieveRequestExpandItem": ".users_retrieve_request_expand_item",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ result = getattr(module, attr_name)
+ return result
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
+
+__all__ = ["UsersListRequestExpandItem", "UsersRetrieveRequestExpandItem"]
diff --git a/src/merge/resources/email/resources/users/types/users_list_request_expand_item.py b/src/merge/resources/email/resources/users/types/users_list_request_expand_item.py
new file mode 100644
index 00000000..353a5fff
--- /dev/null
+++ b/src/merge/resources/email/resources/users/types/users_list_request_expand_item.py
@@ -0,0 +1,25 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import enum
+import typing
+
+T_Result = typing.TypeVar("T_Result")
+
+
+class UsersListRequestExpandItem(str, enum.Enum):
+ EMAIL_ADDRESSES = "email_addresses"
+ GROUPS = "groups"
+ MAILBOXES = "mailboxes"
+
+ def visit(
+ self,
+ email_addresses: typing.Callable[[], T_Result],
+ groups: typing.Callable[[], T_Result],
+ mailboxes: typing.Callable[[], T_Result],
+ ) -> T_Result:
+ if self is UsersListRequestExpandItem.EMAIL_ADDRESSES:
+ return email_addresses()
+ if self is UsersListRequestExpandItem.GROUPS:
+ return groups()
+ if self is UsersListRequestExpandItem.MAILBOXES:
+ return mailboxes()
diff --git a/src/merge/resources/email/resources/users/types/users_retrieve_request_expand_item.py b/src/merge/resources/email/resources/users/types/users_retrieve_request_expand_item.py
new file mode 100644
index 00000000..52907ee6
--- /dev/null
+++ b/src/merge/resources/email/resources/users/types/users_retrieve_request_expand_item.py
@@ -0,0 +1,25 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import enum
+import typing
+
+T_Result = typing.TypeVar("T_Result")
+
+
+class UsersRetrieveRequestExpandItem(str, enum.Enum):
+ EMAIL_ADDRESSES = "email_addresses"
+ GROUPS = "groups"
+ MAILBOXES = "mailboxes"
+
+ def visit(
+ self,
+ email_addresses: typing.Callable[[], T_Result],
+ groups: typing.Callable[[], T_Result],
+ mailboxes: typing.Callable[[], T_Result],
+ ) -> T_Result:
+ if self is UsersRetrieveRequestExpandItem.EMAIL_ADDRESSES:
+ return email_addresses()
+ if self is UsersRetrieveRequestExpandItem.GROUPS:
+ return groups()
+ if self is UsersRetrieveRequestExpandItem.MAILBOXES:
+ return mailboxes()
diff --git a/src/merge/resources/email/resources/webhook_receivers/__init__.py b/src/merge/resources/email/resources/webhook_receivers/__init__.py
new file mode 100644
index 00000000..5cde0202
--- /dev/null
+++ b/src/merge/resources/email/resources/webhook_receivers/__init__.py
@@ -0,0 +1,4 @@
+# This file was auto-generated by Fern from our API Definition.
+
+# isort: skip_file
+
diff --git a/src/merge/resources/email/resources/webhook_receivers/client.py b/src/merge/resources/email/resources/webhook_receivers/client.py
new file mode 100644
index 00000000..1f8a8481
--- /dev/null
+++ b/src/merge/resources/email/resources/webhook_receivers/client.py
@@ -0,0 +1,201 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .....core.request_options import RequestOptions
+from ...types.webhook_receiver import WebhookReceiver
+from .raw_client import AsyncRawWebhookReceiversClient, RawWebhookReceiversClient
+
+# this is used as the default value for optional parameters
+OMIT = typing.cast(typing.Any, ...)
+
+
+class WebhookReceiversClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._raw_client = RawWebhookReceiversClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> RawWebhookReceiversClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ RawWebhookReceiversClient
+ """
+ return self._raw_client
+
+ def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> typing.List[WebhookReceiver]:
+ """
+ Returns a list of `WebhookReceiver` objects.
+
+ Parameters
+ ----------
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ typing.List[WebhookReceiver]
+
+
+ Examples
+ --------
+ from merge import Merge
+
+ client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+ client.email.webhook_receivers.list()
+ """
+ _response = self._raw_client.list(request_options=request_options)
+ return _response.data
+
+ def create(
+ self,
+ *,
+ event: str,
+ is_active: bool,
+ key: typing.Optional[str] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> WebhookReceiver:
+ """
+ Creates a `WebhookReceiver` object with the given values.
+
+ Parameters
+ ----------
+ event : str
+
+ is_active : bool
+
+ key : typing.Optional[str]
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ WebhookReceiver
+
+
+ Examples
+ --------
+ from merge import Merge
+
+ client = Merge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+ client.email.webhook_receivers.create(
+ event="event",
+ is_active=True,
+ )
+ """
+ _response = self._raw_client.create(event=event, is_active=is_active, key=key, request_options=request_options)
+ return _response.data
+
+
+class AsyncWebhookReceiversClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._raw_client = AsyncRawWebhookReceiversClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> AsyncRawWebhookReceiversClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ AsyncRawWebhookReceiversClient
+ """
+ return self._raw_client
+
+ async def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> typing.List[WebhookReceiver]:
+ """
+ Returns a list of `WebhookReceiver` objects.
+
+ Parameters
+ ----------
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ typing.List[WebhookReceiver]
+
+
+ Examples
+ --------
+ import asyncio
+
+ from merge import AsyncMerge
+
+ client = AsyncMerge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.email.webhook_receivers.list()
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.list(request_options=request_options)
+ return _response.data
+
+ async def create(
+ self,
+ *,
+ event: str,
+ is_active: bool,
+ key: typing.Optional[str] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> WebhookReceiver:
+ """
+ Creates a `WebhookReceiver` object with the given values.
+
+ Parameters
+ ----------
+ event : str
+
+ is_active : bool
+
+ key : typing.Optional[str]
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ WebhookReceiver
+
+
+ Examples
+ --------
+ import asyncio
+
+ from merge import AsyncMerge
+
+ client = AsyncMerge(
+ account_token="YOUR_ACCOUNT_TOKEN",
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.email.webhook_receivers.create(
+ event="event",
+ is_active=True,
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.create(
+ event=event, is_active=is_active, key=key, request_options=request_options
+ )
+ return _response.data
diff --git a/src/merge/resources/email/resources/webhook_receivers/raw_client.py b/src/merge/resources/email/resources/webhook_receivers/raw_client.py
new file mode 100644
index 00000000..78c33981
--- /dev/null
+++ b/src/merge/resources/email/resources/webhook_receivers/raw_client.py
@@ -0,0 +1,208 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+from json.decoder import JSONDecodeError
+
+from .....core.api_error import ApiError
+from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .....core.http_response import AsyncHttpResponse, HttpResponse
+from .....core.request_options import RequestOptions
+from .....core.unchecked_base_model import construct_type
+from ...types.webhook_receiver import WebhookReceiver
+
+# this is used as the default value for optional parameters
+OMIT = typing.cast(typing.Any, ...)
+
+
+class RawWebhookReceiversClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ def list(
+ self, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> HttpResponse[typing.List[WebhookReceiver]]:
+ """
+ Returns a list of `WebhookReceiver` objects.
+
+ Parameters
+ ----------
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[typing.List[WebhookReceiver]]
+
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ "email/v1/webhook-receivers",
+ method="GET",
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ typing.List[WebhookReceiver],
+ construct_type(
+ type_=typing.List[WebhookReceiver], # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ def create(
+ self,
+ *,
+ event: str,
+ is_active: bool,
+ key: typing.Optional[str] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> HttpResponse[WebhookReceiver]:
+ """
+ Creates a `WebhookReceiver` object with the given values.
+
+ Parameters
+ ----------
+ event : str
+
+ is_active : bool
+
+ key : typing.Optional[str]
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[WebhookReceiver]
+
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ "email/v1/webhook-receivers",
+ method="POST",
+ json={
+ "event": event,
+ "is_active": is_active,
+ "key": key,
+ },
+ headers={
+ "content-type": "application/json",
+ },
+ request_options=request_options,
+ omit=OMIT,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ WebhookReceiver,
+ construct_type(
+ type_=WebhookReceiver, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+
+class AsyncRawWebhookReceiversClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ async def list(
+ self, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> AsyncHttpResponse[typing.List[WebhookReceiver]]:
+ """
+ Returns a list of `WebhookReceiver` objects.
+
+ Parameters
+ ----------
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[typing.List[WebhookReceiver]]
+
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ "email/v1/webhook-receivers",
+ method="GET",
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ typing.List[WebhookReceiver],
+ construct_type(
+ type_=typing.List[WebhookReceiver], # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ async def create(
+ self,
+ *,
+ event: str,
+ is_active: bool,
+ key: typing.Optional[str] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> AsyncHttpResponse[WebhookReceiver]:
+ """
+ Creates a `WebhookReceiver` object with the given values.
+
+ Parameters
+ ----------
+ event : str
+
+ is_active : bool
+
+ key : typing.Optional[str]
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[WebhookReceiver]
+
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ "email/v1/webhook-receivers",
+ method="POST",
+ json={
+ "event": event,
+ "is_active": is_active,
+ "key": key,
+ },
+ headers={
+ "content-type": "application/json",
+ },
+ request_options=request_options,
+ omit=OMIT,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ WebhookReceiver,
+ construct_type(
+ type_=WebhookReceiver, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
diff --git a/src/merge/resources/email/types/__init__.py b/src/merge/resources/email/types/__init__.py
new file mode 100644
index 00000000..0a3239df
--- /dev/null
+++ b/src/merge/resources/email/types/__init__.py
@@ -0,0 +1,347 @@
+# This file was auto-generated by Fern from our API Definition.
+
+# isort: skip_file
+
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .account_details import AccountDetails
+ from .account_details_and_actions import AccountDetailsAndActions
+ from .account_details_and_actions_category import AccountDetailsAndActionsCategory
+ from .account_details_and_actions_integration import AccountDetailsAndActionsIntegration
+ from .account_details_and_actions_status import AccountDetailsAndActionsStatus
+ from .account_details_and_actions_status_enum import AccountDetailsAndActionsStatusEnum
+ from .account_details_category import AccountDetailsCategory
+ from .account_integration import AccountIntegration
+ from .account_token import AccountToken
+ from .actions_enum import ActionsEnum
+ from .advanced_metadata import AdvancedMetadata
+ from .async_passthrough_reciept import AsyncPassthroughReciept
+ from .audit_log_event import AuditLogEvent
+ from .audit_log_event_event_type import AuditLogEventEventType
+ from .audit_log_event_role import AuditLogEventRole
+ from .available_actions import AvailableActions
+ from .categories_enum import CategoriesEnum
+ from .category_enum import CategoryEnum
+ from .common_model_scope_api import CommonModelScopeApi
+ from .common_model_scopes_body_request import CommonModelScopesBodyRequest
+ from .completed_account_initial_screen_enum import CompletedAccountInitialScreenEnum
+ from .data_passthrough_request import DataPassthroughRequest
+ from .data_passthrough_request_method import DataPassthroughRequestMethod
+ from .data_passthrough_request_request_format import DataPassthroughRequestRequestFormat
+ from .debug_mode_log import DebugModeLog
+ from .debug_model_log_summary import DebugModelLogSummary
+ from .effect_enum import EffectEnum
+ from .email_address import EmailAddress
+ from .email_address_field_mappings import EmailAddressFieldMappings
+ from .enabled_actions_enum import EnabledActionsEnum
+ from .encoding_enum import EncodingEnum
+ from .error_validation_problem import ErrorValidationProblem
+ from .event_type_enum import EventTypeEnum
+ from .external_target_field_api import ExternalTargetFieldApi
+ from .external_target_field_api_response import ExternalTargetFieldApiResponse
+ from .field_mapping_api_instance import FieldMappingApiInstance
+ from .field_mapping_api_instance_remote_field import FieldMappingApiInstanceRemoteField
+ from .field_mapping_api_instance_remote_field_remote_endpoint_info import (
+ FieldMappingApiInstanceRemoteFieldRemoteEndpointInfo,
+ )
+ from .field_mapping_api_instance_response import FieldMappingApiInstanceResponse
+ from .field_mapping_api_instance_target_field import FieldMappingApiInstanceTargetField
+ from .field_mapping_instance_response import FieldMappingInstanceResponse
+ from .field_permission_deserializer import FieldPermissionDeserializer
+ from .field_permission_deserializer_request import FieldPermissionDeserializerRequest
+ from .folder import Folder
+ from .folder_field_mappings import FolderFieldMappings
+ from .group import Group
+ from .group_field_mappings import GroupFieldMappings
+ from .individual_common_model_scope_deserializer import IndividualCommonModelScopeDeserializer
+ from .individual_common_model_scope_deserializer_request import IndividualCommonModelScopeDeserializerRequest
+ from .issue import Issue
+ from .issue_status import IssueStatus
+ from .issue_status_enum import IssueStatusEnum
+ from .language_enum import LanguageEnum
+ from .last_sync_result_enum import LastSyncResultEnum
+ from .link_token import LinkToken
+ from .mailbox import Mailbox
+ from .mailbox_field_mappings import MailboxFieldMappings
+ from .mailbox_type import MailboxType
+ from .mailbox_type_enum import MailboxTypeEnum
+ from .message import Message
+ from .method_enum import MethodEnum
+ from .model_operation import ModelOperation
+ from .model_permission_deserializer import ModelPermissionDeserializer
+ from .model_permission_deserializer_request import ModelPermissionDeserializerRequest
+ from .multipart_form_field_request import MultipartFormFieldRequest
+ from .multipart_form_field_request_encoding import MultipartFormFieldRequestEncoding
+ from .paginated_account_details_and_actions_list import PaginatedAccountDetailsAndActionsList
+ from .paginated_audit_log_event_list import PaginatedAuditLogEventList
+ from .paginated_email_address_list import PaginatedEmailAddressList
+ from .paginated_folder_list import PaginatedFolderList
+ from .paginated_group_list import PaginatedGroupList
+ from .paginated_issue_list import PaginatedIssueList
+ from .paginated_mailbox_list import PaginatedMailboxList
+ from .paginated_message_list import PaginatedMessageList
+ from .paginated_sync_status_list import PaginatedSyncStatusList
+ from .paginated_user_list import PaginatedUserList
+ from .permission import Permission
+ from .permission_effect import PermissionEffect
+ from .permission_field_mappings import PermissionFieldMappings
+ from .regenerate_account_token import RegenerateAccountToken
+ from .remote_data import RemoteData
+ from .remote_endpoint_info import RemoteEndpointInfo
+ from .remote_field_api import RemoteFieldApi
+ from .remote_field_api_advanced_metadata import RemoteFieldApiAdvancedMetadata
+ from .remote_field_api_coverage import RemoteFieldApiCoverage
+ from .remote_field_api_response import RemoteFieldApiResponse
+ from .remote_key import RemoteKey
+ from .remote_response import RemoteResponse
+ from .remote_response_response_type import RemoteResponseResponseType
+ from .request_format_enum import RequestFormatEnum
+ from .response_type_enum import ResponseTypeEnum
+ from .role_enum import RoleEnum
+ from .selective_sync_configurations_usage_enum import SelectiveSyncConfigurationsUsageEnum
+ from .status_fd_5_enum import StatusFd5Enum
+ from .sync_status import SyncStatus
+ from .sync_status_last_sync_result import SyncStatusLastSyncResult
+ from .sync_status_status import SyncStatusStatus
+ from .user import User
+ from .user_field_mappings import UserFieldMappings
+ from .user_type import UserType
+ from .user_type_enum import UserTypeEnum
+ from .validation_problem_source import ValidationProblemSource
+ from .warning_validation_problem import WarningValidationProblem
+ from .webhook_receiver import WebhookReceiver
+_dynamic_imports: typing.Dict[str, str] = {
+ "AccountDetails": ".account_details",
+ "AccountDetailsAndActions": ".account_details_and_actions",
+ "AccountDetailsAndActionsCategory": ".account_details_and_actions_category",
+ "AccountDetailsAndActionsIntegration": ".account_details_and_actions_integration",
+ "AccountDetailsAndActionsStatus": ".account_details_and_actions_status",
+ "AccountDetailsAndActionsStatusEnum": ".account_details_and_actions_status_enum",
+ "AccountDetailsCategory": ".account_details_category",
+ "AccountIntegration": ".account_integration",
+ "AccountToken": ".account_token",
+ "ActionsEnum": ".actions_enum",
+ "AdvancedMetadata": ".advanced_metadata",
+ "AsyncPassthroughReciept": ".async_passthrough_reciept",
+ "AuditLogEvent": ".audit_log_event",
+ "AuditLogEventEventType": ".audit_log_event_event_type",
+ "AuditLogEventRole": ".audit_log_event_role",
+ "AvailableActions": ".available_actions",
+ "CategoriesEnum": ".categories_enum",
+ "CategoryEnum": ".category_enum",
+ "CommonModelScopeApi": ".common_model_scope_api",
+ "CommonModelScopesBodyRequest": ".common_model_scopes_body_request",
+ "CompletedAccountInitialScreenEnum": ".completed_account_initial_screen_enum",
+ "DataPassthroughRequest": ".data_passthrough_request",
+ "DataPassthroughRequestMethod": ".data_passthrough_request_method",
+ "DataPassthroughRequestRequestFormat": ".data_passthrough_request_request_format",
+ "DebugModeLog": ".debug_mode_log",
+ "DebugModelLogSummary": ".debug_model_log_summary",
+ "EffectEnum": ".effect_enum",
+ "EmailAddress": ".email_address",
+ "EmailAddressFieldMappings": ".email_address_field_mappings",
+ "EnabledActionsEnum": ".enabled_actions_enum",
+ "EncodingEnum": ".encoding_enum",
+ "ErrorValidationProblem": ".error_validation_problem",
+ "EventTypeEnum": ".event_type_enum",
+ "ExternalTargetFieldApi": ".external_target_field_api",
+ "ExternalTargetFieldApiResponse": ".external_target_field_api_response",
+ "FieldMappingApiInstance": ".field_mapping_api_instance",
+ "FieldMappingApiInstanceRemoteField": ".field_mapping_api_instance_remote_field",
+ "FieldMappingApiInstanceRemoteFieldRemoteEndpointInfo": ".field_mapping_api_instance_remote_field_remote_endpoint_info",
+ "FieldMappingApiInstanceResponse": ".field_mapping_api_instance_response",
+ "FieldMappingApiInstanceTargetField": ".field_mapping_api_instance_target_field",
+ "FieldMappingInstanceResponse": ".field_mapping_instance_response",
+ "FieldPermissionDeserializer": ".field_permission_deserializer",
+ "FieldPermissionDeserializerRequest": ".field_permission_deserializer_request",
+ "Folder": ".folder",
+ "FolderFieldMappings": ".folder_field_mappings",
+ "Group": ".group",
+ "GroupFieldMappings": ".group_field_mappings",
+ "IndividualCommonModelScopeDeserializer": ".individual_common_model_scope_deserializer",
+ "IndividualCommonModelScopeDeserializerRequest": ".individual_common_model_scope_deserializer_request",
+ "Issue": ".issue",
+ "IssueStatus": ".issue_status",
+ "IssueStatusEnum": ".issue_status_enum",
+ "LanguageEnum": ".language_enum",
+ "LastSyncResultEnum": ".last_sync_result_enum",
+ "LinkToken": ".link_token",
+ "Mailbox": ".mailbox",
+ "MailboxFieldMappings": ".mailbox_field_mappings",
+ "MailboxType": ".mailbox_type",
+ "MailboxTypeEnum": ".mailbox_type_enum",
+ "Message": ".message",
+ "MethodEnum": ".method_enum",
+ "ModelOperation": ".model_operation",
+ "ModelPermissionDeserializer": ".model_permission_deserializer",
+ "ModelPermissionDeserializerRequest": ".model_permission_deserializer_request",
+ "MultipartFormFieldRequest": ".multipart_form_field_request",
+ "MultipartFormFieldRequestEncoding": ".multipart_form_field_request_encoding",
+ "PaginatedAccountDetailsAndActionsList": ".paginated_account_details_and_actions_list",
+ "PaginatedAuditLogEventList": ".paginated_audit_log_event_list",
+ "PaginatedEmailAddressList": ".paginated_email_address_list",
+ "PaginatedFolderList": ".paginated_folder_list",
+ "PaginatedGroupList": ".paginated_group_list",
+ "PaginatedIssueList": ".paginated_issue_list",
+ "PaginatedMailboxList": ".paginated_mailbox_list",
+ "PaginatedMessageList": ".paginated_message_list",
+ "PaginatedSyncStatusList": ".paginated_sync_status_list",
+ "PaginatedUserList": ".paginated_user_list",
+ "Permission": ".permission",
+ "PermissionEffect": ".permission_effect",
+ "PermissionFieldMappings": ".permission_field_mappings",
+ "RegenerateAccountToken": ".regenerate_account_token",
+ "RemoteData": ".remote_data",
+ "RemoteEndpointInfo": ".remote_endpoint_info",
+ "RemoteFieldApi": ".remote_field_api",
+ "RemoteFieldApiAdvancedMetadata": ".remote_field_api_advanced_metadata",
+ "RemoteFieldApiCoverage": ".remote_field_api_coverage",
+ "RemoteFieldApiResponse": ".remote_field_api_response",
+ "RemoteKey": ".remote_key",
+ "RemoteResponse": ".remote_response",
+ "RemoteResponseResponseType": ".remote_response_response_type",
+ "RequestFormatEnum": ".request_format_enum",
+ "ResponseTypeEnum": ".response_type_enum",
+ "RoleEnum": ".role_enum",
+ "SelectiveSyncConfigurationsUsageEnum": ".selective_sync_configurations_usage_enum",
+ "StatusFd5Enum": ".status_fd_5_enum",
+ "SyncStatus": ".sync_status",
+ "SyncStatusLastSyncResult": ".sync_status_last_sync_result",
+ "SyncStatusStatus": ".sync_status_status",
+ "User": ".user",
+ "UserFieldMappings": ".user_field_mappings",
+ "UserType": ".user_type",
+ "UserTypeEnum": ".user_type_enum",
+ "ValidationProblemSource": ".validation_problem_source",
+ "WarningValidationProblem": ".warning_validation_problem",
+ "WebhookReceiver": ".webhook_receiver",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ result = getattr(module, attr_name)
+ return result
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
+
+__all__ = [
+ "AccountDetails",
+ "AccountDetailsAndActions",
+ "AccountDetailsAndActionsCategory",
+ "AccountDetailsAndActionsIntegration",
+ "AccountDetailsAndActionsStatus",
+ "AccountDetailsAndActionsStatusEnum",
+ "AccountDetailsCategory",
+ "AccountIntegration",
+ "AccountToken",
+ "ActionsEnum",
+ "AdvancedMetadata",
+ "AsyncPassthroughReciept",
+ "AuditLogEvent",
+ "AuditLogEventEventType",
+ "AuditLogEventRole",
+ "AvailableActions",
+ "CategoriesEnum",
+ "CategoryEnum",
+ "CommonModelScopeApi",
+ "CommonModelScopesBodyRequest",
+ "CompletedAccountInitialScreenEnum",
+ "DataPassthroughRequest",
+ "DataPassthroughRequestMethod",
+ "DataPassthroughRequestRequestFormat",
+ "DebugModeLog",
+ "DebugModelLogSummary",
+ "EffectEnum",
+ "EmailAddress",
+ "EmailAddressFieldMappings",
+ "EnabledActionsEnum",
+ "EncodingEnum",
+ "ErrorValidationProblem",
+ "EventTypeEnum",
+ "ExternalTargetFieldApi",
+ "ExternalTargetFieldApiResponse",
+ "FieldMappingApiInstance",
+ "FieldMappingApiInstanceRemoteField",
+ "FieldMappingApiInstanceRemoteFieldRemoteEndpointInfo",
+ "FieldMappingApiInstanceResponse",
+ "FieldMappingApiInstanceTargetField",
+ "FieldMappingInstanceResponse",
+ "FieldPermissionDeserializer",
+ "FieldPermissionDeserializerRequest",
+ "Folder",
+ "FolderFieldMappings",
+ "Group",
+ "GroupFieldMappings",
+ "IndividualCommonModelScopeDeserializer",
+ "IndividualCommonModelScopeDeserializerRequest",
+ "Issue",
+ "IssueStatus",
+ "IssueStatusEnum",
+ "LanguageEnum",
+ "LastSyncResultEnum",
+ "LinkToken",
+ "Mailbox",
+ "MailboxFieldMappings",
+ "MailboxType",
+ "MailboxTypeEnum",
+ "Message",
+ "MethodEnum",
+ "ModelOperation",
+ "ModelPermissionDeserializer",
+ "ModelPermissionDeserializerRequest",
+ "MultipartFormFieldRequest",
+ "MultipartFormFieldRequestEncoding",
+ "PaginatedAccountDetailsAndActionsList",
+ "PaginatedAuditLogEventList",
+ "PaginatedEmailAddressList",
+ "PaginatedFolderList",
+ "PaginatedGroupList",
+ "PaginatedIssueList",
+ "PaginatedMailboxList",
+ "PaginatedMessageList",
+ "PaginatedSyncStatusList",
+ "PaginatedUserList",
+ "Permission",
+ "PermissionEffect",
+ "PermissionFieldMappings",
+ "RegenerateAccountToken",
+ "RemoteData",
+ "RemoteEndpointInfo",
+ "RemoteFieldApi",
+ "RemoteFieldApiAdvancedMetadata",
+ "RemoteFieldApiCoverage",
+ "RemoteFieldApiResponse",
+ "RemoteKey",
+ "RemoteResponse",
+ "RemoteResponseResponseType",
+ "RequestFormatEnum",
+ "ResponseTypeEnum",
+ "RoleEnum",
+ "SelectiveSyncConfigurationsUsageEnum",
+ "StatusFd5Enum",
+ "SyncStatus",
+ "SyncStatusLastSyncResult",
+ "SyncStatusStatus",
+ "User",
+ "UserFieldMappings",
+ "UserType",
+ "UserTypeEnum",
+ "ValidationProblemSource",
+ "WarningValidationProblem",
+ "WebhookReceiver",
+]
diff --git a/src/merge/resources/email/types/account_details.py b/src/merge/resources/email/types/account_details.py
new file mode 100644
index 00000000..4d7bb370
--- /dev/null
+++ b/src/merge/resources/email/types/account_details.py
@@ -0,0 +1,43 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+from .account_details_category import AccountDetailsCategory
+
+
+class AccountDetails(UncheckedBaseModel):
+ id: typing.Optional[str] = None
+ integration: typing.Optional[str] = None
+ integration_slug: typing.Optional[str] = None
+ category: typing.Optional[AccountDetailsCategory] = None
+ end_user_origin_id: typing.Optional[str] = None
+ end_user_organization_name: typing.Optional[str] = None
+ end_user_email_address: typing.Optional[str] = None
+ status: typing.Optional[str] = None
+ webhook_listener_url: typing.Optional[str] = None
+ is_duplicate: typing.Optional[bool] = pydantic.Field(default=None)
+ """
+ Whether a Production Linked Account's credentials match another existing Production Linked Account. This field is `null` for Test Linked Accounts, incomplete Production Linked Accounts, and ignored duplicate Production Linked Account sets.
+ """
+
+ account_type: typing.Optional[str] = None
+ completed_at: typing.Optional[dt.datetime] = pydantic.Field(default=None)
+ """
+ The time at which account completes the linking flow.
+ """
+
+ instance_id: typing.Optional[str] = None
+ instance_display_value: typing.Optional[str] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/account_details_and_actions.py b/src/merge/resources/email/types/account_details_and_actions.py
new file mode 100644
index 00000000..93c874ed
--- /dev/null
+++ b/src/merge/resources/email/types/account_details_and_actions.py
@@ -0,0 +1,54 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+from .account_details_and_actions_category import AccountDetailsAndActionsCategory
+from .account_details_and_actions_integration import AccountDetailsAndActionsIntegration
+from .account_details_and_actions_status import AccountDetailsAndActionsStatus
+
+
+class AccountDetailsAndActions(UncheckedBaseModel):
+ """
+ # The LinkedAccount Object
+ ### Description
+ The `LinkedAccount` object is used to represent an end user's link with a specific integration.
+
+ ### Usage Example
+ View a list of your organization's `LinkedAccount` objects.
+ """
+
+ id: str
+ category: typing.Optional[AccountDetailsAndActionsCategory] = None
+ status: AccountDetailsAndActionsStatus
+ status_detail: typing.Optional[str] = None
+ end_user_origin_id: typing.Optional[str] = None
+ end_user_organization_name: str
+ end_user_email_address: str
+ subdomain: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ The tenant or domain the customer has provided access to.
+ """
+
+ webhook_listener_url: str
+ is_duplicate: typing.Optional[bool] = pydantic.Field(default=None)
+ """
+ Whether a Production Linked Account's credentials match another existing Production Linked Account. This field is `null` for Test Linked Accounts, incomplete Production Linked Accounts, and ignored duplicate Production Linked Account sets.
+ """
+
+ integration: typing.Optional[AccountDetailsAndActionsIntegration] = None
+ account_type: str
+ completed_at: dt.datetime
+ integration_specific_fields: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/account_details_and_actions_category.py b/src/merge/resources/email/types/account_details_and_actions_category.py
new file mode 100644
index 00000000..93b4188b
--- /dev/null
+++ b/src/merge/resources/email/types/account_details_and_actions_category.py
@@ -0,0 +1,7 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+from .category_enum import CategoryEnum
+
+AccountDetailsAndActionsCategory = typing.Union[CategoryEnum, str]
diff --git a/src/merge/resources/email/types/account_details_and_actions_integration.py b/src/merge/resources/email/types/account_details_and_actions_integration.py
new file mode 100644
index 00000000..73467bbb
--- /dev/null
+++ b/src/merge/resources/email/types/account_details_and_actions_integration.py
@@ -0,0 +1,29 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+from .categories_enum import CategoriesEnum
+from .model_operation import ModelOperation
+
+
+class AccountDetailsAndActionsIntegration(UncheckedBaseModel):
+ name: str
+ categories: typing.List[CategoriesEnum]
+ image: typing.Optional[str] = None
+ square_image: typing.Optional[str] = None
+ color: str
+ slug: str
+ passthrough_available: bool
+ available_model_operations: typing.Optional[typing.List[ModelOperation]] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/account_details_and_actions_status.py b/src/merge/resources/email/types/account_details_and_actions_status.py
new file mode 100644
index 00000000..445922f8
--- /dev/null
+++ b/src/merge/resources/email/types/account_details_and_actions_status.py
@@ -0,0 +1,7 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+from .account_details_and_actions_status_enum import AccountDetailsAndActionsStatusEnum
+
+AccountDetailsAndActionsStatus = typing.Union[AccountDetailsAndActionsStatusEnum, str]
diff --git a/src/merge/resources/email/types/account_details_and_actions_status_enum.py b/src/merge/resources/email/types/account_details_and_actions_status_enum.py
new file mode 100644
index 00000000..0701a829
--- /dev/null
+++ b/src/merge/resources/email/types/account_details_and_actions_status_enum.py
@@ -0,0 +1,29 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import enum
+import typing
+
+T_Result = typing.TypeVar("T_Result")
+
+
+class AccountDetailsAndActionsStatusEnum(str, enum.Enum):
+ COMPLETE = "COMPLETE"
+ INCOMPLETE = "INCOMPLETE"
+ RELINK_NEEDED = "RELINK_NEEDED"
+ IDLE = "IDLE"
+
+ def visit(
+ self,
+ complete: typing.Callable[[], T_Result],
+ incomplete: typing.Callable[[], T_Result],
+ relink_needed: typing.Callable[[], T_Result],
+ idle: typing.Callable[[], T_Result],
+ ) -> T_Result:
+ if self is AccountDetailsAndActionsStatusEnum.COMPLETE:
+ return complete()
+ if self is AccountDetailsAndActionsStatusEnum.INCOMPLETE:
+ return incomplete()
+ if self is AccountDetailsAndActionsStatusEnum.RELINK_NEEDED:
+ return relink_needed()
+ if self is AccountDetailsAndActionsStatusEnum.IDLE:
+ return idle()
diff --git a/src/merge/resources/email/types/account_details_category.py b/src/merge/resources/email/types/account_details_category.py
new file mode 100644
index 00000000..8a0cc59c
--- /dev/null
+++ b/src/merge/resources/email/types/account_details_category.py
@@ -0,0 +1,7 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+from .category_enum import CategoryEnum
+
+AccountDetailsCategory = typing.Union[CategoryEnum, str]
diff --git a/src/merge/resources/email/types/account_integration.py b/src/merge/resources/email/types/account_integration.py
new file mode 100644
index 00000000..ef8b260d
--- /dev/null
+++ b/src/merge/resources/email/types/account_integration.py
@@ -0,0 +1,67 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+from .categories_enum import CategoriesEnum
+
+
+class AccountIntegration(UncheckedBaseModel):
+ name: str = pydantic.Field()
+ """
+ Company name.
+ """
+
+ abbreviated_name: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ Optional. This shortened name appears in places with limited space, usually in conjunction with the platform's logo (e.g., Merge Link menu).
Example: Workforce Now (in lieu of ADP Workforce Now), SuccessFactors (in lieu of SAP SuccessFactors)
+ """
+
+ categories: typing.Optional[typing.List[CategoriesEnum]] = pydantic.Field(default=None)
+ """
+ Category or categories this integration belongs to. Multiple categories should be comma separated, i.e. [ats, hris].
+ """
+
+ image: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ Company logo in rectangular shape.
+ """
+
+ square_image: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ Company logo in square shape.
+ """
+
+ color: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ The color of this integration used for buttons and text throughout the app and landing pages. Choose a darker, saturated color.
+ """
+
+ slug: typing.Optional[str] = None
+ api_endpoints_to_documentation_urls: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = (
+ pydantic.Field(default=None)
+ )
+ """
+ Mapping of API endpoints to documentation urls for support. Example: {'GET': [['/common-model-scopes', 'https://docs.merge.dev/accounting/common-model-scopes/#common_model_scopes_retrieve'],['/common-model-actions', 'https://docs.merge.dev/accounting/common-model-actions/#common_model_actions_retrieve']], 'POST': []}
+ """
+
+ webhook_setup_guide_url: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ Setup guide URL for third party webhook creation. Exposed in Merge Docs.
+ """
+
+ category_beta_status: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = pydantic.Field(default=None)
+ """
+ Category or categories this integration is in beta status for.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/account_token.py b/src/merge/resources/email/types/account_token.py
new file mode 100644
index 00000000..6e82c8ac
--- /dev/null
+++ b/src/merge/resources/email/types/account_token.py
@@ -0,0 +1,23 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+from .account_integration import AccountIntegration
+
+
+class AccountToken(UncheckedBaseModel):
+ account_token: str
+ integration: AccountIntegration
+ id: str
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/actions_enum.py b/src/merge/resources/email/types/actions_enum.py
new file mode 100644
index 00000000..5481c548
--- /dev/null
+++ b/src/merge/resources/email/types/actions_enum.py
@@ -0,0 +1,5 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+ActionsEnum = typing.Literal["READ"]
diff --git a/src/merge/resources/email/types/advanced_metadata.py b/src/merge/resources/email/types/advanced_metadata.py
new file mode 100644
index 00000000..60b5d072
--- /dev/null
+++ b/src/merge/resources/email/types/advanced_metadata.py
@@ -0,0 +1,25 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+
+
+class AdvancedMetadata(UncheckedBaseModel):
+ id: str
+ display_name: typing.Optional[str] = None
+ description: typing.Optional[str] = None
+ is_required: typing.Optional[bool] = None
+ is_custom: typing.Optional[bool] = None
+ field_choices: typing.Optional[typing.List[typing.Optional[typing.Any]]] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/async_passthrough_reciept.py b/src/merge/resources/email/types/async_passthrough_reciept.py
new file mode 100644
index 00000000..21c95080
--- /dev/null
+++ b/src/merge/resources/email/types/async_passthrough_reciept.py
@@ -0,0 +1,20 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+
+
+class AsyncPassthroughReciept(UncheckedBaseModel):
+ async_passthrough_receipt_id: str
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/audit_log_event.py b/src/merge/resources/email/types/audit_log_event.py
new file mode 100644
index 00000000..69063d10
--- /dev/null
+++ b/src/merge/resources/email/types/audit_log_event.py
@@ -0,0 +1,46 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+from .audit_log_event_event_type import AuditLogEventEventType
+from .audit_log_event_role import AuditLogEventRole
+
+
+class AuditLogEvent(UncheckedBaseModel):
+ id: typing.Optional[str] = None
+ user_name: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ The User's full name at the time of this Event occurring.
+ """
+
+ user_email: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ The User's email at the time of this Event occurring.
+ """
+
+ role: AuditLogEventRole = pydantic.Field()
+ """
+ Designates the role of the user (or SYSTEM/API if action not taken by a user) at the time of this Event occurring.
+ """
+
+ ip_address: str
+ event_type: AuditLogEventEventType = pydantic.Field()
+ """
+ Designates the type of event that occurred.
+ """
+
+ event_description: str
+ created_at: typing.Optional[dt.datetime] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/audit_log_event_event_type.py b/src/merge/resources/email/types/audit_log_event_event_type.py
new file mode 100644
index 00000000..f9c9d2b3
--- /dev/null
+++ b/src/merge/resources/email/types/audit_log_event_event_type.py
@@ -0,0 +1,7 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+from .event_type_enum import EventTypeEnum
+
+AuditLogEventEventType = typing.Union[EventTypeEnum, str]
diff --git a/src/merge/resources/email/types/audit_log_event_role.py b/src/merge/resources/email/types/audit_log_event_role.py
new file mode 100644
index 00000000..fe91ed6f
--- /dev/null
+++ b/src/merge/resources/email/types/audit_log_event_role.py
@@ -0,0 +1,7 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+from .role_enum import RoleEnum
+
+AuditLogEventRole = typing.Union[RoleEnum, str]
diff --git a/src/merge/resources/email/types/available_actions.py b/src/merge/resources/email/types/available_actions.py
new file mode 100644
index 00000000..8b5019d7
--- /dev/null
+++ b/src/merge/resources/email/types/available_actions.py
@@ -0,0 +1,33 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+from .account_integration import AccountIntegration
+from .model_operation import ModelOperation
+
+
+class AvailableActions(UncheckedBaseModel):
+ """
+ # The AvailableActions Object
+ ### Description
+ The `Activity` object is used to see all available model/operation combinations for an integration.
+
+ ### Usage Example
+ Fetch all the actions available for the `Zenefits` integration.
+ """
+
+ integration: AccountIntegration
+ passthrough_available: bool
+ available_model_operations: typing.Optional[typing.List[ModelOperation]] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/categories_enum.py b/src/merge/resources/email/types/categories_enum.py
new file mode 100644
index 00000000..b6575458
--- /dev/null
+++ b/src/merge/resources/email/types/categories_enum.py
@@ -0,0 +1,45 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import enum
+import typing
+
+T_Result = typing.TypeVar("T_Result")
+
+
+class CategoriesEnum(str, enum.Enum):
+ HRIS = "hris"
+ ATS = "ats"
+ ACCOUNTING = "accounting"
+ TICKETING = "ticketing"
+ CRM = "crm"
+ MKTG = "mktg"
+ FILESTORAGE = "filestorage"
+ KNOWLEDGEBASE = "knowledgebase"
+
+ def visit(
+ self,
+ hris: typing.Callable[[], T_Result],
+ ats: typing.Callable[[], T_Result],
+ accounting: typing.Callable[[], T_Result],
+ ticketing: typing.Callable[[], T_Result],
+ crm: typing.Callable[[], T_Result],
+ mktg: typing.Callable[[], T_Result],
+ filestorage: typing.Callable[[], T_Result],
+ knowledgebase: typing.Callable[[], T_Result],
+ ) -> T_Result:
+ if self is CategoriesEnum.HRIS:
+ return hris()
+ if self is CategoriesEnum.ATS:
+ return ats()
+ if self is CategoriesEnum.ACCOUNTING:
+ return accounting()
+ if self is CategoriesEnum.TICKETING:
+ return ticketing()
+ if self is CategoriesEnum.CRM:
+ return crm()
+ if self is CategoriesEnum.MKTG:
+ return mktg()
+ if self is CategoriesEnum.FILESTORAGE:
+ return filestorage()
+ if self is CategoriesEnum.KNOWLEDGEBASE:
+ return knowledgebase()
diff --git a/src/merge/resources/email/types/category_enum.py b/src/merge/resources/email/types/category_enum.py
new file mode 100644
index 00000000..4ee2f4e4
--- /dev/null
+++ b/src/merge/resources/email/types/category_enum.py
@@ -0,0 +1,45 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import enum
+import typing
+
+T_Result = typing.TypeVar("T_Result")
+
+
+class CategoryEnum(str, enum.Enum):
+ HRIS = "hris"
+ ATS = "ats"
+ ACCOUNTING = "accounting"
+ TICKETING = "ticketing"
+ CRM = "crm"
+ MKTG = "mktg"
+ FILESTORAGE = "filestorage"
+ KNOWLEDGEBASE = "knowledgebase"
+
+ def visit(
+ self,
+ hris: typing.Callable[[], T_Result],
+ ats: typing.Callable[[], T_Result],
+ accounting: typing.Callable[[], T_Result],
+ ticketing: typing.Callable[[], T_Result],
+ crm: typing.Callable[[], T_Result],
+ mktg: typing.Callable[[], T_Result],
+ filestorage: typing.Callable[[], T_Result],
+ knowledgebase: typing.Callable[[], T_Result],
+ ) -> T_Result:
+ if self is CategoryEnum.HRIS:
+ return hris()
+ if self is CategoryEnum.ATS:
+ return ats()
+ if self is CategoryEnum.ACCOUNTING:
+ return accounting()
+ if self is CategoryEnum.TICKETING:
+ return ticketing()
+ if self is CategoryEnum.CRM:
+ return crm()
+ if self is CategoryEnum.MKTG:
+ return mktg()
+ if self is CategoryEnum.FILESTORAGE:
+ return filestorage()
+ if self is CategoryEnum.KNOWLEDGEBASE:
+ return knowledgebase()
diff --git a/src/merge/resources/email/types/common_model_scope_api.py b/src/merge/resources/email/types/common_model_scope_api.py
new file mode 100644
index 00000000..5484808d
--- /dev/null
+++ b/src/merge/resources/email/types/common_model_scope_api.py
@@ -0,0 +1,24 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+from .individual_common_model_scope_deserializer import IndividualCommonModelScopeDeserializer
+
+
+class CommonModelScopeApi(UncheckedBaseModel):
+ common_models: typing.List[IndividualCommonModelScopeDeserializer] = pydantic.Field()
+ """
+ The common models you want to update the scopes for
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/common_model_scopes_body_request.py b/src/merge/resources/email/types/common_model_scopes_body_request.py
new file mode 100644
index 00000000..a9fed25b
--- /dev/null
+++ b/src/merge/resources/email/types/common_model_scopes_body_request.py
@@ -0,0 +1,23 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+from .enabled_actions_enum import EnabledActionsEnum
+
+
+class CommonModelScopesBodyRequest(UncheckedBaseModel):
+ model_id: str
+ enabled_actions: typing.List[EnabledActionsEnum]
+ disabled_fields: typing.List[str]
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/completed_account_initial_screen_enum.py b/src/merge/resources/email/types/completed_account_initial_screen_enum.py
new file mode 100644
index 00000000..c112dfd1
--- /dev/null
+++ b/src/merge/resources/email/types/completed_account_initial_screen_enum.py
@@ -0,0 +1,5 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+CompletedAccountInitialScreenEnum = typing.Literal["SELECTIVE_SYNC"]
diff --git a/src/merge/resources/email/types/data_passthrough_request.py b/src/merge/resources/email/types/data_passthrough_request.py
new file mode 100644
index 00000000..5a60bfb6
--- /dev/null
+++ b/src/merge/resources/email/types/data_passthrough_request.py
@@ -0,0 +1,62 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+from .data_passthrough_request_method import DataPassthroughRequestMethod
+from .data_passthrough_request_request_format import DataPassthroughRequestRequestFormat
+from .multipart_form_field_request import MultipartFormFieldRequest
+
+
+class DataPassthroughRequest(UncheckedBaseModel):
+ """
+ # The DataPassthrough Object
+ ### Description
+ The `DataPassthrough` object is used to send information to an otherwise-unsupported third-party endpoint.
+
+ ### Usage Example
+ Create a `DataPassthrough` to get team hierarchies from your Rippling integration.
+ """
+
+ method: DataPassthroughRequestMethod
+ path: str = pydantic.Field()
+ """
+ The path of the request in the third party's platform.
+ """
+
+ base_url_override: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ An optional override of the third party's base url for the request.
+ """
+
+ data: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ The data with the request. You must include a `request_format` parameter matching the data's format
+ """
+
+ multipart_form_data: typing.Optional[typing.List[MultipartFormFieldRequest]] = pydantic.Field(default=None)
+ """
+ Pass an array of `MultipartFormField` objects in here instead of using the `data` param if `request_format` is set to `MULTIPART`.
+ """
+
+ headers: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = pydantic.Field(default=None)
+ """
+ The headers to use for the request (Merge will handle the account's authorization headers). `Content-Type` header is required for passthrough. Choose content type corresponding to expected format of receiving server.
+ """
+
+ request_format: typing.Optional[DataPassthroughRequestRequestFormat] = None
+ normalize_response: typing.Optional[bool] = pydantic.Field(default=None)
+ """
+ Optional. If true, the response will always be an object of the form `{"type": T, "value": ...}` where `T` will be one of `string, boolean, number, null, array, object`.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/data_passthrough_request_method.py b/src/merge/resources/email/types/data_passthrough_request_method.py
new file mode 100644
index 00000000..58874cbf
--- /dev/null
+++ b/src/merge/resources/email/types/data_passthrough_request_method.py
@@ -0,0 +1,7 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+from .method_enum import MethodEnum
+
+DataPassthroughRequestMethod = typing.Union[MethodEnum, str]
diff --git a/src/merge/resources/email/types/data_passthrough_request_request_format.py b/src/merge/resources/email/types/data_passthrough_request_request_format.py
new file mode 100644
index 00000000..13dc95f0
--- /dev/null
+++ b/src/merge/resources/email/types/data_passthrough_request_request_format.py
@@ -0,0 +1,7 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+from .request_format_enum import RequestFormatEnum
+
+DataPassthroughRequestRequestFormat = typing.Union[RequestFormatEnum, str]
diff --git a/src/merge/resources/email/types/debug_mode_log.py b/src/merge/resources/email/types/debug_mode_log.py
new file mode 100644
index 00000000..9c7d2a3f
--- /dev/null
+++ b/src/merge/resources/email/types/debug_mode_log.py
@@ -0,0 +1,23 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+from .debug_model_log_summary import DebugModelLogSummary
+
+
+class DebugModeLog(UncheckedBaseModel):
+ log_id: str
+ dashboard_view: str
+ log_summary: DebugModelLogSummary
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/debug_model_log_summary.py b/src/merge/resources/email/types/debug_model_log_summary.py
new file mode 100644
index 00000000..d7e1d3e6
--- /dev/null
+++ b/src/merge/resources/email/types/debug_model_log_summary.py
@@ -0,0 +1,22 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+
+
+class DebugModelLogSummary(UncheckedBaseModel):
+ url: str
+ method: str
+ status_code: int
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/effect_enum.py b/src/merge/resources/email/types/effect_enum.py
new file mode 100644
index 00000000..781c7ad5
--- /dev/null
+++ b/src/merge/resources/email/types/effect_enum.py
@@ -0,0 +1,25 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import enum
+import typing
+
+T_Result = typing.TypeVar("T_Result")
+
+
+class EffectEnum(str, enum.Enum):
+ ALLOWED = "ALLOWED"
+ DENIED = "DENIED"
+ INHERITED = "INHERITED"
+
+ def visit(
+ self,
+ allowed: typing.Callable[[], T_Result],
+ denied: typing.Callable[[], T_Result],
+ inherited: typing.Callable[[], T_Result],
+ ) -> T_Result:
+ if self is EffectEnum.ALLOWED:
+ return allowed()
+ if self is EffectEnum.DENIED:
+ return denied()
+ if self is EffectEnum.INHERITED:
+ return inherited()
diff --git a/src/merge/resources/email/types/email_address.py b/src/merge/resources/email/types/email_address.py
new file mode 100644
index 00000000..12ea8e3a
--- /dev/null
+++ b/src/merge/resources/email/types/email_address.py
@@ -0,0 +1,71 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+from .email_address_field_mappings import EmailAddressFieldMappings
+from .remote_data import RemoteData
+
+
+class EmailAddress(UncheckedBaseModel):
+ """
+ # The EmailAddress Object
+ ### Description
+ The `EmailAddress` object is used to represent an email address.
+ ### Usage Example
+ Fetch from the `GET /api/email/v1/email-addresses` endpoint and view their email addresses.
+ """
+
+ id: typing.Optional[str] = None
+ remote_id: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ The third-party API ID of the matching object.
+ """
+
+ created_at: typing.Optional[dt.datetime] = pydantic.Field(default=None)
+ """
+ The datetime that this object was created by Merge.
+ """
+
+ modified_at: typing.Optional[dt.datetime] = pydantic.Field(default=None)
+ """
+ The datetime that this object was modified by Merge.
+ """
+
+ email_address: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ The location where emails are sent/received.
+ """
+
+ mailboxes: typing.Optional[typing.List[typing.Optional[str]]] = None
+ users: typing.Optional[typing.List[typing.Optional[str]]] = None
+ groups: typing.Optional[typing.List[typing.Optional[str]]] = None
+ remote_created_at: typing.Optional[dt.datetime] = pydantic.Field(default=None)
+ """
+ When the third party's email address was created.
+ """
+
+ remote_updated_at: typing.Optional[dt.datetime] = pydantic.Field(default=None)
+ """
+ When the third party's email address was updated.
+ """
+
+ remote_was_deleted: typing.Optional[bool] = pydantic.Field(default=None)
+ """
+ Indicates whether or not this object has been deleted in the third party platform. Full coverage deletion detection is a premium add-on. Native deletion detection is offered for free with limited coverage. [Learn more](https://docs.merge.dev/integrations/hris/supported-features/).
+ """
+
+ field_mappings: typing.Optional[EmailAddressFieldMappings] = None
+ remote_data: typing.Optional[typing.List[RemoteData]] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/email_address_field_mappings.py b/src/merge/resources/email/types/email_address_field_mappings.py
new file mode 100644
index 00000000..29175058
--- /dev/null
+++ b/src/merge/resources/email/types/email_address_field_mappings.py
@@ -0,0 +1,21 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+
+
+class EmailAddressFieldMappings(UncheckedBaseModel):
+ organization_defined_targets: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = None
+ linked_account_defined_targets: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/enabled_actions_enum.py b/src/merge/resources/email/types/enabled_actions_enum.py
new file mode 100644
index 00000000..cb19286a
--- /dev/null
+++ b/src/merge/resources/email/types/enabled_actions_enum.py
@@ -0,0 +1,17 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import enum
+import typing
+
+T_Result = typing.TypeVar("T_Result")
+
+
+class EnabledActionsEnum(str, enum.Enum):
+ READ = "READ"
+ WRITE = "WRITE"
+
+ def visit(self, read: typing.Callable[[], T_Result], write: typing.Callable[[], T_Result]) -> T_Result:
+ if self is EnabledActionsEnum.READ:
+ return read()
+ if self is EnabledActionsEnum.WRITE:
+ return write()
diff --git a/src/merge/resources/email/types/encoding_enum.py b/src/merge/resources/email/types/encoding_enum.py
new file mode 100644
index 00000000..7d4b8977
--- /dev/null
+++ b/src/merge/resources/email/types/encoding_enum.py
@@ -0,0 +1,25 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import enum
+import typing
+
+T_Result = typing.TypeVar("T_Result")
+
+
+class EncodingEnum(str, enum.Enum):
+ RAW = "RAW"
+ BASE_64 = "BASE64"
+ GZIP_BASE_64 = "GZIP_BASE64"
+
+ def visit(
+ self,
+ raw: typing.Callable[[], T_Result],
+ base_64: typing.Callable[[], T_Result],
+ gzip_base_64: typing.Callable[[], T_Result],
+ ) -> T_Result:
+ if self is EncodingEnum.RAW:
+ return raw()
+ if self is EncodingEnum.BASE_64:
+ return base_64()
+ if self is EncodingEnum.GZIP_BASE_64:
+ return gzip_base_64()
diff --git a/src/merge/resources/email/types/error_validation_problem.py b/src/merge/resources/email/types/error_validation_problem.py
new file mode 100644
index 00000000..eca8e811
--- /dev/null
+++ b/src/merge/resources/email/types/error_validation_problem.py
@@ -0,0 +1,27 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+from .validation_problem_source import ValidationProblemSource
+
+
+class ErrorValidationProblem(UncheckedBaseModel):
+ source: typing.Optional[ValidationProblemSource] = None
+ title: str
+ detail: str
+ problem_type: str
+ block_merge_link: typing.Optional[bool] = None
+ raw_error: typing.Optional[str] = None
+ error_code: typing.Optional[int] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/event_type_enum.py b/src/merge/resources/email/types/event_type_enum.py
new file mode 100644
index 00000000..a04b9681
--- /dev/null
+++ b/src/merge/resources/email/types/event_type_enum.py
@@ -0,0 +1,185 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import enum
+import typing
+
+T_Result = typing.TypeVar("T_Result")
+
+
+class EventTypeEnum(str, enum.Enum):
+ CREATED_REMOTE_PRODUCTION_API_KEY = "CREATED_REMOTE_PRODUCTION_API_KEY"
+ DELETED_REMOTE_PRODUCTION_API_KEY = "DELETED_REMOTE_PRODUCTION_API_KEY"
+ CREATED_TEST_API_KEY = "CREATED_TEST_API_KEY"
+ DELETED_TEST_API_KEY = "DELETED_TEST_API_KEY"
+ REGENERATED_PRODUCTION_API_KEY = "REGENERATED_PRODUCTION_API_KEY"
+ REGENERATED_WEBHOOK_SIGNATURE = "REGENERATED_WEBHOOK_SIGNATURE"
+ INVITED_USER = "INVITED_USER"
+ TWO_FACTOR_AUTH_ENABLED = "TWO_FACTOR_AUTH_ENABLED"
+ TWO_FACTOR_AUTH_DISABLED = "TWO_FACTOR_AUTH_DISABLED"
+ DELETED_LINKED_ACCOUNT = "DELETED_LINKED_ACCOUNT"
+ DELETED_ALL_COMMON_MODELS_FOR_LINKED_ACCOUNT = "DELETED_ALL_COMMON_MODELS_FOR_LINKED_ACCOUNT"
+ CREATED_DESTINATION = "CREATED_DESTINATION"
+ DELETED_DESTINATION = "DELETED_DESTINATION"
+ CHANGED_DESTINATION = "CHANGED_DESTINATION"
+ CHANGED_SCOPES = "CHANGED_SCOPES"
+ CHANGED_PERSONAL_INFORMATION = "CHANGED_PERSONAL_INFORMATION"
+ CHANGED_ORGANIZATION_SETTINGS = "CHANGED_ORGANIZATION_SETTINGS"
+ ENABLED_INTEGRATION = "ENABLED_INTEGRATION"
+ DISABLED_INTEGRATION = "DISABLED_INTEGRATION"
+ ENABLED_CATEGORY = "ENABLED_CATEGORY"
+ DISABLED_CATEGORY = "DISABLED_CATEGORY"
+ CHANGED_PASSWORD = "CHANGED_PASSWORD"
+ RESET_PASSWORD = "RESET_PASSWORD"
+ ENABLED_REDACT_UNMAPPED_DATA_FOR_ORGANIZATION = "ENABLED_REDACT_UNMAPPED_DATA_FOR_ORGANIZATION"
+ ENABLED_REDACT_UNMAPPED_DATA_FOR_LINKED_ACCOUNT = "ENABLED_REDACT_UNMAPPED_DATA_FOR_LINKED_ACCOUNT"
+ DISABLED_REDACT_UNMAPPED_DATA_FOR_ORGANIZATION = "DISABLED_REDACT_UNMAPPED_DATA_FOR_ORGANIZATION"
+ DISABLED_REDACT_UNMAPPED_DATA_FOR_LINKED_ACCOUNT = "DISABLED_REDACT_UNMAPPED_DATA_FOR_LINKED_ACCOUNT"
+ CREATED_INTEGRATION_WIDE_FIELD_MAPPING = "CREATED_INTEGRATION_WIDE_FIELD_MAPPING"
+ CREATED_LINKED_ACCOUNT_FIELD_MAPPING = "CREATED_LINKED_ACCOUNT_FIELD_MAPPING"
+ CHANGED_INTEGRATION_WIDE_FIELD_MAPPING = "CHANGED_INTEGRATION_WIDE_FIELD_MAPPING"
+ CHANGED_LINKED_ACCOUNT_FIELD_MAPPING = "CHANGED_LINKED_ACCOUNT_FIELD_MAPPING"
+ DELETED_INTEGRATION_WIDE_FIELD_MAPPING = "DELETED_INTEGRATION_WIDE_FIELD_MAPPING"
+ DELETED_LINKED_ACCOUNT_FIELD_MAPPING = "DELETED_LINKED_ACCOUNT_FIELD_MAPPING"
+ CREATED_LINKED_ACCOUNT_COMMON_MODEL_OVERRIDE = "CREATED_LINKED_ACCOUNT_COMMON_MODEL_OVERRIDE"
+ CHANGED_LINKED_ACCOUNT_COMMON_MODEL_OVERRIDE = "CHANGED_LINKED_ACCOUNT_COMMON_MODEL_OVERRIDE"
+ DELETED_LINKED_ACCOUNT_COMMON_MODEL_OVERRIDE = "DELETED_LINKED_ACCOUNT_COMMON_MODEL_OVERRIDE"
+ FORCED_LINKED_ACCOUNT_RESYNC = "FORCED_LINKED_ACCOUNT_RESYNC"
+ MUTED_ISSUE = "MUTED_ISSUE"
+ GENERATED_MAGIC_LINK = "GENERATED_MAGIC_LINK"
+ ENABLED_MERGE_WEBHOOK = "ENABLED_MERGE_WEBHOOK"
+ DISABLED_MERGE_WEBHOOK = "DISABLED_MERGE_WEBHOOK"
+ MERGE_WEBHOOK_TARGET_CHANGED = "MERGE_WEBHOOK_TARGET_CHANGED"
+ END_USER_CREDENTIALS_ACCESSED = "END_USER_CREDENTIALS_ACCESSED"
+
+ def visit(
+ self,
+ created_remote_production_api_key: typing.Callable[[], T_Result],
+ deleted_remote_production_api_key: typing.Callable[[], T_Result],
+ created_test_api_key: typing.Callable[[], T_Result],
+ deleted_test_api_key: typing.Callable[[], T_Result],
+ regenerated_production_api_key: typing.Callable[[], T_Result],
+ regenerated_webhook_signature: typing.Callable[[], T_Result],
+ invited_user: typing.Callable[[], T_Result],
+ two_factor_auth_enabled: typing.Callable[[], T_Result],
+ two_factor_auth_disabled: typing.Callable[[], T_Result],
+ deleted_linked_account: typing.Callable[[], T_Result],
+ deleted_all_common_models_for_linked_account: typing.Callable[[], T_Result],
+ created_destination: typing.Callable[[], T_Result],
+ deleted_destination: typing.Callable[[], T_Result],
+ changed_destination: typing.Callable[[], T_Result],
+ changed_scopes: typing.Callable[[], T_Result],
+ changed_personal_information: typing.Callable[[], T_Result],
+ changed_organization_settings: typing.Callable[[], T_Result],
+ enabled_integration: typing.Callable[[], T_Result],
+ disabled_integration: typing.Callable[[], T_Result],
+ enabled_category: typing.Callable[[], T_Result],
+ disabled_category: typing.Callable[[], T_Result],
+ changed_password: typing.Callable[[], T_Result],
+ reset_password: typing.Callable[[], T_Result],
+ enabled_redact_unmapped_data_for_organization: typing.Callable[[], T_Result],
+ enabled_redact_unmapped_data_for_linked_account: typing.Callable[[], T_Result],
+ disabled_redact_unmapped_data_for_organization: typing.Callable[[], T_Result],
+ disabled_redact_unmapped_data_for_linked_account: typing.Callable[[], T_Result],
+ created_integration_wide_field_mapping: typing.Callable[[], T_Result],
+ created_linked_account_field_mapping: typing.Callable[[], T_Result],
+ changed_integration_wide_field_mapping: typing.Callable[[], T_Result],
+ changed_linked_account_field_mapping: typing.Callable[[], T_Result],
+ deleted_integration_wide_field_mapping: typing.Callable[[], T_Result],
+ deleted_linked_account_field_mapping: typing.Callable[[], T_Result],
+ created_linked_account_common_model_override: typing.Callable[[], T_Result],
+ changed_linked_account_common_model_override: typing.Callable[[], T_Result],
+ deleted_linked_account_common_model_override: typing.Callable[[], T_Result],
+ forced_linked_account_resync: typing.Callable[[], T_Result],
+ muted_issue: typing.Callable[[], T_Result],
+ generated_magic_link: typing.Callable[[], T_Result],
+ enabled_merge_webhook: typing.Callable[[], T_Result],
+ disabled_merge_webhook: typing.Callable[[], T_Result],
+ merge_webhook_target_changed: typing.Callable[[], T_Result],
+ end_user_credentials_accessed: typing.Callable[[], T_Result],
+ ) -> T_Result:
+ if self is EventTypeEnum.CREATED_REMOTE_PRODUCTION_API_KEY:
+ return created_remote_production_api_key()
+ if self is EventTypeEnum.DELETED_REMOTE_PRODUCTION_API_KEY:
+ return deleted_remote_production_api_key()
+ if self is EventTypeEnum.CREATED_TEST_API_KEY:
+ return created_test_api_key()
+ if self is EventTypeEnum.DELETED_TEST_API_KEY:
+ return deleted_test_api_key()
+ if self is EventTypeEnum.REGENERATED_PRODUCTION_API_KEY:
+ return regenerated_production_api_key()
+ if self is EventTypeEnum.REGENERATED_WEBHOOK_SIGNATURE:
+ return regenerated_webhook_signature()
+ if self is EventTypeEnum.INVITED_USER:
+ return invited_user()
+ if self is EventTypeEnum.TWO_FACTOR_AUTH_ENABLED:
+ return two_factor_auth_enabled()
+ if self is EventTypeEnum.TWO_FACTOR_AUTH_DISABLED:
+ return two_factor_auth_disabled()
+ if self is EventTypeEnum.DELETED_LINKED_ACCOUNT:
+ return deleted_linked_account()
+ if self is EventTypeEnum.DELETED_ALL_COMMON_MODELS_FOR_LINKED_ACCOUNT:
+ return deleted_all_common_models_for_linked_account()
+ if self is EventTypeEnum.CREATED_DESTINATION:
+ return created_destination()
+ if self is EventTypeEnum.DELETED_DESTINATION:
+ return deleted_destination()
+ if self is EventTypeEnum.CHANGED_DESTINATION:
+ return changed_destination()
+ if self is EventTypeEnum.CHANGED_SCOPES:
+ return changed_scopes()
+ if self is EventTypeEnum.CHANGED_PERSONAL_INFORMATION:
+ return changed_personal_information()
+ if self is EventTypeEnum.CHANGED_ORGANIZATION_SETTINGS:
+ return changed_organization_settings()
+ if self is EventTypeEnum.ENABLED_INTEGRATION:
+ return enabled_integration()
+ if self is EventTypeEnum.DISABLED_INTEGRATION:
+ return disabled_integration()
+ if self is EventTypeEnum.ENABLED_CATEGORY:
+ return enabled_category()
+ if self is EventTypeEnum.DISABLED_CATEGORY:
+ return disabled_category()
+ if self is EventTypeEnum.CHANGED_PASSWORD:
+ return changed_password()
+ if self is EventTypeEnum.RESET_PASSWORD:
+ return reset_password()
+ if self is EventTypeEnum.ENABLED_REDACT_UNMAPPED_DATA_FOR_ORGANIZATION:
+ return enabled_redact_unmapped_data_for_organization()
+ if self is EventTypeEnum.ENABLED_REDACT_UNMAPPED_DATA_FOR_LINKED_ACCOUNT:
+ return enabled_redact_unmapped_data_for_linked_account()
+ if self is EventTypeEnum.DISABLED_REDACT_UNMAPPED_DATA_FOR_ORGANIZATION:
+ return disabled_redact_unmapped_data_for_organization()
+ if self is EventTypeEnum.DISABLED_REDACT_UNMAPPED_DATA_FOR_LINKED_ACCOUNT:
+ return disabled_redact_unmapped_data_for_linked_account()
+ if self is EventTypeEnum.CREATED_INTEGRATION_WIDE_FIELD_MAPPING:
+ return created_integration_wide_field_mapping()
+ if self is EventTypeEnum.CREATED_LINKED_ACCOUNT_FIELD_MAPPING:
+ return created_linked_account_field_mapping()
+ if self is EventTypeEnum.CHANGED_INTEGRATION_WIDE_FIELD_MAPPING:
+ return changed_integration_wide_field_mapping()
+ if self is EventTypeEnum.CHANGED_LINKED_ACCOUNT_FIELD_MAPPING:
+ return changed_linked_account_field_mapping()
+ if self is EventTypeEnum.DELETED_INTEGRATION_WIDE_FIELD_MAPPING:
+ return deleted_integration_wide_field_mapping()
+ if self is EventTypeEnum.DELETED_LINKED_ACCOUNT_FIELD_MAPPING:
+ return deleted_linked_account_field_mapping()
+ if self is EventTypeEnum.CREATED_LINKED_ACCOUNT_COMMON_MODEL_OVERRIDE:
+ return created_linked_account_common_model_override()
+ if self is EventTypeEnum.CHANGED_LINKED_ACCOUNT_COMMON_MODEL_OVERRIDE:
+ return changed_linked_account_common_model_override()
+ if self is EventTypeEnum.DELETED_LINKED_ACCOUNT_COMMON_MODEL_OVERRIDE:
+ return deleted_linked_account_common_model_override()
+ if self is EventTypeEnum.FORCED_LINKED_ACCOUNT_RESYNC:
+ return forced_linked_account_resync()
+ if self is EventTypeEnum.MUTED_ISSUE:
+ return muted_issue()
+ if self is EventTypeEnum.GENERATED_MAGIC_LINK:
+ return generated_magic_link()
+ if self is EventTypeEnum.ENABLED_MERGE_WEBHOOK:
+ return enabled_merge_webhook()
+ if self is EventTypeEnum.DISABLED_MERGE_WEBHOOK:
+ return disabled_merge_webhook()
+ if self is EventTypeEnum.MERGE_WEBHOOK_TARGET_CHANGED:
+ return merge_webhook_target_changed()
+ if self is EventTypeEnum.END_USER_CREDENTIALS_ACCESSED:
+ return end_user_credentials_accessed()
diff --git a/src/merge/resources/email/types/external_target_field_api.py b/src/merge/resources/email/types/external_target_field_api.py
new file mode 100644
index 00000000..c0fea1eb
--- /dev/null
+++ b/src/merge/resources/email/types/external_target_field_api.py
@@ -0,0 +1,22 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+
+
+class ExternalTargetFieldApi(UncheckedBaseModel):
+ name: typing.Optional[str] = None
+ description: typing.Optional[str] = None
+ is_mapped: typing.Optional[str] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/external_target_field_api_response.py b/src/merge/resources/email/types/external_target_field_api_response.py
new file mode 100644
index 00000000..280fa60a
--- /dev/null
+++ b/src/merge/resources/email/types/external_target_field_api_response.py
@@ -0,0 +1,27 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+from .external_target_field_api import ExternalTargetFieldApi
+
+
+class ExternalTargetFieldApiResponse(UncheckedBaseModel):
+ user: typing.Optional[typing.List[ExternalTargetFieldApi]] = pydantic.Field(alias="User", default=None)
+ group: typing.Optional[typing.List[ExternalTargetFieldApi]] = pydantic.Field(alias="Group", default=None)
+ mailbox: typing.Optional[typing.List[ExternalTargetFieldApi]] = pydantic.Field(alias="Mailbox", default=None)
+ folder: typing.Optional[typing.List[ExternalTargetFieldApi]] = pydantic.Field(alias="Folder", default=None)
+ email_address: typing.Optional[typing.List[ExternalTargetFieldApi]] = pydantic.Field(
+ alias="EmailAddress", default=None
+ )
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/field_mapping_api_instance.py b/src/merge/resources/email/types/field_mapping_api_instance.py
new file mode 100644
index 00000000..5bac0110
--- /dev/null
+++ b/src/merge/resources/email/types/field_mapping_api_instance.py
@@ -0,0 +1,27 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+from .field_mapping_api_instance_remote_field import FieldMappingApiInstanceRemoteField
+from .field_mapping_api_instance_target_field import FieldMappingApiInstanceTargetField
+
+
+class FieldMappingApiInstance(UncheckedBaseModel):
+ id: typing.Optional[str] = None
+ is_integration_wide: typing.Optional[bool] = None
+ target_field: typing.Optional[FieldMappingApiInstanceTargetField] = None
+ remote_field: typing.Optional[FieldMappingApiInstanceRemoteField] = None
+ jmes_path: typing.Optional[str] = None
+ advanced_mapping_expression: typing.Optional[str] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/field_mapping_api_instance_remote_field.py b/src/merge/resources/email/types/field_mapping_api_instance_remote_field.py
new file mode 100644
index 00000000..578a2b10
--- /dev/null
+++ b/src/merge/resources/email/types/field_mapping_api_instance_remote_field.py
@@ -0,0 +1,27 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+from .field_mapping_api_instance_remote_field_remote_endpoint_info import (
+ FieldMappingApiInstanceRemoteFieldRemoteEndpointInfo,
+)
+
+
+class FieldMappingApiInstanceRemoteField(UncheckedBaseModel):
+ remote_key_name: typing.Optional[str] = None
+ schema_: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = pydantic.Field(
+ alias="schema", default=None
+ )
+ remote_endpoint_info: FieldMappingApiInstanceRemoteFieldRemoteEndpointInfo
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/field_mapping_api_instance_remote_field_remote_endpoint_info.py b/src/merge/resources/email/types/field_mapping_api_instance_remote_field_remote_endpoint_info.py
new file mode 100644
index 00000000..4171f08b
--- /dev/null
+++ b/src/merge/resources/email/types/field_mapping_api_instance_remote_field_remote_endpoint_info.py
@@ -0,0 +1,22 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+
+
+class FieldMappingApiInstanceRemoteFieldRemoteEndpointInfo(UncheckedBaseModel):
+ method: typing.Optional[str] = None
+ url_path: typing.Optional[str] = None
+ field_traversal_path: typing.Optional[typing.List[str]] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/field_mapping_api_instance_response.py b/src/merge/resources/email/types/field_mapping_api_instance_response.py
new file mode 100644
index 00000000..c3c882de
--- /dev/null
+++ b/src/merge/resources/email/types/field_mapping_api_instance_response.py
@@ -0,0 +1,27 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+from .field_mapping_api_instance import FieldMappingApiInstance
+
+
+class FieldMappingApiInstanceResponse(UncheckedBaseModel):
+ user: typing.Optional[typing.List[FieldMappingApiInstance]] = pydantic.Field(alias="User", default=None)
+ group: typing.Optional[typing.List[FieldMappingApiInstance]] = pydantic.Field(alias="Group", default=None)
+ mailbox: typing.Optional[typing.List[FieldMappingApiInstance]] = pydantic.Field(alias="Mailbox", default=None)
+ folder: typing.Optional[typing.List[FieldMappingApiInstance]] = pydantic.Field(alias="Folder", default=None)
+ email_address: typing.Optional[typing.List[FieldMappingApiInstance]] = pydantic.Field(
+ alias="EmailAddress", default=None
+ )
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/field_mapping_api_instance_target_field.py b/src/merge/resources/email/types/field_mapping_api_instance_target_field.py
new file mode 100644
index 00000000..e6474cba
--- /dev/null
+++ b/src/merge/resources/email/types/field_mapping_api_instance_target_field.py
@@ -0,0 +1,22 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+
+
+class FieldMappingApiInstanceTargetField(UncheckedBaseModel):
+ name: str
+ description: str
+ is_organization_wide: bool
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/field_mapping_instance_response.py b/src/merge/resources/email/types/field_mapping_instance_response.py
new file mode 100644
index 00000000..f921e641
--- /dev/null
+++ b/src/merge/resources/email/types/field_mapping_instance_response.py
@@ -0,0 +1,27 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+from .debug_mode_log import DebugModeLog
+from .error_validation_problem import ErrorValidationProblem
+from .field_mapping_api_instance import FieldMappingApiInstance
+from .warning_validation_problem import WarningValidationProblem
+
+
+class FieldMappingInstanceResponse(UncheckedBaseModel):
+ model: FieldMappingApiInstance
+ warnings: typing.List[WarningValidationProblem]
+ errors: typing.List[ErrorValidationProblem]
+ logs: typing.Optional[typing.List[DebugModeLog]] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/field_permission_deserializer.py b/src/merge/resources/email/types/field_permission_deserializer.py
new file mode 100644
index 00000000..1d71ae04
--- /dev/null
+++ b/src/merge/resources/email/types/field_permission_deserializer.py
@@ -0,0 +1,21 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+
+
+class FieldPermissionDeserializer(UncheckedBaseModel):
+ enabled_fields: typing.Optional[typing.List[typing.Optional[typing.Any]]] = None
+ disabled_fields: typing.Optional[typing.List[typing.Optional[typing.Any]]] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/field_permission_deserializer_request.py b/src/merge/resources/email/types/field_permission_deserializer_request.py
new file mode 100644
index 00000000..a4113b46
--- /dev/null
+++ b/src/merge/resources/email/types/field_permission_deserializer_request.py
@@ -0,0 +1,21 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+
+
+class FieldPermissionDeserializerRequest(UncheckedBaseModel):
+ enabled_fields: typing.Optional[typing.List[typing.Optional[typing.Any]]] = None
+ disabled_fields: typing.Optional[typing.List[typing.Optional[typing.Any]]] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/folder.py b/src/merge/resources/email/types/folder.py
new file mode 100644
index 00000000..af697568
--- /dev/null
+++ b/src/merge/resources/email/types/folder.py
@@ -0,0 +1,76 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+from .folder_field_mappings import FolderFieldMappings
+from .permission import Permission
+from .remote_data import RemoteData
+
+
+class Folder(UncheckedBaseModel):
+ """
+ # The Folder Object
+ ### Description
+ The `Folder` object is used to represent an email folder.
+ ### Usage Example
+ Fetch from the `GET /api/email/v1/folders` endpoint and view their folders.
+ """
+
+ id: typing.Optional[str] = None
+ remote_id: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ The third-party API ID of the matching object.
+ """
+
+ created_at: typing.Optional[dt.datetime] = pydantic.Field(default=None)
+ """
+ The datetime that this object was created by Merge.
+ """
+
+ modified_at: typing.Optional[dt.datetime] = pydantic.Field(default=None)
+ """
+ The datetime that this object was modified by Merge.
+ """
+
+ name: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ The name of the folder.
+ """
+
+ parent_folder: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ The folder that the folder belongs to.
+ """
+
+ permissions: typing.Optional[typing.List[Permission]] = None
+ mailboxes: typing.Optional[typing.List[typing.Optional[str]]] = None
+ remote_created_at: typing.Optional[dt.datetime] = pydantic.Field(default=None)
+ """
+ When the third party's folder was created.
+ """
+
+ remote_updated_at: typing.Optional[dt.datetime] = pydantic.Field(default=None)
+ """
+ When the third party's folder was updated.
+ """
+
+ remote_was_deleted: typing.Optional[bool] = pydantic.Field(default=None)
+ """
+ Indicates whether or not this object has been deleted in the third party platform. Full coverage deletion detection is a premium add-on. Native deletion detection is offered for free with limited coverage. [Learn more](https://docs.merge.dev/integrations/hris/supported-features/).
+ """
+
+ field_mappings: typing.Optional[FolderFieldMappings] = None
+ remote_data: typing.Optional[typing.List[RemoteData]] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/folder_field_mappings.py b/src/merge/resources/email/types/folder_field_mappings.py
new file mode 100644
index 00000000..b55828f8
--- /dev/null
+++ b/src/merge/resources/email/types/folder_field_mappings.py
@@ -0,0 +1,21 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+
+
+class FolderFieldMappings(UncheckedBaseModel):
+ organization_defined_targets: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = None
+ linked_account_defined_targets: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/group.py b/src/merge/resources/email/types/group.py
new file mode 100644
index 00000000..9731c129
--- /dev/null
+++ b/src/merge/resources/email/types/group.py
@@ -0,0 +1,71 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+from .group_field_mappings import GroupFieldMappings
+from .remote_data import RemoteData
+
+
+class Group(UncheckedBaseModel):
+ """
+ # The Group Object
+ ### Description
+ The `Group` object is used to represent an email group.
+ ### Usage Example
+ Fetch from the `GET /api/email/v1/groups` endpoint and view their groups.
+ """
+
+ id: typing.Optional[str] = None
+ remote_id: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ The third-party API ID of the matching object.
+ """
+
+ created_at: typing.Optional[dt.datetime] = pydantic.Field(default=None)
+ """
+ The datetime that this object was created by Merge.
+ """
+
+ modified_at: typing.Optional[dt.datetime] = pydantic.Field(default=None)
+ """
+ The datetime that this object was modified by Merge.
+ """
+
+ name: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ The name of the group.
+ """
+
+ users: typing.Optional[typing.List[typing.Optional[str]]] = None
+ email_addresses: typing.Optional[typing.List[typing.Optional[str]]] = None
+ mailboxes: typing.Optional[typing.List[typing.Optional[str]]] = None
+ remote_created_at: typing.Optional[dt.datetime] = pydantic.Field(default=None)
+ """
+ When the third party's group was created.
+ """
+
+ remote_updated_at: typing.Optional[dt.datetime] = pydantic.Field(default=None)
+ """
+ When the third party's group was updated.
+ """
+
+ remote_was_deleted: typing.Optional[bool] = pydantic.Field(default=None)
+ """
+ Indicates whether or not this object has been deleted in the third party platform. Full coverage deletion detection is a premium add-on. Native deletion detection is offered for free with limited coverage. [Learn more](https://docs.merge.dev/integrations/hris/supported-features/).
+ """
+
+ field_mappings: typing.Optional[GroupFieldMappings] = None
+ remote_data: typing.Optional[typing.List[RemoteData]] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/group_field_mappings.py b/src/merge/resources/email/types/group_field_mappings.py
new file mode 100644
index 00000000..3be990d2
--- /dev/null
+++ b/src/merge/resources/email/types/group_field_mappings.py
@@ -0,0 +1,21 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+
+
+class GroupFieldMappings(UncheckedBaseModel):
+ organization_defined_targets: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = None
+ linked_account_defined_targets: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/individual_common_model_scope_deserializer.py b/src/merge/resources/email/types/individual_common_model_scope_deserializer.py
new file mode 100644
index 00000000..4b1ef6a4
--- /dev/null
+++ b/src/merge/resources/email/types/individual_common_model_scope_deserializer.py
@@ -0,0 +1,24 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+from .field_permission_deserializer import FieldPermissionDeserializer
+from .model_permission_deserializer import ModelPermissionDeserializer
+
+
+class IndividualCommonModelScopeDeserializer(UncheckedBaseModel):
+ model_name: str
+ model_permissions: typing.Optional[typing.Dict[str, ModelPermissionDeserializer]] = None
+ field_permissions: typing.Optional[FieldPermissionDeserializer] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/individual_common_model_scope_deserializer_request.py b/src/merge/resources/email/types/individual_common_model_scope_deserializer_request.py
new file mode 100644
index 00000000..1dcda203
--- /dev/null
+++ b/src/merge/resources/email/types/individual_common_model_scope_deserializer_request.py
@@ -0,0 +1,24 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+from .field_permission_deserializer_request import FieldPermissionDeserializerRequest
+from .model_permission_deserializer_request import ModelPermissionDeserializerRequest
+
+
+class IndividualCommonModelScopeDeserializerRequest(UncheckedBaseModel):
+ model_name: str
+ model_permissions: typing.Optional[typing.Dict[str, ModelPermissionDeserializerRequest]] = None
+ field_permissions: typing.Optional[FieldPermissionDeserializerRequest] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/issue.py b/src/merge/resources/email/types/issue.py
new file mode 100644
index 00000000..8f1027ca
--- /dev/null
+++ b/src/merge/resources/email/types/issue.py
@@ -0,0 +1,33 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+from .issue_status import IssueStatus
+
+
+class Issue(UncheckedBaseModel):
+ id: typing.Optional[str] = None
+ status: typing.Optional[IssueStatus] = pydantic.Field(default=None)
+ """
+ Status of the issue.
+ """
+
+ error_description: str
+ end_user: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = None
+ first_incident_time: typing.Optional[dt.datetime] = None
+ last_incident_time: typing.Optional[dt.datetime] = None
+ is_muted: typing.Optional[bool] = None
+ error_details: typing.Optional[typing.List[str]] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/issue_status.py b/src/merge/resources/email/types/issue_status.py
new file mode 100644
index 00000000..8e4d6516
--- /dev/null
+++ b/src/merge/resources/email/types/issue_status.py
@@ -0,0 +1,7 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+from .issue_status_enum import IssueStatusEnum
+
+IssueStatus = typing.Union[IssueStatusEnum, str]
diff --git a/src/merge/resources/email/types/issue_status_enum.py b/src/merge/resources/email/types/issue_status_enum.py
new file mode 100644
index 00000000..d75e26e2
--- /dev/null
+++ b/src/merge/resources/email/types/issue_status_enum.py
@@ -0,0 +1,17 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import enum
+import typing
+
+T_Result = typing.TypeVar("T_Result")
+
+
+class IssueStatusEnum(str, enum.Enum):
+ ONGOING = "ONGOING"
+ RESOLVED = "RESOLVED"
+
+ def visit(self, ongoing: typing.Callable[[], T_Result], resolved: typing.Callable[[], T_Result]) -> T_Result:
+ if self is IssueStatusEnum.ONGOING:
+ return ongoing()
+ if self is IssueStatusEnum.RESOLVED:
+ return resolved()
diff --git a/src/merge/resources/email/types/language_enum.py b/src/merge/resources/email/types/language_enum.py
new file mode 100644
index 00000000..19f87fe0
--- /dev/null
+++ b/src/merge/resources/email/types/language_enum.py
@@ -0,0 +1,17 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import enum
+import typing
+
+T_Result = typing.TypeVar("T_Result")
+
+
+class LanguageEnum(str, enum.Enum):
+ EN = "en"
+ DE = "de"
+
+ def visit(self, en: typing.Callable[[], T_Result], de: typing.Callable[[], T_Result]) -> T_Result:
+ if self is LanguageEnum.EN:
+ return en()
+ if self is LanguageEnum.DE:
+ return de()
diff --git a/src/merge/resources/email/types/last_sync_result_enum.py b/src/merge/resources/email/types/last_sync_result_enum.py
new file mode 100644
index 00000000..52ecd845
--- /dev/null
+++ b/src/merge/resources/email/types/last_sync_result_enum.py
@@ -0,0 +1,37 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import enum
+import typing
+
+T_Result = typing.TypeVar("T_Result")
+
+
+class LastSyncResultEnum(str, enum.Enum):
+ SYNCING = "SYNCING"
+ DONE = "DONE"
+ FAILED = "FAILED"
+ DISABLED = "DISABLED"
+ PAUSED = "PAUSED"
+ PARTIALLY_SYNCED = "PARTIALLY_SYNCED"
+
+ def visit(
+ self,
+ syncing: typing.Callable[[], T_Result],
+ done: typing.Callable[[], T_Result],
+ failed: typing.Callable[[], T_Result],
+ disabled: typing.Callable[[], T_Result],
+ paused: typing.Callable[[], T_Result],
+ partially_synced: typing.Callable[[], T_Result],
+ ) -> T_Result:
+ if self is LastSyncResultEnum.SYNCING:
+ return syncing()
+ if self is LastSyncResultEnum.DONE:
+ return done()
+ if self is LastSyncResultEnum.FAILED:
+ return failed()
+ if self is LastSyncResultEnum.DISABLED:
+ return disabled()
+ if self is LastSyncResultEnum.PAUSED:
+ return paused()
+ if self is LastSyncResultEnum.PARTIALLY_SYNCED:
+ return partially_synced()
diff --git a/src/merge/resources/email/types/link_token.py b/src/merge/resources/email/types/link_token.py
new file mode 100644
index 00000000..f78dedeb
--- /dev/null
+++ b/src/merge/resources/email/types/link_token.py
@@ -0,0 +1,22 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+
+
+class LinkToken(UncheckedBaseModel):
+ link_token: str
+ integration_name: typing.Optional[str] = None
+ magic_link_url: typing.Optional[str] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/mailbox.py b/src/merge/resources/email/types/mailbox.py
new file mode 100644
index 00000000..4159c457
--- /dev/null
+++ b/src/merge/resources/email/types/mailbox.py
@@ -0,0 +1,90 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+from .mailbox_field_mappings import MailboxFieldMappings
+from .mailbox_type import MailboxType
+from .permission import Permission
+from .remote_data import RemoteData
+
+
+class Mailbox(UncheckedBaseModel):
+ """
+ # The Mailbox Object
+ ### Description
+ The `Mailbox` object is used to represent an email mailbox.
+ ### Usage Example
+ Fetch from the `GET /api/email/v1/mailboxes` endpoint and view their mailboxes.
+ """
+
+ id: typing.Optional[str] = None
+ remote_id: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ The third-party API ID of the matching object.
+ """
+
+ created_at: typing.Optional[dt.datetime] = pydantic.Field(default=None)
+ """
+ The datetime that this object was created by Merge.
+ """
+
+ modified_at: typing.Optional[dt.datetime] = pydantic.Field(default=None)
+ """
+ The datetime that this object was modified by Merge.
+ """
+
+ name: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ The name of the mailbox.
+ """
+
+ type: typing.Optional[MailboxType] = pydantic.Field(default=None)
+ """
+ The mailbox's type.
+ """
+
+ type_native: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ Remote field for type.
+ """
+
+ folders: typing.Optional[typing.List[typing.Optional[str]]] = None
+ groups: typing.Optional[typing.List[typing.Optional[str]]] = None
+ users: typing.Optional[typing.List[typing.Optional[str]]] = None
+ primary_email_address: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ The primary email address associated with the mailbox.
+ """
+
+ alias_email_addresses: typing.Optional[typing.List[typing.Optional[str]]] = None
+ permissions: typing.Optional[typing.List[Permission]] = None
+ remote_created_at: typing.Optional[dt.datetime] = pydantic.Field(default=None)
+ """
+ When the third party's mailbox was created.
+ """
+
+ remote_updated_at: typing.Optional[dt.datetime] = pydantic.Field(default=None)
+ """
+ When the third party's mailbox was updated.
+ """
+
+ remote_was_deleted: typing.Optional[bool] = pydantic.Field(default=None)
+ """
+ Indicates whether or not this object has been deleted in the third party platform. Full coverage deletion detection is a premium add-on. Native deletion detection is offered for free with limited coverage. [Learn more](https://docs.merge.dev/integrations/hris/supported-features/).
+ """
+
+ field_mappings: typing.Optional[MailboxFieldMappings] = None
+ remote_data: typing.Optional[typing.List[RemoteData]] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/mailbox_field_mappings.py b/src/merge/resources/email/types/mailbox_field_mappings.py
new file mode 100644
index 00000000..7ecc9cf7
--- /dev/null
+++ b/src/merge/resources/email/types/mailbox_field_mappings.py
@@ -0,0 +1,21 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+
+
+class MailboxFieldMappings(UncheckedBaseModel):
+ organization_defined_targets: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = None
+ linked_account_defined_targets: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/mailbox_type.py b/src/merge/resources/email/types/mailbox_type.py
new file mode 100644
index 00000000..c86dcf61
--- /dev/null
+++ b/src/merge/resources/email/types/mailbox_type.py
@@ -0,0 +1,7 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+from .mailbox_type_enum import MailboxTypeEnum
+
+MailboxType = typing.Union[MailboxTypeEnum, str]
diff --git a/src/merge/resources/email/types/mailbox_type_enum.py b/src/merge/resources/email/types/mailbox_type_enum.py
new file mode 100644
index 00000000..80c1883a
--- /dev/null
+++ b/src/merge/resources/email/types/mailbox_type_enum.py
@@ -0,0 +1,17 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import enum
+import typing
+
+T_Result = typing.TypeVar("T_Result")
+
+
+class MailboxTypeEnum(str, enum.Enum):
+ USER = "USER"
+ SHARED = "SHARED"
+
+ def visit(self, user: typing.Callable[[], T_Result], shared: typing.Callable[[], T_Result]) -> T_Result:
+ if self is MailboxTypeEnum.USER:
+ return user()
+ if self is MailboxTypeEnum.SHARED:
+ return shared()
diff --git a/src/merge/resources/email/types/message.py b/src/merge/resources/email/types/message.py
new file mode 100644
index 00000000..7797c47c
--- /dev/null
+++ b/src/merge/resources/email/types/message.py
@@ -0,0 +1,99 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+from .permission import Permission
+
+
+class Message(UncheckedBaseModel):
+ """
+ # The Message Object
+ ### Description
+ The `Message` object is used to represent an email message.
+ ### Usage Example
+ Fetch from the `GET /api/email/v1/messages` endpoint and view their messages.
+ """
+
+ id: typing.Optional[str] = None
+ remote_id: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ The third-party API ID of the matching object.
+ """
+
+ created_at: typing.Optional[dt.datetime] = pydantic.Field(default=None)
+ """
+ The datetime that this object was created by Merge.
+ """
+
+ modified_at: typing.Optional[dt.datetime] = pydantic.Field(default=None)
+ """
+ The datetime that this object was modified by Merge.
+ """
+
+ subject: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ The subject of the message.
+ """
+
+ body_text: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ The body text of the message.
+ """
+
+ message_url: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ The 3rd party url of the message.
+ """
+
+ sent_at: typing.Optional[dt.datetime] = pydantic.Field(default=None)
+ """
+ When the message was sent.
+ """
+
+ received_at: typing.Optional[dt.datetime] = pydantic.Field(default=None)
+ """
+ When the message was received.
+ """
+
+ is_draft: typing.Optional[bool] = pydantic.Field(default=None)
+ """
+ Whether the message is a draft.
+ """
+
+ from_address: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ The sender of the message.
+ """
+
+ thread: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ The thread that the message belongs to.
+ """
+
+ to: typing.Optional[typing.List[typing.Optional[str]]] = None
+ cc: typing.Optional[typing.List[typing.Optional[str]]] = None
+ bcc: typing.Optional[typing.List[typing.Optional[str]]] = None
+ mailboxes: typing.Optional[typing.List[typing.Optional[str]]] = None
+ permissions: typing.Optional[typing.List[Permission]] = None
+ folder: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ The folder that the message belongs to.
+ """
+
+ remote_was_deleted: typing.Optional[bool] = pydantic.Field(default=None)
+ """
+ Indicates whether or not this object has been deleted in the third party platform. Full coverage deletion detection is a premium add-on. Native deletion detection is offered for free with limited coverage. [Learn more](https://docs.merge.dev/integrations/hris/supported-features/).
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/method_enum.py b/src/merge/resources/email/types/method_enum.py
new file mode 100644
index 00000000..73d2556f
--- /dev/null
+++ b/src/merge/resources/email/types/method_enum.py
@@ -0,0 +1,41 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import enum
+import typing
+
+T_Result = typing.TypeVar("T_Result")
+
+
+class MethodEnum(str, enum.Enum):
+ GET = "GET"
+ OPTIONS = "OPTIONS"
+ HEAD = "HEAD"
+ POST = "POST"
+ PUT = "PUT"
+ PATCH = "PATCH"
+ DELETE = "DELETE"
+
+ def visit(
+ self,
+ get: typing.Callable[[], T_Result],
+ options: typing.Callable[[], T_Result],
+ head: typing.Callable[[], T_Result],
+ post: typing.Callable[[], T_Result],
+ put: typing.Callable[[], T_Result],
+ patch: typing.Callable[[], T_Result],
+ delete: typing.Callable[[], T_Result],
+ ) -> T_Result:
+ if self is MethodEnum.GET:
+ return get()
+ if self is MethodEnum.OPTIONS:
+ return options()
+ if self is MethodEnum.HEAD:
+ return head()
+ if self is MethodEnum.POST:
+ return post()
+ if self is MethodEnum.PUT:
+ return put()
+ if self is MethodEnum.PATCH:
+ return patch()
+ if self is MethodEnum.DELETE:
+ return delete()
diff --git a/src/merge/resources/email/types/model_operation.py b/src/merge/resources/email/types/model_operation.py
new file mode 100644
index 00000000..c367572d
--- /dev/null
+++ b/src/merge/resources/email/types/model_operation.py
@@ -0,0 +1,32 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+
+
+class ModelOperation(UncheckedBaseModel):
+ """
+ # The ModelOperation Object
+ ### Description
+ The `ModelOperation` object is used to represent the operations that are currently supported for a given model.
+
+ ### Usage Example
+ View what operations are supported for the `Candidate` endpoint.
+ """
+
+ model_name: str
+ available_operations: typing.List[str]
+ required_post_parameters: typing.List[str]
+ supported_fields: typing.List[str]
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/model_permission_deserializer.py b/src/merge/resources/email/types/model_permission_deserializer.py
new file mode 100644
index 00000000..6381814c
--- /dev/null
+++ b/src/merge/resources/email/types/model_permission_deserializer.py
@@ -0,0 +1,20 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+
+
+class ModelPermissionDeserializer(UncheckedBaseModel):
+ is_enabled: typing.Optional[bool] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/model_permission_deserializer_request.py b/src/merge/resources/email/types/model_permission_deserializer_request.py
new file mode 100644
index 00000000..cdc2ff4c
--- /dev/null
+++ b/src/merge/resources/email/types/model_permission_deserializer_request.py
@@ -0,0 +1,20 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+
+
+class ModelPermissionDeserializerRequest(UncheckedBaseModel):
+ is_enabled: typing.Optional[bool] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/multipart_form_field_request.py b/src/merge/resources/email/types/multipart_form_field_request.py
new file mode 100644
index 00000000..cb0039e1
--- /dev/null
+++ b/src/merge/resources/email/types/multipart_form_field_request.py
@@ -0,0 +1,53 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+from .multipart_form_field_request_encoding import MultipartFormFieldRequestEncoding
+
+
+class MultipartFormFieldRequest(UncheckedBaseModel):
+ """
+ # The MultipartFormField Object
+ ### Description
+ The `MultipartFormField` object is used to represent fields in an HTTP request using `multipart/form-data`.
+
+ ### Usage Example
+ Create a `MultipartFormField` to define a multipart form entry.
+ """
+
+ name: str = pydantic.Field()
+ """
+ The name of the form field
+ """
+
+ data: str = pydantic.Field()
+ """
+ The data for the form field.
+ """
+
+ encoding: typing.Optional[MultipartFormFieldRequestEncoding] = pydantic.Field(default=None)
+ """
+ The encoding of the value of `data`. Defaults to `RAW` if not defined.
+ """
+
+ file_name: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ The file name of the form field, if the field is for a file.
+ """
+
+ content_type: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ The MIME type of the file, if the field is for a file.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/multipart_form_field_request_encoding.py b/src/merge/resources/email/types/multipart_form_field_request_encoding.py
new file mode 100644
index 00000000..c6513b6b
--- /dev/null
+++ b/src/merge/resources/email/types/multipart_form_field_request_encoding.py
@@ -0,0 +1,7 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+from .encoding_enum import EncodingEnum
+
+MultipartFormFieldRequestEncoding = typing.Union[EncodingEnum, str]
diff --git a/src/merge/resources/email/types/paginated_account_details_and_actions_list.py b/src/merge/resources/email/types/paginated_account_details_and_actions_list.py
new file mode 100644
index 00000000..d2d16116
--- /dev/null
+++ b/src/merge/resources/email/types/paginated_account_details_and_actions_list.py
@@ -0,0 +1,23 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+from .account_details_and_actions import AccountDetailsAndActions
+
+
+class PaginatedAccountDetailsAndActionsList(UncheckedBaseModel):
+ next: typing.Optional[str] = None
+ previous: typing.Optional[str] = None
+ results: typing.Optional[typing.List[AccountDetailsAndActions]] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/paginated_audit_log_event_list.py b/src/merge/resources/email/types/paginated_audit_log_event_list.py
new file mode 100644
index 00000000..24139397
--- /dev/null
+++ b/src/merge/resources/email/types/paginated_audit_log_event_list.py
@@ -0,0 +1,23 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+from .audit_log_event import AuditLogEvent
+
+
+class PaginatedAuditLogEventList(UncheckedBaseModel):
+ next: typing.Optional[str] = None
+ previous: typing.Optional[str] = None
+ results: typing.Optional[typing.List[AuditLogEvent]] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/paginated_email_address_list.py b/src/merge/resources/email/types/paginated_email_address_list.py
new file mode 100644
index 00000000..cb95820d
--- /dev/null
+++ b/src/merge/resources/email/types/paginated_email_address_list.py
@@ -0,0 +1,23 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+from .email_address import EmailAddress
+
+
+class PaginatedEmailAddressList(UncheckedBaseModel):
+ next: typing.Optional[str] = None
+ previous: typing.Optional[str] = None
+ results: typing.Optional[typing.List[EmailAddress]] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/paginated_folder_list.py b/src/merge/resources/email/types/paginated_folder_list.py
new file mode 100644
index 00000000..643d17ed
--- /dev/null
+++ b/src/merge/resources/email/types/paginated_folder_list.py
@@ -0,0 +1,23 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+from .folder import Folder
+
+
+class PaginatedFolderList(UncheckedBaseModel):
+ next: typing.Optional[str] = None
+ previous: typing.Optional[str] = None
+ results: typing.Optional[typing.List[Folder]] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/paginated_group_list.py b/src/merge/resources/email/types/paginated_group_list.py
new file mode 100644
index 00000000..90702e1f
--- /dev/null
+++ b/src/merge/resources/email/types/paginated_group_list.py
@@ -0,0 +1,23 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+from .group import Group
+
+
+class PaginatedGroupList(UncheckedBaseModel):
+ next: typing.Optional[str] = None
+ previous: typing.Optional[str] = None
+ results: typing.Optional[typing.List[Group]] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/paginated_issue_list.py b/src/merge/resources/email/types/paginated_issue_list.py
new file mode 100644
index 00000000..686173e5
--- /dev/null
+++ b/src/merge/resources/email/types/paginated_issue_list.py
@@ -0,0 +1,23 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+from .issue import Issue
+
+
+class PaginatedIssueList(UncheckedBaseModel):
+ next: typing.Optional[str] = None
+ previous: typing.Optional[str] = None
+ results: typing.Optional[typing.List[Issue]] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/paginated_mailbox_list.py b/src/merge/resources/email/types/paginated_mailbox_list.py
new file mode 100644
index 00000000..391c9334
--- /dev/null
+++ b/src/merge/resources/email/types/paginated_mailbox_list.py
@@ -0,0 +1,23 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+from .mailbox import Mailbox
+
+
+class PaginatedMailboxList(UncheckedBaseModel):
+ next: typing.Optional[str] = None
+ previous: typing.Optional[str] = None
+ results: typing.Optional[typing.List[Mailbox]] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/paginated_message_list.py b/src/merge/resources/email/types/paginated_message_list.py
new file mode 100644
index 00000000..6e8a7aee
--- /dev/null
+++ b/src/merge/resources/email/types/paginated_message_list.py
@@ -0,0 +1,23 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+from .message import Message
+
+
+class PaginatedMessageList(UncheckedBaseModel):
+ next: typing.Optional[str] = None
+ previous: typing.Optional[str] = None
+ results: typing.Optional[typing.List[Message]] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/paginated_sync_status_list.py b/src/merge/resources/email/types/paginated_sync_status_list.py
new file mode 100644
index 00000000..cc4bd7a8
--- /dev/null
+++ b/src/merge/resources/email/types/paginated_sync_status_list.py
@@ -0,0 +1,23 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+from .sync_status import SyncStatus
+
+
+class PaginatedSyncStatusList(UncheckedBaseModel):
+ next: typing.Optional[str] = None
+ previous: typing.Optional[str] = None
+ results: typing.Optional[typing.List[SyncStatus]] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/paginated_user_list.py b/src/merge/resources/email/types/paginated_user_list.py
new file mode 100644
index 00000000..809b285c
--- /dev/null
+++ b/src/merge/resources/email/types/paginated_user_list.py
@@ -0,0 +1,23 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+from .user import User
+
+
+class PaginatedUserList(UncheckedBaseModel):
+ next: typing.Optional[str] = None
+ previous: typing.Optional[str] = None
+ results: typing.Optional[typing.List[User]] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/permission.py b/src/merge/resources/email/types/permission.py
new file mode 100644
index 00000000..2e51a422
--- /dev/null
+++ b/src/merge/resources/email/types/permission.py
@@ -0,0 +1,67 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+from .actions_enum import ActionsEnum
+from .permission_effect import PermissionEffect
+from .permission_field_mappings import PermissionFieldMappings
+
+
+class Permission(UncheckedBaseModel):
+ """
+ # The EmailPermission Object
+ ### Description
+ The `EmailPermission` object is used to represent a permission on an email resource.
+ ### Usage Example
+ Fetch from the `GET /api/email/v1/email-permissions` endpoint and view their email permissions.
+ """
+
+ id: typing.Optional[str] = None
+ remote_id: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ The third-party API ID of the matching object.
+ """
+
+ created_at: typing.Optional[dt.datetime] = pydantic.Field(default=None)
+ """
+ The datetime that this object was created by Merge.
+ """
+
+ modified_at: typing.Optional[dt.datetime] = pydantic.Field(default=None)
+ """
+ The datetime that this object was modified by Merge.
+ """
+
+ effect: typing.Optional[PermissionEffect] = pydantic.Field(default=None)
+ """
+ The permission's effect.
+ """
+
+ actions: typing.Optional[typing.List[typing.Optional[ActionsEnum]]] = pydantic.Field(default=None)
+ """
+ The actions that this permission applies to.
+ """
+
+ applied_to_users: typing.Optional[typing.List[typing.Optional[str]]] = None
+ applied_to_groups: typing.Optional[typing.List[typing.Optional[str]]] = None
+ applied_to_folders: typing.Optional[typing.List[typing.Optional[str]]] = None
+ applied_to_mailboxes: typing.Optional[typing.List[typing.Optional[str]]] = None
+ remote_was_deleted: typing.Optional[bool] = pydantic.Field(default=None)
+ """
+ Indicates whether or not this object has been deleted in the third party platform. Full coverage deletion detection is a premium add-on. Native deletion detection is offered for free with limited coverage. [Learn more](https://docs.merge.dev/integrations/hris/supported-features/).
+ """
+
+ field_mappings: typing.Optional[PermissionFieldMappings] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/permission_effect.py b/src/merge/resources/email/types/permission_effect.py
new file mode 100644
index 00000000..88d536ee
--- /dev/null
+++ b/src/merge/resources/email/types/permission_effect.py
@@ -0,0 +1,7 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+from .effect_enum import EffectEnum
+
+PermissionEffect = typing.Union[EffectEnum, str]
diff --git a/src/merge/resources/email/types/permission_field_mappings.py b/src/merge/resources/email/types/permission_field_mappings.py
new file mode 100644
index 00000000..9c2804c2
--- /dev/null
+++ b/src/merge/resources/email/types/permission_field_mappings.py
@@ -0,0 +1,21 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+
+
+class PermissionFieldMappings(UncheckedBaseModel):
+ organization_defined_targets: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = None
+ linked_account_defined_targets: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/regenerate_account_token.py b/src/merge/resources/email/types/regenerate_account_token.py
new file mode 100644
index 00000000..5c31cf57
--- /dev/null
+++ b/src/merge/resources/email/types/regenerate_account_token.py
@@ -0,0 +1,30 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+
+
+class RegenerateAccountToken(UncheckedBaseModel):
+ """
+ # The RegenerateAccountToken Object
+ ### Description
+ The `RegenerateAccountToken` object is used to exchange an old account token for a new one.
+
+ ### Usage Example
+ Post to receive a new `RegenerateAccountToken`.
+ """
+
+ linked_account_id: str
+ account_token: str
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/remote_data.py b/src/merge/resources/email/types/remote_data.py
new file mode 100644
index 00000000..f34bec80
--- /dev/null
+++ b/src/merge/resources/email/types/remote_data.py
@@ -0,0 +1,37 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+
+
+class RemoteData(UncheckedBaseModel):
+ """
+ # The RemoteData Object
+ ### Description
+ The `RemoteData` object is used to represent the full data pulled from the third-party API for an object.
+
+ ### Usage Example
+ TODO
+ """
+
+ path: str = pydantic.Field()
+ """
+ The third-party API path that is being called.
+ """
+
+ data: typing.Optional[typing.Optional[typing.Any]] = pydantic.Field(default=None)
+ """
+ The data returned from the third-party for this object in its original, unnormalized format.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/remote_endpoint_info.py b/src/merge/resources/email/types/remote_endpoint_info.py
new file mode 100644
index 00000000..07ceff6a
--- /dev/null
+++ b/src/merge/resources/email/types/remote_endpoint_info.py
@@ -0,0 +1,22 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+
+
+class RemoteEndpointInfo(UncheckedBaseModel):
+ method: str
+ url_path: str
+ field_traversal_path: typing.List[typing.Optional[typing.Any]]
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/remote_field_api.py b/src/merge/resources/email/types/remote_field_api.py
new file mode 100644
index 00000000..0756bfc3
--- /dev/null
+++ b/src/merge/resources/email/types/remote_field_api.py
@@ -0,0 +1,28 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+from .remote_endpoint_info import RemoteEndpointInfo
+from .remote_field_api_advanced_metadata import RemoteFieldApiAdvancedMetadata
+from .remote_field_api_coverage import RemoteFieldApiCoverage
+
+
+class RemoteFieldApi(UncheckedBaseModel):
+ schema_: typing.Dict[str, typing.Optional[typing.Any]] = pydantic.Field(alias="schema")
+ remote_key_name: str
+ remote_endpoint_info: RemoteEndpointInfo
+ example_values: typing.Optional[typing.List[typing.Optional[typing.Any]]] = None
+ advanced_metadata: typing.Optional[RemoteFieldApiAdvancedMetadata] = None
+ coverage: typing.Optional[RemoteFieldApiCoverage] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/remote_field_api_advanced_metadata.py b/src/merge/resources/email/types/remote_field_api_advanced_metadata.py
new file mode 100644
index 00000000..e93da936
--- /dev/null
+++ b/src/merge/resources/email/types/remote_field_api_advanced_metadata.py
@@ -0,0 +1,7 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+from .advanced_metadata import AdvancedMetadata
+
+RemoteFieldApiAdvancedMetadata = typing.Union[AdvancedMetadata, str]
diff --git a/src/merge/resources/email/types/remote_field_api_coverage.py b/src/merge/resources/email/types/remote_field_api_coverage.py
new file mode 100644
index 00000000..adcd9be9
--- /dev/null
+++ b/src/merge/resources/email/types/remote_field_api_coverage.py
@@ -0,0 +1,5 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+RemoteFieldApiCoverage = typing.Union[int, float]
diff --git a/src/merge/resources/email/types/remote_field_api_response.py b/src/merge/resources/email/types/remote_field_api_response.py
new file mode 100644
index 00000000..523e5892
--- /dev/null
+++ b/src/merge/resources/email/types/remote_field_api_response.py
@@ -0,0 +1,25 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+from .remote_field_api import RemoteFieldApi
+
+
+class RemoteFieldApiResponse(UncheckedBaseModel):
+ user: typing.Optional[typing.List[RemoteFieldApi]] = pydantic.Field(alias="User", default=None)
+ group: typing.Optional[typing.List[RemoteFieldApi]] = pydantic.Field(alias="Group", default=None)
+ mailbox: typing.Optional[typing.List[RemoteFieldApi]] = pydantic.Field(alias="Mailbox", default=None)
+ folder: typing.Optional[typing.List[RemoteFieldApi]] = pydantic.Field(alias="Folder", default=None)
+ email_address: typing.Optional[typing.List[RemoteFieldApi]] = pydantic.Field(alias="EmailAddress", default=None)
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/remote_key.py b/src/merge/resources/email/types/remote_key.py
new file mode 100644
index 00000000..c2482040
--- /dev/null
+++ b/src/merge/resources/email/types/remote_key.py
@@ -0,0 +1,30 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+
+
+class RemoteKey(UncheckedBaseModel):
+ """
+ # The RemoteKey Object
+ ### Description
+ The `RemoteKey` object is used to represent a request for a new remote key.
+
+ ### Usage Example
+ Post a `GenerateRemoteKey` to receive a new `RemoteKey`.
+ """
+
+ name: str
+ key: str
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/remote_response.py b/src/merge/resources/email/types/remote_response.py
new file mode 100644
index 00000000..db01131f
--- /dev/null
+++ b/src/merge/resources/email/types/remote_response.py
@@ -0,0 +1,36 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+from .remote_response_response_type import RemoteResponseResponseType
+
+
+class RemoteResponse(UncheckedBaseModel):
+ """
+ # The RemoteResponse Object
+ ### Description
+ The `RemoteResponse` object is used to represent information returned from a third-party endpoint.
+
+ ### Usage Example
+ View the `RemoteResponse` returned from your `DataPassthrough`.
+ """
+
+ method: str
+ path: str
+ status: int
+ response: typing.Optional[typing.Any] = None
+ response_headers: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = None
+ response_type: typing.Optional[RemoteResponseResponseType] = None
+ headers: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/remote_response_response_type.py b/src/merge/resources/email/types/remote_response_response_type.py
new file mode 100644
index 00000000..2556417a
--- /dev/null
+++ b/src/merge/resources/email/types/remote_response_response_type.py
@@ -0,0 +1,7 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+from .response_type_enum import ResponseTypeEnum
+
+RemoteResponseResponseType = typing.Union[ResponseTypeEnum, str]
diff --git a/src/merge/resources/email/types/request_format_enum.py b/src/merge/resources/email/types/request_format_enum.py
new file mode 100644
index 00000000..70ecd9bb
--- /dev/null
+++ b/src/merge/resources/email/types/request_format_enum.py
@@ -0,0 +1,25 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import enum
+import typing
+
+T_Result = typing.TypeVar("T_Result")
+
+
+class RequestFormatEnum(str, enum.Enum):
+ JSON = "JSON"
+ XML = "XML"
+ MULTIPART = "MULTIPART"
+
+ def visit(
+ self,
+ json: typing.Callable[[], T_Result],
+ xml: typing.Callable[[], T_Result],
+ multipart: typing.Callable[[], T_Result],
+ ) -> T_Result:
+ if self is RequestFormatEnum.JSON:
+ return json()
+ if self is RequestFormatEnum.XML:
+ return xml()
+ if self is RequestFormatEnum.MULTIPART:
+ return multipart()
diff --git a/src/merge/resources/email/types/response_type_enum.py b/src/merge/resources/email/types/response_type_enum.py
new file mode 100644
index 00000000..23b6bb5b
--- /dev/null
+++ b/src/merge/resources/email/types/response_type_enum.py
@@ -0,0 +1,17 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import enum
+import typing
+
+T_Result = typing.TypeVar("T_Result")
+
+
+class ResponseTypeEnum(str, enum.Enum):
+ JSON = "JSON"
+ BASE_64_GZIP = "BASE64_GZIP"
+
+ def visit(self, json: typing.Callable[[], T_Result], base_64_gzip: typing.Callable[[], T_Result]) -> T_Result:
+ if self is ResponseTypeEnum.JSON:
+ return json()
+ if self is ResponseTypeEnum.BASE_64_GZIP:
+ return base_64_gzip()
diff --git a/src/merge/resources/email/types/role_enum.py b/src/merge/resources/email/types/role_enum.py
new file mode 100644
index 00000000..c97de31f
--- /dev/null
+++ b/src/merge/resources/email/types/role_enum.py
@@ -0,0 +1,41 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import enum
+import typing
+
+T_Result = typing.TypeVar("T_Result")
+
+
+class RoleEnum(str, enum.Enum):
+ ADMIN = "ADMIN"
+ DEVELOPER = "DEVELOPER"
+ MEMBER = "MEMBER"
+ API = "API"
+ SYSTEM = "SYSTEM"
+ MERGE_TEAM = "MERGE_TEAM"
+ SUPPORT = "SUPPORT"
+
+ def visit(
+ self,
+ admin: typing.Callable[[], T_Result],
+ developer: typing.Callable[[], T_Result],
+ member: typing.Callable[[], T_Result],
+ api: typing.Callable[[], T_Result],
+ system: typing.Callable[[], T_Result],
+ merge_team: typing.Callable[[], T_Result],
+ support: typing.Callable[[], T_Result],
+ ) -> T_Result:
+ if self is RoleEnum.ADMIN:
+ return admin()
+ if self is RoleEnum.DEVELOPER:
+ return developer()
+ if self is RoleEnum.MEMBER:
+ return member()
+ if self is RoleEnum.API:
+ return api()
+ if self is RoleEnum.SYSTEM:
+ return system()
+ if self is RoleEnum.MERGE_TEAM:
+ return merge_team()
+ if self is RoleEnum.SUPPORT:
+ return support()
diff --git a/src/merge/resources/email/types/selective_sync_configurations_usage_enum.py b/src/merge/resources/email/types/selective_sync_configurations_usage_enum.py
new file mode 100644
index 00000000..7b486b59
--- /dev/null
+++ b/src/merge/resources/email/types/selective_sync_configurations_usage_enum.py
@@ -0,0 +1,19 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import enum
+import typing
+
+T_Result = typing.TypeVar("T_Result")
+
+
+class SelectiveSyncConfigurationsUsageEnum(str, enum.Enum):
+ IN_NEXT_SYNC = "IN_NEXT_SYNC"
+ IN_LAST_SYNC = "IN_LAST_SYNC"
+
+ def visit(
+ self, in_next_sync: typing.Callable[[], T_Result], in_last_sync: typing.Callable[[], T_Result]
+ ) -> T_Result:
+ if self is SelectiveSyncConfigurationsUsageEnum.IN_NEXT_SYNC:
+ return in_next_sync()
+ if self is SelectiveSyncConfigurationsUsageEnum.IN_LAST_SYNC:
+ return in_last_sync()
diff --git a/src/merge/resources/email/types/status_fd_5_enum.py b/src/merge/resources/email/types/status_fd_5_enum.py
new file mode 100644
index 00000000..3bf97afd
--- /dev/null
+++ b/src/merge/resources/email/types/status_fd_5_enum.py
@@ -0,0 +1,37 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import enum
+import typing
+
+T_Result = typing.TypeVar("T_Result")
+
+
+class StatusFd5Enum(str, enum.Enum):
+ SYNCING = "SYNCING"
+ DONE = "DONE"
+ FAILED = "FAILED"
+ DISABLED = "DISABLED"
+ PAUSED = "PAUSED"
+ PARTIALLY_SYNCED = "PARTIALLY_SYNCED"
+
+ def visit(
+ self,
+ syncing: typing.Callable[[], T_Result],
+ done: typing.Callable[[], T_Result],
+ failed: typing.Callable[[], T_Result],
+ disabled: typing.Callable[[], T_Result],
+ paused: typing.Callable[[], T_Result],
+ partially_synced: typing.Callable[[], T_Result],
+ ) -> T_Result:
+ if self is StatusFd5Enum.SYNCING:
+ return syncing()
+ if self is StatusFd5Enum.DONE:
+ return done()
+ if self is StatusFd5Enum.FAILED:
+ return failed()
+ if self is StatusFd5Enum.DISABLED:
+ return disabled()
+ if self is StatusFd5Enum.PAUSED:
+ return paused()
+ if self is StatusFd5Enum.PARTIALLY_SYNCED:
+ return partially_synced()
diff --git a/src/merge/resources/email/types/sync_status.py b/src/merge/resources/email/types/sync_status.py
new file mode 100644
index 00000000..e8564068
--- /dev/null
+++ b/src/merge/resources/email/types/sync_status.py
@@ -0,0 +1,41 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+from .selective_sync_configurations_usage_enum import SelectiveSyncConfigurationsUsageEnum
+from .sync_status_last_sync_result import SyncStatusLastSyncResult
+from .sync_status_status import SyncStatusStatus
+
+
+class SyncStatus(UncheckedBaseModel):
+ """
+ # The SyncStatus Object
+ ### Description
+ The `SyncStatus` object is used to represent the syncing state of an account
+
+ ### Usage Example
+ View the `SyncStatus` for an account to see how recently its models were synced.
+ """
+
+ model_name: str
+ model_id: str
+ last_sync_start: typing.Optional[dt.datetime] = None
+ next_sync_start: typing.Optional[dt.datetime] = None
+ last_sync_result: typing.Optional[SyncStatusLastSyncResult] = None
+ last_sync_finished: typing.Optional[dt.datetime] = None
+ status: SyncStatusStatus
+ is_initial_sync: bool
+ selective_sync_configurations_usage: typing.Optional[SelectiveSyncConfigurationsUsageEnum] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/sync_status_last_sync_result.py b/src/merge/resources/email/types/sync_status_last_sync_result.py
new file mode 100644
index 00000000..980e7d94
--- /dev/null
+++ b/src/merge/resources/email/types/sync_status_last_sync_result.py
@@ -0,0 +1,7 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+from .last_sync_result_enum import LastSyncResultEnum
+
+SyncStatusLastSyncResult = typing.Union[LastSyncResultEnum, str]
diff --git a/src/merge/resources/email/types/sync_status_status.py b/src/merge/resources/email/types/sync_status_status.py
new file mode 100644
index 00000000..78e4cc47
--- /dev/null
+++ b/src/merge/resources/email/types/sync_status_status.py
@@ -0,0 +1,7 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+from .status_fd_5_enum import StatusFd5Enum
+
+SyncStatusStatus = typing.Union[StatusFd5Enum, str]
diff --git a/src/merge/resources/email/types/user.py b/src/merge/resources/email/types/user.py
new file mode 100644
index 00000000..a6c96cab
--- /dev/null
+++ b/src/merge/resources/email/types/user.py
@@ -0,0 +1,82 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+from .remote_data import RemoteData
+from .user_field_mappings import UserFieldMappings
+from .user_type import UserType
+
+
+class User(UncheckedBaseModel):
+ """
+ # The User Object
+ ### Description
+ The `User` object is used to represent an email user.
+ ### Usage Example
+ Fetch from the `GET /api/email/v1/users` endpoint and view their users.
+ """
+
+ id: typing.Optional[str] = None
+ remote_id: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ The third-party API ID of the matching object.
+ """
+
+ created_at: typing.Optional[dt.datetime] = pydantic.Field(default=None)
+ """
+ The datetime that this object was created by Merge.
+ """
+
+ modified_at: typing.Optional[dt.datetime] = pydantic.Field(default=None)
+ """
+ The datetime that this object was modified by Merge.
+ """
+
+ name: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ The user's name.
+ """
+
+ type: typing.Optional[UserType] = pydantic.Field(default=None)
+ """
+ The user's type.
+ """
+
+ type_native: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ Remote field for type.
+ """
+
+ remote_created_at: typing.Optional[dt.datetime] = pydantic.Field(default=None)
+ """
+ When the third party's user was created.
+ """
+
+ remote_updated_at: typing.Optional[dt.datetime] = pydantic.Field(default=None)
+ """
+ When the third party's user was updated.
+ """
+
+ groups: typing.Optional[typing.List[typing.Optional[str]]] = None
+ mailboxes: typing.Optional[typing.List[typing.Optional[str]]] = None
+ email_addresses: typing.Optional[typing.List[typing.Optional[str]]] = None
+ remote_was_deleted: typing.Optional[bool] = pydantic.Field(default=None)
+ """
+ Indicates whether or not this object has been deleted in the third party platform. Full coverage deletion detection is a premium add-on. Native deletion detection is offered for free with limited coverage. [Learn more](https://docs.merge.dev/integrations/hris/supported-features/).
+ """
+
+ field_mappings: typing.Optional[UserFieldMappings] = None
+ remote_data: typing.Optional[typing.List[RemoteData]] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/user_field_mappings.py b/src/merge/resources/email/types/user_field_mappings.py
new file mode 100644
index 00000000..374935d7
--- /dev/null
+++ b/src/merge/resources/email/types/user_field_mappings.py
@@ -0,0 +1,21 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+
+
+class UserFieldMappings(UncheckedBaseModel):
+ organization_defined_targets: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = None
+ linked_account_defined_targets: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/user_type.py b/src/merge/resources/email/types/user_type.py
new file mode 100644
index 00000000..b6efee8a
--- /dev/null
+++ b/src/merge/resources/email/types/user_type.py
@@ -0,0 +1,7 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+from .user_type_enum import UserTypeEnum
+
+UserType = typing.Union[UserTypeEnum, str]
diff --git a/src/merge/resources/email/types/user_type_enum.py b/src/merge/resources/email/types/user_type_enum.py
new file mode 100644
index 00000000..f95c76c1
--- /dev/null
+++ b/src/merge/resources/email/types/user_type_enum.py
@@ -0,0 +1,25 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import enum
+import typing
+
+T_Result = typing.TypeVar("T_Result")
+
+
+class UserTypeEnum(str, enum.Enum):
+ INDIVIDUAL = "INDIVIDUAL"
+ SHARED = "SHARED"
+ EXTERNAL = "EXTERNAL"
+
+ def visit(
+ self,
+ individual: typing.Callable[[], T_Result],
+ shared: typing.Callable[[], T_Result],
+ external: typing.Callable[[], T_Result],
+ ) -> T_Result:
+ if self is UserTypeEnum.INDIVIDUAL:
+ return individual()
+ if self is UserTypeEnum.SHARED:
+ return shared()
+ if self is UserTypeEnum.EXTERNAL:
+ return external()
diff --git a/src/merge/resources/email/types/validation_problem_source.py b/src/merge/resources/email/types/validation_problem_source.py
new file mode 100644
index 00000000..fbebe626
--- /dev/null
+++ b/src/merge/resources/email/types/validation_problem_source.py
@@ -0,0 +1,20 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+
+
+class ValidationProblemSource(UncheckedBaseModel):
+ pointer: str
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/warning_validation_problem.py b/src/merge/resources/email/types/warning_validation_problem.py
new file mode 100644
index 00000000..28a56c2c
--- /dev/null
+++ b/src/merge/resources/email/types/warning_validation_problem.py
@@ -0,0 +1,27 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+from .validation_problem_source import ValidationProblemSource
+
+
+class WarningValidationProblem(UncheckedBaseModel):
+ source: typing.Optional[ValidationProblemSource] = None
+ title: str
+ detail: str
+ problem_type: str
+ block_merge_link: typing.Optional[bool] = None
+ raw_error: typing.Optional[str] = None
+ error_code: typing.Optional[int] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/merge/resources/email/types/webhook_receiver.py b/src/merge/resources/email/types/webhook_receiver.py
new file mode 100644
index 00000000..fb49c044
--- /dev/null
+++ b/src/merge/resources/email/types/webhook_receiver.py
@@ -0,0 +1,22 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ....core.pydantic_utilities import IS_PYDANTIC_V2
+from ....core.unchecked_base_model import UncheckedBaseModel
+
+
+class WebhookReceiver(UncheckedBaseModel):
+ event: str
+ is_active: bool
+ key: typing.Optional[str] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow