diff --git a/poetry.lock b/poetry.lock index ea08ef08..d18ca797 100644 --- a/poetry.lock +++ b/poetry.lock @@ -38,13 +38,13 @@ trio = ["trio (>=0.26.1)"] [[package]] name = "certifi" -version = "2025.10.5" +version = "2025.11.12" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.7" files = [ - {file = "certifi-2025.10.5-py3-none-any.whl", hash = "sha256:0f212c2744a9bb6de0c56639a6f68afe01ecd92d91f14ae897c4fe7bbeeef0de"}, - {file = "certifi-2025.10.5.tar.gz", hash = "sha256:47c09d31ccf2acf0be3f701ea53595ee7e0b8fa08801c6624be771df09ae7b43"}, + {file = "certifi-2025.11.12-py3-none-any.whl", hash = "sha256:97de8790030bbd5c2d96b7ec782fc2f7820ef8dba6db909ccf95449f2d062d4b"}, + {file = "certifi-2025.11.12.tar.gz", hash = "sha256:d8ab5478f2ecd78af242878415affce761ca6bc54a22a27e026d7c25357c3316"}, ] [[package]] diff --git a/pyproject.toml b/pyproject.toml index c9f17861..f9299f31 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,7 +3,7 @@ name = "sayari" [tool.poetry] name = "sayari" -version = "0.1.43" +version = "0.1.44" description = "A Python SDK for Sayari" readme = "README.md" authors = [ diff --git a/reference.md b/reference.md index 3121accd..d9af5d89 100644 --- a/reference.md +++ b/reference.md @@ -3684,6 +3684,190 @@ client.project_entity.get_project_entity( + + + + +
client.project_entity.add_project_entity_matches(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Adds matches to a project entity. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from sayari import Sayari +from sayari.project_entity import UpdateProjectEntityMatchesBody + +client = Sayari( + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +client.project_entity.add_project_entity_matches( + project_id="project_id", + project_entity_id="project_entity_id", + request=UpdateProjectEntityMatchesBody( + entity_ids=["entity_ids", "entity_ids"], + ), +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**project_id:** `str` + +
+
+ +
+
+ +**project_entity_id:** `str` + +
+
+ +
+
+ +**request:** `UpdateProjectEntityMatchesBody` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.project_entity.replace_project_entity_matches(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Replace matches in a project entity. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from sayari import Sayari +from sayari.project_entity import UpdateProjectEntityMatchesBody + +client = Sayari( + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +client.project_entity.replace_project_entity_matches( + project_id="project_id", + project_entity_id="project_entity_id", + request=UpdateProjectEntityMatchesBody( + entity_ids=["entity_ids", "entity_ids"], + ), +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**project_id:** `str` + +
+
+ +
+
+ +**project_entity_id:** `str` + +
+
+ +
+
+ +**request:** `UpdateProjectEntityMatchesBody` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ +
@@ -5016,6 +5200,7 @@ client = Sayari( client.project.create_project( request=CreateProjectRequest( label="My First Project", + type="network", share=ProjectShareOnCreate( org="admin", ), @@ -5140,6 +5325,14 @@ client.project.get_projects(
+**type:** `typing.Optional[ProjectType]` — Which project types to return + +
+
+ +
+
+ **request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
diff --git a/src/sayari/__init__.py b/src/sayari/__init__.py index d73b5232..26543ce7 100644 --- a/src/sayari/__init__.py +++ b/src/sayari/__init__.py @@ -204,6 +204,7 @@ ProjectEntity, ProjectEntityUpstream, ProjectShareOnCreate, + ProjectType, ProjectWithMembers, PsaSummary, Role, @@ -279,6 +280,8 @@ TradeCounts, Translation, UpdateEntityTagsResponse, + UpdateProjectEntityMatchesBody, + UpdateProjectEntityMatchesResponse, UpdateProjectEntityTagsBody, UpstreamCount, UpstreamInfo, @@ -353,6 +356,7 @@ UnprocessableContentResponse, ) from .shared_types import ( + CaseInfo, CaseStatus, ClientName, CompanyType, @@ -467,6 +471,7 @@ "BusinessPurposeProperties", "BusinessPurposeStandard", "BuyerSearchResponse", + "CaseInfo", "CaseStatus", "ClientName", "CompanyStatus", @@ -692,6 +697,7 @@ "ProjectRiskChangesResponseData", "ProjectRiskFactor", "ProjectShareOnCreate", + "ProjectType", "ProjectWithMembers", "Psa", "PsaEntity", @@ -817,6 +823,8 @@ "UpdateProjectEntityAttributeRequest", "UpdateProjectEntityAttributeResponse", "UpdateProjectEntityAttributeResponseData", + "UpdateProjectEntityMatchesBody", + "UpdateProjectEntityMatchesResponse", "UpdateProjectEntityTagsBody", "UpstreamCount", "UpstreamInfo", diff --git a/src/sayari/core/client_wrapper.py b/src/sayari/core/client_wrapper.py index f5ae1103..b2e88806 100644 --- a/src/sayari/core/client_wrapper.py +++ b/src/sayari/core/client_wrapper.py @@ -22,7 +22,7 @@ def get_headers(self) -> typing.Dict[str, str]: headers: typing.Dict[str, str] = { "X-Fern-Language": "Python", "X-Fern-SDK-Name": "sayari", - "X-Fern-SDK-Version": "0.1.43", + "X-Fern-SDK-Version": "0.1.44", } token = self._get_token() if token is not None: diff --git a/src/sayari/generated_types/types/identifier_type.py b/src/sayari/generated_types/types/identifier_type.py index defba80a..bde8faac 100644 --- a/src/sayari/generated_types/types/identifier_type.py +++ b/src/sayari/generated_types/types/identifier_type.py @@ -44,6 +44,7 @@ "aus_credit_licence_number", "aus_credit_rep_number", "aus_passport", + "aus_trademark_reg_no", "aut_firmenbuch_no", "aut_uid", "aze_tin_number", @@ -287,8 +288,10 @@ "ind_passport", "ind_permanent_account_number", "ind_society_registration_number", + "ind_techsalerator_id", "ind_tin", "ind_trademark_submission_ref", + "ind_udyam", "int_maritime_org_id", "internal_curated_merge_id", "internal_curated_split_id", @@ -328,6 +331,7 @@ "jpn_edinet_code", "jpn_trade_internal_shipment_id", "kaz_bin", + "kaz_business_identification_number", "kaz_identifier", "kaz_okpo_num", "kaz_state_reg_num", @@ -545,6 +549,8 @@ "tjk_ein_number", "tjk_tin_number", "tokyo_stock_exchange_no", + "ton_reg_id", + "ton_tax_id", "tto_biz_number", "tun_passport", "tur_id", @@ -701,6 +707,7 @@ "wcpfc_rfmo_id", "wipo_intl_ref_no", "wipo_intl_reg_no", + "wsm_reg_id", "xxx_acuris_id", "xxx_cedar_rose_uid", "xxx_crb_monitor_entity_id", diff --git a/src/sayari/generated_types/types/risk.py b/src/sayari/generated_types/types/risk.py index 46dcb8d2..363053bb 100644 --- a/src/sayari/generated_types/types/risk.py +++ b/src/sayari/generated_types/types/risk.py @@ -8,6 +8,7 @@ "aspi_uyghur_forced_labor_report_entity_adjacent", "basel_aml", "bis_addresses_high_diversion_risk", + "bis_affiliates_50_percent_rule", "bis_boycott_requester_list", "chinese_soe_adjacent", "chinese_state_owned", @@ -40,12 +41,15 @@ "export_controls_bis_entity_50_percent_rule", "export_controls_bis_meu", "export_controls_bis_meu_50_percent_rule", + "export_controls_other", + "export_controls_other_adjacent", "export_controls_section_1260h", "export_controls_section_1260h_50_percent_rule", "export_controls_unverified_list", "export_controls_unverified_list_50_percent_rule", "export_to_chinese_soe", "export_to_sanctioned", + "export_to_sanctioned_other", "export_to_soe", "exports_bis_high_priority_items_critical_components_direct", "exports_bis_high_priority_items_critical_components_indirect", @@ -202,6 +206,7 @@ "owned_by_chinese_soe", "owned_by_cmic_entity", "owned_by_entity_in_export_controls", + "owned_by_entity_in_export_controls_other", "owned_by_forced_labor_xinjiang_uflpa", "owned_by_jpn_meti_end_user_entity", "owned_by_jpn_mofa_export_ban_entity", @@ -233,6 +238,7 @@ "owned_by_sanctioned_mys_moha_entity", "owned_by_sanctioned_nld_mofa_entity", "owned_by_sanctioned_nzl_mfat_rus_entity", + "owned_by_sanctioned_other_entity", "owned_by_sanctioned_pol_mia_entity", "owned_by_sanctioned_sgp_agc_entity", "owned_by_sanctioned_ukr_nsdc_entity", @@ -257,6 +263,7 @@ "owner_of_aspi_forced_labor_entity", "owner_of_chinese_soe", "owner_of_export_controls_entity", + "owner_of_export_controls_other_entity", "owner_of_forced_labor_xinjiang_entity", "owner_of_forced_labor_xinjiang_uflpa", "owner_of_jpn_meti_end_user_entity", @@ -289,6 +296,7 @@ "owner_of_sanctioned_mys_moha_entity", "owner_of_sanctioned_nld_mofa_entity", "owner_of_sanctioned_nzl_mfat_rus_entity", + "owner_of_sanctioned_other_entity", "owner_of_sanctioned_pol_mia_entity", "owner_of_sanctioned_sgp_agc_entity", "owner_of_sanctioned_ukr_nsdc_entity", @@ -319,10 +327,12 @@ "psa_export_controls", "psa_export_controls_bis_entity_50_percent_rule", "psa_export_controls_bis_meu_50_percent_rule", + "psa_export_controls_other", "psa_export_controls_section_1260h_50_percent_rule", "psa_export_controls_unverified_list_50_percent_rule", "psa_export_to_chinese_soe", "psa_export_to_sanctioned", + "psa_export_to_sanctioned_other", "psa_export_to_soe", "psa_exports_bis_high_priority_items_critical_components_direct", "psa_exports_bis_high_priority_items_critical_components_indirect", @@ -429,6 +439,7 @@ "psa_owned_by_chinese_soe", "psa_owned_by_cmic_entity", "psa_owned_by_entity_in_export_controls", + "psa_owned_by_entity_in_export_controls_other", "psa_owned_by_forced_labor_xinjiang_uflpa", "psa_owned_by_jpn_meti_end_user_entity", "psa_owned_by_jpn_mofa_export_ban_entity", @@ -460,6 +471,7 @@ "psa_owned_by_sanctioned_mys_moha_entity", "psa_owned_by_sanctioned_nld_mofa_entity", "psa_owned_by_sanctioned_nzl_mfat_rus_entity", + "psa_owned_by_sanctioned_other_entity", "psa_owned_by_sanctioned_pol_mia_entity", "psa_owned_by_sanctioned_sgp_agc_entity", "psa_owned_by_sanctioned_ukr_nsdc_entity", @@ -484,6 +496,7 @@ "psa_owner_of_aspi_forced_labor_entity", "psa_owner_of_chinese_soe", "psa_owner_of_export_controls_entity", + "psa_owner_of_export_controls_other_entity", "psa_owner_of_forced_labor_xinjiang_entity", "psa_owner_of_forced_labor_xinjiang_uflpa", "psa_owner_of_jpn_meti_end_user_entity", @@ -516,6 +529,7 @@ "psa_owner_of_sanctioned_mys_moha_entity", "psa_owner_of_sanctioned_nld_mofa_entity", "psa_owner_of_sanctioned_nzl_mfat_rus_entity", + "psa_owner_of_sanctioned_other_entity", "psa_owner_of_sanctioned_pol_mia_entity", "psa_owner_of_sanctioned_sgp_agc_entity", "psa_owner_of_sanctioned_ukr_nsdc_entity", @@ -558,6 +572,7 @@ "psa_sanctioned_mys_moha", "psa_sanctioned_nld_mofa", "psa_sanctioned_nzl_mfat_rus", + "psa_sanctioned_other", "psa_sanctioned_pol_mia", "psa_sanctioned_sgp_agc", "psa_sanctioned_ukr_nsdc", @@ -616,6 +631,8 @@ "sanctioned_mys_moha", "sanctioned_nld_mofa", "sanctioned_nzl_mfat_rus", + "sanctioned_other", + "sanctioned_other_adjacent", "sanctioned_pol_mia", "sanctioned_sgp_agc", "sanctioned_ukr_nsdc", diff --git a/src/sayari/generated_types/types/weak_identifier_type.py b/src/sayari/generated_types/types/weak_identifier_type.py index efdfc676..f5b9dd81 100644 --- a/src/sayari/generated_types/types/weak_identifier_type.py +++ b/src/sayari/generated_types/types/weak_identifier_type.py @@ -54,6 +54,7 @@ "ind_sebi", "ind_shipment_bill_id", "int_trade_internal_shipment_id", + "international_trademark_no", "irl_registration_no", "irn_reg_number", "irq_provision_card", @@ -129,6 +130,7 @@ "south_africa_partial_id_number", "svk_filing_number", "tokyo_shoko_id", + "ton_foreign_investor_id", "tur_declaration_number", "tur_office_registration_number", "tur_partial_mersis_number", diff --git a/src/sayari/project/__init__.py b/src/sayari/project/__init__.py index 8570e7de..bc92b03d 100644 --- a/src/sayari/project/__init__.py +++ b/src/sayari/project/__init__.py @@ -17,6 +17,7 @@ ProjectEntity, ProjectEntityUpstream, ProjectShareOnCreate, + ProjectType, ProjectWithMembers, PsaSummary, Role, @@ -47,6 +48,7 @@ "ProjectEntity", "ProjectEntityUpstream", "ProjectShareOnCreate", + "ProjectType", "ProjectWithMembers", "PsaSummary", "Role", diff --git a/src/sayari/project/client.py b/src/sayari/project/client.py index 6962d3d7..a570b664 100644 --- a/src/sayari/project/client.py +++ b/src/sayari/project/client.py @@ -21,6 +21,7 @@ from ..shared_errors.types.internal_server_error_response import InternalServerErrorResponse from json.decoder import JSONDecodeError from ..core.api_error import ApiError +from .types.project_type import ProjectType from .types.get_projects_response import GetProjectsResponse from .types.delete_project_response import DeleteProjectResponse from ..core.jsonable_encoder import jsonable_encoder @@ -63,6 +64,7 @@ def create_project( client.project.create_project( request=CreateProjectRequest( label="My First Project", + type="network", share=ProjectShareOnCreate( org="admin", ), @@ -159,6 +161,7 @@ def get_projects( prev: typing.Optional[str] = None, limit: typing.Optional[int] = None, archived: typing.Optional[bool] = None, + type: typing.Optional[ProjectType] = None, request_options: typing.Optional[RequestOptions] = None, ) -> GetProjectsResponse: """ @@ -178,6 +181,9 @@ def get_projects( archived : typing.Optional[bool] Toggle between projects that have been archived (true) or not (false). Defaults to false. + type : typing.Optional[ProjectType] + Which project types to return + request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -206,6 +212,7 @@ def get_projects( "prev": prev, "limit": limit, "archived": archived, + "type": type, }, request_options=request_options, ) @@ -430,6 +437,7 @@ async def main() -> None: await client.project.create_project( request=CreateProjectRequest( label="My First Project", + type="network", share=ProjectShareOnCreate( org="admin", ), @@ -529,6 +537,7 @@ async def get_projects( prev: typing.Optional[str] = None, limit: typing.Optional[int] = None, archived: typing.Optional[bool] = None, + type: typing.Optional[ProjectType] = None, request_options: typing.Optional[RequestOptions] = None, ) -> GetProjectsResponse: """ @@ -548,6 +557,9 @@ async def get_projects( archived : typing.Optional[bool] Toggle between projects that have been archived (true) or not (false). Defaults to false. + type : typing.Optional[ProjectType] + Which project types to return + request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -584,6 +596,7 @@ async def main() -> None: "prev": prev, "limit": limit, "archived": archived, + "type": type, }, request_options=request_options, ) diff --git a/src/sayari/project/types/__init__.py b/src/sayari/project/types/__init__.py index 51e53adf..22242d37 100644 --- a/src/sayari/project/types/__init__.py +++ b/src/sayari/project/types/__init__.py @@ -16,6 +16,7 @@ from .project_entity import ProjectEntity from .project_entity_upstream import ProjectEntityUpstream from .project_share_on_create import ProjectShareOnCreate +from .project_type import ProjectType from .project_with_members import ProjectWithMembers from .psa_summary import PsaSummary from .role import Role @@ -45,6 +46,7 @@ "ProjectEntity", "ProjectEntityUpstream", "ProjectShareOnCreate", + "ProjectType", "ProjectWithMembers", "PsaSummary", "Role", diff --git a/src/sayari/project/types/create_project_request.py b/src/sayari/project/types/create_project_request.py index a35ec56e..88a13eee 100644 --- a/src/sayari/project/types/create_project_request.py +++ b/src/sayari/project/types/create_project_request.py @@ -2,8 +2,9 @@ from ...core.pydantic_utilities import UniversalBaseModel import typing -from .project_share_on_create import ProjectShareOnCreate +from .project_type import ProjectType import pydantic +from .project_share_on_create import ProjectShareOnCreate from ...core.pydantic_utilities import IS_PYDANTIC_V2 @@ -15,6 +16,7 @@ class CreateProjectRequest(UniversalBaseModel): CreateProjectRequest( label="My First Project", + type="network", share=ProjectShareOnCreate( org="admin", ), @@ -22,6 +24,11 @@ class CreateProjectRequest(UniversalBaseModel): """ label: str + type: typing.Optional[ProjectType] = pydantic.Field(default=None) + """ + Specifies which type of project to create. Defaults to 'network' + """ + share: typing.Optional[ProjectShareOnCreate] = pydantic.Field(default=None) """ Specifies access levels available to users in a project within an organization. For comprehensive access, the admin role is recommended. diff --git a/src/sayari/project/types/create_project_response.py b/src/sayari/project/types/create_project_response.py index 8ba9371f..0e0ea8ec 100644 --- a/src/sayari/project/types/create_project_response.py +++ b/src/sayari/project/types/create_project_response.py @@ -27,6 +27,7 @@ class CreateProjectResponse(UniversalBaseModel): search=0, ), is_scrm=False, + type="network", ), ) """ diff --git a/src/sayari/project/types/delete_project_response.py b/src/sayari/project/types/delete_project_response.py index 6fc75cc3..6d6ba11a 100644 --- a/src/sayari/project/types/delete_project_response.py +++ b/src/sayari/project/types/delete_project_response.py @@ -20,6 +20,7 @@ class DeleteProjectResponse(UniversalBaseModel): archived=False, created="2024-04-24 13:43:56.546705+00", updated="2024-04-24 13:43:56.546705+00", + type="network", counts=ProjectCounts( entity=2, graph=0, diff --git a/src/sayari/project/types/get_projects_response.py b/src/sayari/project/types/get_projects_response.py index 10ef3ec1..74c539a3 100644 --- a/src/sayari/project/types/get_projects_response.py +++ b/src/sayari/project/types/get_projects_response.py @@ -29,6 +29,7 @@ class GetProjectsResponse(UniversalBaseModel): archived=False, created="2023-10-25 14:44:06.322117+00", updated="2023-10-25 14:44:06.322117+00", + type="network", counts=ProjectCounts(), members=[ RoleMember( @@ -46,6 +47,7 @@ class GetProjectsResponse(UniversalBaseModel): archived=False, created="2023-10-24 20:41:21.235451+00", updated="2023-10-24 20:41:21.235451+00", + type="network", counts=ProjectCounts( graph=1, entity=2530, diff --git a/src/sayari/project/types/project.py b/src/sayari/project/types/project.py index 55dc9eaf..d063a54c 100644 --- a/src/sayari/project/types/project.py +++ b/src/sayari/project/types/project.py @@ -4,6 +4,7 @@ import pydantic from .project_counts import ProjectCounts import typing +from .project_type import ProjectType from ...core.pydantic_utilities import IS_PYDANTIC_V2 @@ -26,7 +27,12 @@ class Project(UniversalBaseModel): created: str updated: str counts: ProjectCounts - is_scrm: typing.Optional[bool] = None + is_scrm: typing.Optional[bool] = pydantic.Field(default=None) + """ + **Deprecated.** Use `type == 'supply_chain'` instead. + """ + + type: ProjectType if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/sayari/project/types/project_type.py b/src/sayari/project/types/project_type.py new file mode 100644 index 00000000..caf22caf --- /dev/null +++ b/src/sayari/project/types/project_type.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +ProjectType = typing.Union[typing.Literal["network", "supply_chain"], typing.Any] diff --git a/src/sayari/project_entity/__init__.py b/src/sayari/project_entity/__init__.py index e5d8e9bb..74f0784c 100644 --- a/src/sayari/project_entity/__init__.py +++ b/src/sayari/project_entity/__init__.py @@ -63,6 +63,8 @@ TradeCounts, Translation, UpdateEntityTagsResponse, + UpdateProjectEntityMatchesBody, + UpdateProjectEntityMatchesResponse, UpdateProjectEntityTagsBody, UpstreamCount, UpstreamInfo, @@ -131,6 +133,8 @@ "TradeCounts", "Translation", "UpdateEntityTagsResponse", + "UpdateProjectEntityMatchesBody", + "UpdateProjectEntityMatchesResponse", "UpdateProjectEntityTagsBody", "UpstreamCount", "UpstreamInfo", diff --git a/src/sayari/project_entity/client.py b/src/sayari/project_entity/client.py index 427139e7..feedfd61 100644 --- a/src/sayari/project_entity/client.py +++ b/src/sayari/project_entity/client.py @@ -24,6 +24,8 @@ from ..core.api_error import ApiError from .types.project_entities_filter import ProjectEntitiesFilter from .types.project_entities_response import ProjectEntitiesResponse +from .types.update_project_entity_matches_body import UpdateProjectEntityMatchesBody +from .types.update_project_entity_matches_response import UpdateProjectEntityMatchesResponse from .types.resolution_attributes import ResolutionAttributes from .types.project_entity_id_response import ProjectEntityIdResponse from .types.save_project_entity_body import SaveProjectEntityBody @@ -439,6 +441,258 @@ def get_project_entity( raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) + def add_project_entity_matches( + self, + project_id: str, + project_entity_id: str, + *, + request: UpdateProjectEntityMatchesBody, + request_options: typing.Optional[RequestOptions] = None, + ) -> UpdateProjectEntityMatchesResponse: + """ + Adds matches to a project entity. + + Parameters + ---------- + project_id : str + + project_entity_id : str + + request : UpdateProjectEntityMatchesBody + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + UpdateProjectEntityMatchesResponse + + Examples + -------- + from sayari import Sayari + from sayari.project_entity import UpdateProjectEntityMatchesBody + + client = Sayari( + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + client.project_entity.add_project_entity_matches( + project_id="project_id", + project_entity_id="project_entity_id", + request=UpdateProjectEntityMatchesBody( + entity_ids=["entity_ids", "entity_ids"], + ), + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/projects/{jsonable_encoder(project_id)}/entities/{jsonable_encoder(project_entity_id)}/matches", + method="POST", + json=convert_and_respect_annotation_metadata( + object_=request, annotation=UpdateProjectEntityMatchesBody, direction="write" + ), + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + UpdateProjectEntityMatchesResponse, + parse_obj_as( + type_=UpdateProjectEntityMatchesResponse, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequest( + typing.cast( + BadRequestResponse, + parse_obj_as( + type_=BadRequestResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise Unauthorized( + typing.cast( + UnauthorizedResponse, + parse_obj_as( + type_=UnauthorizedResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFound( + typing.cast( + NotFoundResponse, + parse_obj_as( + type_=NotFoundResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 405: + raise MethodNotAllowed( + typing.cast( + MethodNotAllowedResponse, + parse_obj_as( + type_=MethodNotAllowedResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise RateLimitExceeded( + typing.cast( + RateLimitResponse, + parse_obj_as( + type_=RateLimitResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + InternalServerErrorResponse, + parse_obj_as( + type_=InternalServerErrorResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def replace_project_entity_matches( + self, + project_id: str, + project_entity_id: str, + *, + request: UpdateProjectEntityMatchesBody, + request_options: typing.Optional[RequestOptions] = None, + ) -> UpdateProjectEntityMatchesResponse: + """ + Replace matches in a project entity. + + Parameters + ---------- + project_id : str + + project_entity_id : str + + request : UpdateProjectEntityMatchesBody + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + UpdateProjectEntityMatchesResponse + + Examples + -------- + from sayari import Sayari + from sayari.project_entity import UpdateProjectEntityMatchesBody + + client = Sayari( + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + client.project_entity.replace_project_entity_matches( + project_id="project_id", + project_entity_id="project_entity_id", + request=UpdateProjectEntityMatchesBody( + entity_ids=["entity_ids", "entity_ids"], + ), + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/projects/{jsonable_encoder(project_id)}/entities/{jsonable_encoder(project_entity_id)}/matches", + method="PATCH", + json=convert_and_respect_annotation_metadata( + object_=request, annotation=UpdateProjectEntityMatchesBody, direction="write" + ), + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + UpdateProjectEntityMatchesResponse, + parse_obj_as( + type_=UpdateProjectEntityMatchesResponse, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequest( + typing.cast( + BadRequestResponse, + parse_obj_as( + type_=BadRequestResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise Unauthorized( + typing.cast( + UnauthorizedResponse, + parse_obj_as( + type_=UnauthorizedResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFound( + typing.cast( + NotFoundResponse, + parse_obj_as( + type_=NotFoundResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 405: + raise MethodNotAllowed( + typing.cast( + MethodNotAllowedResponse, + parse_obj_as( + type_=MethodNotAllowedResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise RateLimitExceeded( + typing.cast( + RateLimitResponse, + parse_obj_as( + type_=RateLimitResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + InternalServerErrorResponse, + parse_obj_as( + type_=InternalServerErrorResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + def delete_project_entity( self, project_id: str, project_entity_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> None: @@ -2391,6 +2645,274 @@ async def main() -> None: raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) + async def add_project_entity_matches( + self, + project_id: str, + project_entity_id: str, + *, + request: UpdateProjectEntityMatchesBody, + request_options: typing.Optional[RequestOptions] = None, + ) -> UpdateProjectEntityMatchesResponse: + """ + Adds matches to a project entity. + + Parameters + ---------- + project_id : str + + project_entity_id : str + + request : UpdateProjectEntityMatchesBody + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + UpdateProjectEntityMatchesResponse + + Examples + -------- + import asyncio + + from sayari import AsyncSayari + from sayari.project_entity import UpdateProjectEntityMatchesBody + + client = AsyncSayari( + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + await client.project_entity.add_project_entity_matches( + project_id="project_id", + project_entity_id="project_entity_id", + request=UpdateProjectEntityMatchesBody( + entity_ids=["entity_ids", "entity_ids"], + ), + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/projects/{jsonable_encoder(project_id)}/entities/{jsonable_encoder(project_entity_id)}/matches", + method="POST", + json=convert_and_respect_annotation_metadata( + object_=request, annotation=UpdateProjectEntityMatchesBody, direction="write" + ), + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + UpdateProjectEntityMatchesResponse, + parse_obj_as( + type_=UpdateProjectEntityMatchesResponse, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequest( + typing.cast( + BadRequestResponse, + parse_obj_as( + type_=BadRequestResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise Unauthorized( + typing.cast( + UnauthorizedResponse, + parse_obj_as( + type_=UnauthorizedResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFound( + typing.cast( + NotFoundResponse, + parse_obj_as( + type_=NotFoundResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 405: + raise MethodNotAllowed( + typing.cast( + MethodNotAllowedResponse, + parse_obj_as( + type_=MethodNotAllowedResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise RateLimitExceeded( + typing.cast( + RateLimitResponse, + parse_obj_as( + type_=RateLimitResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + InternalServerErrorResponse, + parse_obj_as( + type_=InternalServerErrorResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def replace_project_entity_matches( + self, + project_id: str, + project_entity_id: str, + *, + request: UpdateProjectEntityMatchesBody, + request_options: typing.Optional[RequestOptions] = None, + ) -> UpdateProjectEntityMatchesResponse: + """ + Replace matches in a project entity. + + Parameters + ---------- + project_id : str + + project_entity_id : str + + request : UpdateProjectEntityMatchesBody + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + UpdateProjectEntityMatchesResponse + + Examples + -------- + import asyncio + + from sayari import AsyncSayari + from sayari.project_entity import UpdateProjectEntityMatchesBody + + client = AsyncSayari( + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + await client.project_entity.replace_project_entity_matches( + project_id="project_id", + project_entity_id="project_entity_id", + request=UpdateProjectEntityMatchesBody( + entity_ids=["entity_ids", "entity_ids"], + ), + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/projects/{jsonable_encoder(project_id)}/entities/{jsonable_encoder(project_entity_id)}/matches", + method="PATCH", + json=convert_and_respect_annotation_metadata( + object_=request, annotation=UpdateProjectEntityMatchesBody, direction="write" + ), + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + UpdateProjectEntityMatchesResponse, + parse_obj_as( + type_=UpdateProjectEntityMatchesResponse, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequest( + typing.cast( + BadRequestResponse, + parse_obj_as( + type_=BadRequestResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise Unauthorized( + typing.cast( + UnauthorizedResponse, + parse_obj_as( + type_=UnauthorizedResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFound( + typing.cast( + NotFoundResponse, + parse_obj_as( + type_=NotFoundResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 405: + raise MethodNotAllowed( + typing.cast( + MethodNotAllowedResponse, + parse_obj_as( + type_=MethodNotAllowedResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise RateLimitExceeded( + typing.cast( + RateLimitResponse, + parse_obj_as( + type_=RateLimitResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + InternalServerErrorResponse, + parse_obj_as( + type_=InternalServerErrorResponse, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + async def delete_project_entity( self, project_id: str, project_entity_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> None: diff --git a/src/sayari/project_entity/types/__init__.py b/src/sayari/project_entity/types/__init__.py index 95bc28ae..8e1bf22c 100644 --- a/src/sayari/project_entity/types/__init__.py +++ b/src/sayari/project_entity/types/__init__.py @@ -62,6 +62,8 @@ from .trade_counts import TradeCounts from .translation import Translation from .update_entity_tags_response import UpdateEntityTagsResponse +from .update_project_entity_matches_body import UpdateProjectEntityMatchesBody +from .update_project_entity_matches_response import UpdateProjectEntityMatchesResponse from .update_project_entity_tags_body import UpdateProjectEntityTagsBody from .upstream_count import UpstreamCount from .upstream_info import UpstreamInfo @@ -129,6 +131,8 @@ "TradeCounts", "Translation", "UpdateEntityTagsResponse", + "UpdateProjectEntityMatchesBody", + "UpdateProjectEntityMatchesResponse", "UpdateProjectEntityTagsBody", "UpstreamCount", "UpstreamInfo", diff --git a/src/sayari/project_entity/types/project_entities_response.py b/src/sayari/project_entity/types/project_entities_response.py index 942590db..300c2a31 100644 --- a/src/sayari/project_entity/types/project_entities_response.py +++ b/src/sayari/project_entity/types/project_entities_response.py @@ -27,6 +27,7 @@ class ProjectEntitiesResponse(UniversalBaseModel): TradeCounts, UpstreamInfo, ) + from sayari.shared_types import CaseInfo ProjectEntitiesResponse( limit=20, @@ -138,7 +139,11 @@ class ProjectEntitiesResponse(UniversalBaseModel): products=[], ), tags=[], - case="not_assigned", + case=CaseInfo( + id="YZB88Y", + status="not_assigned", + created_at="2025-10-02", + ), matches=[ ProjectEntityMatchResponse( match_id="52z4Wa:dy-rh2g0QtzUN_jC_e9S_A", diff --git a/src/sayari/project_entity/types/project_entity_response.py b/src/sayari/project_entity/types/project_entity_response.py index dbd976cf..e96b3c93 100644 --- a/src/sayari/project_entity/types/project_entity_response.py +++ b/src/sayari/project_entity/types/project_entity_response.py @@ -8,7 +8,7 @@ from .project_risk_factor import ProjectRiskFactor from .upstream_info import UpstreamInfo from .tag_response import TagResponse -from ...shared_types.types.case_status import CaseStatus +from ...shared_types.types.case_info import CaseInfo from .project_entity_match_response import ProjectEntityMatchResponse from ...core.pydantic_utilities import IS_PYDANTIC_V2 import pydantic @@ -27,7 +27,7 @@ class ProjectEntityResponse(UniversalBaseModel): risk_factors: typing.List[ProjectRiskFactor] upstream: UpstreamInfo tags: typing.List[TagResponse] - case: typing.Optional[CaseStatus] = None + case: typing.Optional[CaseInfo] = None matches: typing.List[ProjectEntityMatchResponse] updated_at: typing.Optional[str] = None diff --git a/src/sayari/project_entity/types/single_project_entity_response.py b/src/sayari/project_entity/types/single_project_entity_response.py index 1f9373e5..3f9ee0b8 100644 --- a/src/sayari/project_entity/types/single_project_entity_response.py +++ b/src/sayari/project_entity/types/single_project_entity_response.py @@ -25,6 +25,7 @@ class SingleProjectEntityResponse(UniversalBaseModel): TradeCounts, UpstreamInfo, ) + from sayari.shared_types import CaseInfo SingleProjectEntityResponse( data=ProjectEntityResponse( @@ -134,7 +135,11 @@ class SingleProjectEntityResponse(UniversalBaseModel): products=[], ), tags=[], - case="not_assigned", + case=CaseInfo( + id="YVB88Y", + status="not_assigned", + created_at="2025-10-02", + ), matches=[ ProjectEntityMatchResponse( match_id="52z4Wa:dy-rh2g0QtzUN_jC_e9S_A", diff --git a/src/sayari/project_entity/types/update_project_entity_matches_body.py b/src/sayari/project_entity/types/update_project_entity_matches_body.py new file mode 100644 index 00000000..41a23d04 --- /dev/null +++ b/src/sayari/project_entity/types/update_project_entity_matches_body.py @@ -0,0 +1,23 @@ +# This file was auto-generated by Fern from our API Definition. + +from ...core.pydantic_utilities import UniversalBaseModel +import typing +import pydantic +from ...core.pydantic_utilities import IS_PYDANTIC_V2 + + +class UpdateProjectEntityMatchesBody(UniversalBaseModel): + entity_ids: typing.List[str] + limit: typing.Optional[int] = pydantic.Field(default=None) + """ + Limit total matches to update. Defaults to 10. Max 50. + """ + + 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/sayari/project_entity/types/update_project_entity_matches_response.py b/src/sayari/project_entity/types/update_project_entity_matches_response.py new file mode 100644 index 00000000..5c1c308e --- /dev/null +++ b/src/sayari/project_entity/types/update_project_entity_matches_response.py @@ -0,0 +1,22 @@ +# This file was auto-generated by Fern from our API Definition. + +from ...core.pydantic_utilities import UniversalBaseModel +import typing +import pydantic +from ...core.pydantic_utilities import IS_PYDANTIC_V2 + + +class UpdateProjectEntityMatchesResponse(UniversalBaseModel): + data: typing.List[str] = pydantic.Field() + """ + Updated entity ids + """ + + 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/sayari/shared_types/__init__.py b/src/sayari/shared_types/__init__.py index 1a2063e3..955bbad2 100644 --- a/src/sayari/shared_types/__init__.py +++ b/src/sayari/shared_types/__init__.py @@ -1,6 +1,7 @@ # This file was auto-generated by Fern from our API Definition. from .types import ( + CaseInfo, CaseStatus, ClientName, CompanyType, @@ -42,6 +43,7 @@ ) __all__ = [ + "CaseInfo", "CaseStatus", "ClientName", "CompanyType", diff --git a/src/sayari/shared_types/types/__init__.py b/src/sayari/shared_types/types/__init__.py index f93f2ae6..9ae0f709 100644 --- a/src/sayari/shared_types/types/__init__.py +++ b/src/sayari/shared_types/types/__init__.py @@ -1,5 +1,6 @@ # This file was auto-generated by Fern from our API Definition. +from .case_info import CaseInfo from .case_status import CaseStatus from .client_name import ClientName from .company_type import CompanyType @@ -40,6 +41,7 @@ from .status import Status __all__ = [ + "CaseInfo", "CaseStatus", "ClientName", "CompanyType", diff --git a/src/sayari/shared_types/types/case_info.py b/src/sayari/shared_types/types/case_info.py new file mode 100644 index 00000000..fef5a6dc --- /dev/null +++ b/src/sayari/shared_types/types/case_info.py @@ -0,0 +1,23 @@ +# This file was auto-generated by Fern from our API Definition. + +from ...core.pydantic_utilities import UniversalBaseModel +from .case_status import CaseStatus +import typing +from ...core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class CaseInfo(UniversalBaseModel): + id: str + status: CaseStatus + created_at: str + comment: 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/sayari/shared_types/types/possibly_same_as.py b/src/sayari/shared_types/types/possibly_same_as.py index 501c0ed3..e1b975d3 100644 --- a/src/sayari/shared_types/types/possibly_same_as.py +++ b/src/sayari/shared_types/types/possibly_same_as.py @@ -9,7 +9,7 @@ class PossiblySameAs(PaginatedResponse): """ - List of entities that are Possibly the Same As (PSA) the entity. + This property is deprecated. List of entities that are Possibly the Same As (PSA) the entity. """ offset: typing.Optional[int] = None