stepxmlclient 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. stepxmlclient/__init__.py +22 -0
  2. stepxmlclient/client.py +373 -0
  3. stepxmlclient/creator.py +317 -0
  4. stepxmlclient/model/__init__.py +418 -0
  5. stepxmlclient/model/asset.py +250 -0
  6. stepxmlclient/model/attribute.py +288 -0
  7. stepxmlclient/model/business.py +233 -0
  8. stepxmlclient/model/classification.py +409 -0
  9. stepxmlclient/model/complex_elements.py +260 -0
  10. stepxmlclient/model/deletion.py +87 -0
  11. stepxmlclient/model/entity.py +368 -0
  12. stepxmlclient/model/metadata.py +199 -0
  13. stepxmlclient/model/organization.py +167 -0
  14. stepxmlclient/model/product.py +519 -0
  15. stepxmlclient/model/relations.py +105 -0
  16. stepxmlclient/model/replacement.py +417 -0
  17. stepxmlclient/parser.py +2805 -0
  18. stepxmlclient/rest_client/__init__.py +16 -0
  19. stepxmlclient/rest_client/base.py +388 -0
  20. stepxmlclient/rest_client/client.py +127 -0
  21. stepxmlclient/rest_client/exceptions.py +97 -0
  22. stepxmlclient/rest_client/models/__init__.py +175 -0
  23. stepxmlclient/rest_client/models/asset.py +253 -0
  24. stepxmlclient/rest_client/models/attribute.py +112 -0
  25. stepxmlclient/rest_client/models/background_process.py +23 -0
  26. stepxmlclient/rest_client/models/batch.py +41 -0
  27. stepxmlclient/rest_client/models/classification.py +57 -0
  28. stepxmlclient/rest_client/models/collection.py +26 -0
  29. stepxmlclient/rest_client/models/common.py +192 -0
  30. stepxmlclient/rest_client/models/context.py +16 -0
  31. stepxmlclient/rest_client/models/data_type_group.py +15 -0
  32. stepxmlclient/rest_client/models/entity.py +63 -0
  33. stepxmlclient/rest_client/models/event_processor.py +15 -0
  34. stepxmlclient/rest_client/models/import_export.py +43 -0
  35. stepxmlclient/rest_client/models/integration_endpoint.py +16 -0
  36. stepxmlclient/rest_client/models/product.py +200 -0
  37. stepxmlclient/rest_client/models/relations.py +280 -0
  38. stepxmlclient/rest_client/models/system_information.py +11 -0
  39. stepxmlclient/rest_client/models/user.py +28 -0
  40. stepxmlclient/rest_client/models/workflow.py +30 -0
  41. stepxmlclient/rest_client/operations/__init__.py +54 -0
  42. stepxmlclient/rest_client/operations/assets.py +652 -0
  43. stepxmlclient/rest_client/operations/attributes.py +252 -0
  44. stepxmlclient/rest_client/operations/background_processes.py +84 -0
  45. stepxmlclient/rest_client/operations/batch.py +28 -0
  46. stepxmlclient/rest_client/operations/classifications.py +248 -0
  47. stepxmlclient/rest_client/operations/collection_groups.py +46 -0
  48. stepxmlclient/rest_client/operations/collections.py +67 -0
  49. stepxmlclient/rest_client/operations/contexts.py +88 -0
  50. stepxmlclient/rest_client/operations/data_type_groups.py +68 -0
  51. stepxmlclient/rest_client/operations/entities.py +295 -0
  52. stepxmlclient/rest_client/operations/event_processors.py +109 -0
  53. stepxmlclient/rest_client/operations/exports.py +153 -0
  54. stepxmlclient/rest_client/operations/gateway.py +53 -0
  55. stepxmlclient/rest_client/operations/inbound.py +472 -0
  56. stepxmlclient/rest_client/operations/outbound.py +64 -0
  57. stepxmlclient/rest_client/operations/products.py +489 -0
  58. stepxmlclient/rest_client/operations/relations.py +349 -0
  59. stepxmlclient/rest_client/operations/reports.py +27 -0
  60. stepxmlclient/rest_client/operations/system_information.py +28 -0
  61. stepxmlclient/rest_client/operations/user_groups.py +79 -0
  62. stepxmlclient/rest_client/operations/users.py +119 -0
  63. stepxmlclient/rest_client/operations/workflow_tasks.py +61 -0
  64. stepxmlclient/rest_client/operations/workflows.py +50 -0
  65. stepxmlclient/upload.py +293 -0
  66. stepxmlclient-1.0.0.dist-info/METADATA +666 -0
  67. stepxmlclient-1.0.0.dist-info/RECORD +70 -0
  68. stepxmlclient-1.0.0.dist-info/WHEEL +5 -0
  69. stepxmlclient-1.0.0.dist-info/licenses/LICENSE +21 -0
  70. stepxmlclient-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,153 @@
1
+ """Export and Import operations for STEP REST API v2."""
2
+
3
+ import logging
4
+ from typing import Any, Optional
5
+
6
+ from ..base import BaseOperation, handle_rest_errors
7
+ from ..exceptions import NotFoundError, ValidationError
8
+ from ..models.import_export import (
9
+ BackgroundProcessResponse,
10
+ ExportJobCreateRequest,
11
+ )
12
+
13
+
14
+ class ExportOperations(BaseOperation):
15
+ """Operations for STEP data exports and imports."""
16
+
17
+ def __init__(self, client, logger: Optional[logging.Logger] = None,
18
+ context: str | None = None, workspace: str | None = None):
19
+ """Initialize export operations.
20
+
21
+ Args:
22
+ client: The REST API client
23
+ logger: Optional logger instance
24
+ context: STEP context ID for all API calls
25
+ workspace: STEP workspace ID (defaults to "Main" server-side)
26
+ """
27
+ super().__init__(client, operation_name="ExportOperations", logger=logger,
28
+ context=context, workspace=workspace)
29
+
30
+ @handle_rest_errors
31
+ def create_export_job(self, export_configuration_id: str,
32
+ data: Optional[ExportJobCreateRequest] = None,
33
+ use_request_context_workspace: Optional[bool] = None) -> BackgroundProcessResponse:
34
+ """Trigger an export using a pre-configured export configuration (POST /export/{exportConfigurationId}).
35
+
36
+ Args:
37
+ export_configuration_id: The ID of the export configuration to use (required)
38
+ data: Optional request body with additional export parameters
39
+ use_request_context_workspace: If True, use the workspace from the request context
40
+
41
+ Returns:
42
+ ExportJobResponse with job details
43
+
44
+ Raises:
45
+ ValidationError: If export_configuration_id is missing or data is invalid
46
+ RestApiError: For API errors
47
+ """
48
+ self._validate_required_params(
49
+ {"export_configuration_id": export_configuration_id},
50
+ ["export_configuration_id"]
51
+ )
52
+
53
+ if data is not None:
54
+ if hasattr(data, 'model_dump'):
55
+ create_data = data.model_dump(exclude_none=True)
56
+ else:
57
+ create_data = dict(data) if not isinstance(data, dict) else data
58
+ else:
59
+ create_data = None
60
+
61
+ query_params: dict = self._build_context_params()
62
+ if use_request_context_workspace is not None:
63
+ query_params["useRequestContextWorkspace"] = use_request_context_workspace
64
+
65
+ self._log_operation("startExport", {"exportConfigurationId": export_configuration_id})
66
+
67
+ try:
68
+ if create_data:
69
+ response = self.client.startExport(exportConfigurationId=export_configuration_id, json=create_data, **query_params)
70
+ else:
71
+ response = self.client.startExport(exportConfigurationId=export_configuration_id, **query_params)
72
+ except Exception as e:
73
+ if "404" in str(e):
74
+ raise NotFoundError(export_configuration_id, "ExportConfiguration")
75
+ if "400" in str(e):
76
+ raise ValidationError(f"Export failed: {str(e)}")
77
+ raise
78
+
79
+ self._check_for_api_error(response, export_configuration_id, "ExportConfiguration")
80
+ if isinstance(response, dict):
81
+ return BackgroundProcessResponse(**response)
82
+ return response
83
+
84
+ @handle_rest_errors
85
+ def create_import_job(self, import_configuration_id: str,
86
+ data: Optional[object] = None,
87
+ process_description: str | None = None) -> BackgroundProcessResponse:
88
+ """Trigger an import using a pre-configured import configuration (POST /import/{importConfigurationId}).
89
+
90
+ Args:
91
+ import_configuration_id: The ID of the import configuration to use (required)
92
+ data: Optional request body with import payload
93
+ process_description: Optional human-readable description for the import process
94
+
95
+ Returns:
96
+ BackgroundProcessResponse with job/process details
97
+
98
+ Raises:
99
+ ValidationError: If import_configuration_id is missing or data is invalid
100
+ RestApiError: For API errors
101
+ """
102
+ self._validate_required_params(
103
+ {"import_configuration_id": import_configuration_id},
104
+ ["import_configuration_id"]
105
+ )
106
+
107
+ query_params = self._build_context_params()
108
+ if process_description:
109
+ query_params["processDescription"] = process_description
110
+
111
+ self._log_operation("startImport", {"importConfigurationId": import_configuration_id})
112
+
113
+ try:
114
+ if data is not None:
115
+ # Binary data: convert to bytes if needed
116
+ if isinstance(data, str):
117
+ binary_data = data.encode('utf-8')
118
+ elif isinstance(data, bytes):
119
+ binary_data = data
120
+ else:
121
+ # For Pydantic models or dicts, convert to JSON bytes
122
+ import json
123
+
124
+ from pydantic import BaseModel
125
+ if isinstance(data, BaseModel):
126
+ binary_data = json.dumps(data.model_dump(exclude_none=True)).encode('utf-8')
127
+ else:
128
+ binary_data = json.dumps(data).encode('utf-8')
129
+
130
+ response = self.client.startImport(
131
+ importConfigurationId=import_configuration_id,
132
+ data=binary_data,
133
+ **query_params
134
+ )
135
+ response_dict: dict[str, Any] = response if isinstance(response, dict) else {"success": True}
136
+ else:
137
+ response = self.client.startImport(
138
+ importConfigurationId=import_configuration_id,
139
+ **query_params
140
+ )
141
+ response_dict: dict[str, Any] = response if isinstance(response, dict) else {"success": True}
142
+ except Exception as e:
143
+ if "404" in str(e):
144
+ raise NotFoundError(import_configuration_id, "ImportConfiguration")
145
+ if "400" in str(e):
146
+ raise ValidationError(f"Import failed: {e!s}")
147
+ raise
148
+
149
+ self._check_for_api_error(response_dict, import_configuration_id, "ImportConfiguration")
150
+ if isinstance(response_dict, dict):
151
+ return BackgroundProcessResponse(**response_dict)
152
+ return response_dict
153
+
@@ -0,0 +1,53 @@
1
+ """Gateway integration endpoint operations for STEP REST API v2."""
2
+ from typing import Any
3
+
4
+ from ..base import BaseOperation, handle_rest_errors
5
+ from ..exceptions import NotFoundError
6
+ from ..models.integration_endpoint import IntegrationEndpointResponse
7
+
8
+
9
+ class GatewayOperations(BaseOperation):
10
+ def __init__(self, client, logger=None, context=None, workspace=None):
11
+ super().__init__(client, operation_name="GatewayOperations", logger=logger, context=context, workspace=workspace)
12
+
13
+ @handle_rest_errors
14
+ def get_gateway_endpoints(self) -> list[dict[str, Any]]:
15
+ self._log_operation("getGatewayIntegrationEndpoints", {})
16
+ r = self.client.getGatewayIntegrationEndpoints(**self._build_context_params())
17
+ return r if isinstance(r, list) else []
18
+
19
+ @handle_rest_errors
20
+ def get_gateway_endpoint(self, ep_id: str) -> IntegrationEndpointResponse:
21
+ self._validate_required_params({"ep_id": ep_id}, ["ep_id"])
22
+ self._log_operation("getGatewayIntegrationEndpoint", {"id": ep_id})
23
+ try:
24
+ r = self.client.getGatewayIntegrationEndpoint(id=ep_id, **self._build_context_params())
25
+ except Exception as e:
26
+ if "404" in str(e): raise NotFoundError(ep_id, "GatewayIntegrationEndpoint")
27
+ raise
28
+ return IntegrationEndpointResponse(**r) if isinstance(r, dict) else r
29
+
30
+ @handle_rest_errors
31
+ def get_gateway_endpoint_status(self, ep_id: str) -> IntegrationEndpointResponse:
32
+ self._validate_required_params({"ep_id": ep_id}, ["ep_id"])
33
+ self._log_operation("getGatewayIntegrationEndpointStatus", {"id": ep_id})
34
+ try:
35
+ r = self.client.getGatewayIntegrationEndpointStatus(id=ep_id, **self._build_context_params())
36
+ except Exception as e:
37
+ if "404" in str(e): raise NotFoundError(ep_id, "GatewayIntegrationEndpoint")
38
+ raise
39
+ return IntegrationEndpointResponse(**r) if isinstance(r, dict) else r
40
+
41
+ @handle_rest_errors
42
+ def enable_gateway_endpoint(self, ep_id: str) -> IntegrationEndpointResponse:
43
+ self._validate_required_params({"ep_id": ep_id}, ["ep_id"])
44
+ self._log_operation("enableGatewayIntegrationEndpoint", {"id": ep_id})
45
+ r = self.client.enableGatewayIntegrationEndpoint(id=ep_id, **self._build_context_params())
46
+ return IntegrationEndpointResponse(**r) if isinstance(r, dict) else r
47
+
48
+ @handle_rest_errors
49
+ def disable_gateway_endpoint(self, ep_id: str) -> IntegrationEndpointResponse:
50
+ self._validate_required_params({"ep_id": ep_id}, ["ep_id"])
51
+ self._log_operation("disableGatewayIntegrationEndpoint", {"id": ep_id})
52
+ r = self.client.disableGatewayIntegrationEndpoint(id=ep_id, **self._build_context_params())
53
+ return IntegrationEndpointResponse(**r) if isinstance(r, dict) else r
@@ -0,0 +1,472 @@
1
+ """Inbound Integration Endpoint operations for STEP REST API v2.
2
+
3
+ Provides high-level operations for uploading STEP-XML to Inbound Integration Endpoints
4
+ and managing their status, including enabling/disabling endpoints and retrieving execution reports.
5
+ """
6
+
7
+ import logging
8
+ from typing import Any, Optional, Union
9
+
10
+ from ..base import BaseOperation, handle_rest_errors
11
+ from ..exceptions import NotFoundError, RestApiError, ValidationError
12
+
13
+
14
+ class InboundOperations(BaseOperation):
15
+ """Operations for STEP Inbound Integration Endpoints (IIEP).
16
+
17
+ Handles uploading STEP-XML documents to configured inbound endpoints
18
+ and managing endpoint status and execution reports.
19
+
20
+ Example:
21
+ ```python
22
+ from stepxmlclient.rest_client.client import StepRestClient
23
+ from stepxmlclient.creator import Creator
24
+
25
+ # Create and setup client
26
+ client = StepRestClient(
27
+ location_base="https://your-step.com/restapiv2",
28
+ authorisation=auth,
29
+ context="Context1"
30
+ )
31
+
32
+ # Generate STEP-XML
33
+ creator = Creator(context_id="Context1")
34
+ # ... add products, assets, etc ...
35
+ creator.build()
36
+ xml_bytes = creator.to_bytes()
37
+
38
+ # Send to inbound endpoint
39
+ result = client.inbound.upload_and_invoke(
40
+ endpoint_id="my_inbound_endpoint",
41
+ xml_data=xml_bytes,
42
+ file_name="import_data.xml"
43
+ )
44
+
45
+ print(f"Uploaded {result.get('processId')} to endpoint")
46
+ ```
47
+ """
48
+
49
+ def __init__(self, client, logger: Optional[logging.Logger] = None,
50
+ context: str | None = None, workspace: str | None = None):
51
+ """Initialize inbound operations.
52
+
53
+ Args:
54
+ client: The REST API client
55
+ logger: Optional logger instance
56
+ context: STEP context ID for all API calls (required)
57
+ workspace: STEP workspace ID (defaults to "Main" server-side)
58
+ """
59
+ super().__init__(client, operation_name="InboundOperations", logger=logger,
60
+ context=context, workspace=workspace)
61
+
62
+ @handle_rest_errors
63
+ def upload_and_invoke(self, endpoint_id: str, xml_data: Union[bytes, str],
64
+ file_name: str | None = None) -> dict[str, Any]:
65
+ """Upload STEP-XML to an inbound endpoint and trigger processing.
66
+
67
+ Posts STEP-XML content to a configured Inbound Integration Endpoint
68
+ with a REST receiver plugin. The endpoint is immediately invoked
69
+ to process the uploaded data.
70
+
71
+ Args:
72
+ endpoint_id: ID of the inbound integration endpoint (required)
73
+ xml_data: STEP-XML content as bytes or string
74
+ file_name: Optional filename hint for the upload (e.g., "import_data.xml")
75
+
76
+ Returns:
77
+ Dictionary with response details (typically includes processId or similar)
78
+
79
+ Raises:
80
+ ValidationError: If endpoint_id is missing or endpoint not enabled
81
+ NotFoundError: If endpoint cannot be found
82
+ RestApiError: For other API errors
83
+
84
+ Note:
85
+ - Endpoint must have status "enabled" to invoke
86
+ - Endpoint must have a REST-enabled receiver plugin configured
87
+ - The endpoint will begin processing immediately
88
+ """
89
+ self._validate_required_params(
90
+ {"endpoint_id": endpoint_id, "xml_data": xml_data},
91
+ ["endpoint_id", "xml_data"]
92
+ )
93
+
94
+ # Convert string to bytes if needed
95
+ if isinstance(xml_data, str):
96
+ xml_data = xml_data.encode('utf-8')
97
+
98
+ # Prepare query parameters (context and workspace, plus optional fileName)
99
+ params: dict[str, Any] = {}
100
+ if file_name:
101
+ params["fileName"] = file_name
102
+ params.update(self._build_context_params())
103
+
104
+ self._log_operation("uploadFileToAndInvokeInboundRestEndpoint", {
105
+ "endpointId": endpoint_id,
106
+ "fileSize": len(xml_data),
107
+ "fileName": file_name or "(not specified)"
108
+ })
109
+
110
+ requestor = getattr(self.client, "requestor", None)
111
+ server_url = None
112
+ server = getattr(self.client, "server", None)
113
+ if server is not None:
114
+ server_url = getattr(server, "url", None)
115
+ if not server_url:
116
+ server_url = getattr(self.client, "_server", None)
117
+ if server_url is not None:
118
+ server_url = getattr(server_url, "url", None)
119
+
120
+ try:
121
+ if requestor is not None and hasattr(requestor, "post") and server_url:
122
+ url = f"{server_url.rstrip('/')}/inbound-integration-endpoints/{endpoint_id}/upload-and-invoke"
123
+ response = requestor.post(url, data=xml_data, params=params, timeout=120)
124
+ try:
125
+ response.raise_for_status()
126
+ except Exception as exc:
127
+ error_str = str(exc)
128
+ if "404" in error_str:
129
+ raise NotFoundError(endpoint_id, "InboundIntegrationEndpoint")
130
+ elif "400" in error_str:
131
+ if "not enabled" in error_str.lower() or "disabled" in error_str.lower():
132
+ raise ValidationError(
133
+ f"Inbound endpoint '{endpoint_id}' is not enabled. "
134
+ f"Enable it first using enable_endpoint()."
135
+ )
136
+ elif "REST receiver" in error_str:
137
+ raise ValidationError(
138
+ f"Inbound endpoint '{endpoint_id}' does not have a REST-enabled receiver plugin. "
139
+ f"Configure a REST receiver in the endpoint settings."
140
+ )
141
+ raise ValidationError(f"Upload failed: {error_str}")
142
+ elif "503" in error_str:
143
+ raise RestApiError(503, "Endpoint temporarily unavailable", details=error_str)
144
+ raise
145
+
146
+ if isinstance(response, dict):
147
+ return response
148
+ if hasattr(response, "json"):
149
+ try:
150
+ payload = response.json()
151
+ except Exception:
152
+ payload = None
153
+ if isinstance(payload, dict):
154
+ return payload
155
+ return {"success": True, "endpoint": endpoint_id}
156
+
157
+ # Fallback to generated OpenAPI operation when a requestor is not available.
158
+ response = self.client.uploadFileToAndInvokeInboundRestEndpoint(
159
+ id=endpoint_id,
160
+ data=xml_data,
161
+ **params
162
+ )
163
+
164
+ if isinstance(response, dict):
165
+ return response
166
+ if hasattr(response, "json"):
167
+ try:
168
+ payload = response.json()
169
+ except Exception: # noqa: BLE001
170
+ payload = None
171
+ if isinstance(payload, dict):
172
+ return payload
173
+ return {"success": True, "endpoint": endpoint_id}
174
+
175
+ except Exception as e:
176
+ error_str = str(e)
177
+ if "404" in error_str:
178
+ raise NotFoundError(endpoint_id, "InboundIntegrationEndpoint")
179
+ elif "400" in error_str:
180
+ if "not enabled" in error_str.lower() or "disabled" in error_str.lower():
181
+ raise ValidationError(
182
+ f"Inbound endpoint '{endpoint_id}' is not enabled. "
183
+ f"Enable it first using enable_endpoint()."
184
+ )
185
+ elif "REST receiver" in error_str:
186
+ raise ValidationError(
187
+ f"Inbound endpoint '{endpoint_id}' does not have a REST-enabled receiver plugin. "
188
+ f"Configure a REST receiver in the endpoint settings."
189
+ )
190
+ raise ValidationError(f"Upload failed: {error_str}")
191
+ elif "503" in error_str:
192
+ raise RestApiError(503, "Endpoint temporarily unavailable", details=error_str)
193
+ raise
194
+
195
+
196
+ @handle_rest_errors
197
+ def list_endpoints(self) -> list[dict[str, Any]]:
198
+ """Get all accessible inbound integration endpoints.
199
+
200
+ Returns:
201
+ List of inbound endpoint representations with ID, name, and status info
202
+
203
+ Raises:
204
+ RestApiError: For API errors
205
+ """
206
+ params = self._build_context_params()
207
+
208
+ self._log_operation("getInboundIntegrationEndpoints", {})
209
+
210
+ try:
211
+ response = self.client.getInboundIntegrationEndpoints(**params)
212
+ except Exception as e:
213
+ raise RestApiError(0, f"Failed to list inbound endpoints: {str(e)}", details=str(e))
214
+
215
+ return self._coerce_list_payload(response)
216
+
217
+ @handle_rest_errors
218
+ def get_status(self, endpoint_id: str) -> dict[str, Any]:
219
+ """Get the current status of an inbound endpoint.
220
+
221
+ Args:
222
+ endpoint_id: ID of the inbound integration endpoint
223
+
224
+ Returns:
225
+ Dictionary with status information (status, enabled state, etc.)
226
+
227
+ Raises:
228
+ ValidationError: If endpoint_id is missing
229
+ NotFoundError: If endpoint cannot be found
230
+ RestApiError: For API errors
231
+ """
232
+ self._validate_required_params(
233
+ {"endpoint_id": endpoint_id},
234
+ ["endpoint_id"]
235
+ )
236
+
237
+ self._log_operation("getInboundIntegrationEndpointStatus", {
238
+ "endpointId": endpoint_id
239
+ })
240
+
241
+ try:
242
+ response = self.client.getInboundIntegrationEndpointStatus(
243
+ id=endpoint_id,
244
+ **self._build_context_params()
245
+ )
246
+ except Exception as e:
247
+ if "404" in str(e):
248
+ raise NotFoundError(endpoint_id, "InboundIntegrationEndpoint")
249
+ raise
250
+
251
+ self._check_for_api_error(response, endpoint_id, "InboundIntegrationEndpoint")
252
+
253
+ if isinstance(response, dict):
254
+ return response
255
+ return {"endpoint": endpoint_id}
256
+
257
+ @handle_rest_errors
258
+ def enable_endpoint(self, endpoint_id: str) -> dict[str, Any]:
259
+ """Enable an inbound integration endpoint.
260
+
261
+ Enables the endpoint so it can receive and process uploads.
262
+ If endpoint has status "failed", this will resume it.
263
+
264
+ Args:
265
+ endpoint_id: ID of the inbound integration endpoint
266
+
267
+ Returns:
268
+ Response from the enable operation
269
+
270
+ Raises:
271
+ ValidationError: If endpoint_id is missing
272
+ NotFoundError: If endpoint cannot be found
273
+ RestApiError: For API errors
274
+ """
275
+ self._validate_required_params(
276
+ {"endpoint_id": endpoint_id},
277
+ ["endpoint_id"]
278
+ )
279
+
280
+ self._log_operation("enableInboundIntegrationEndpoint", {
281
+ "endpointId": endpoint_id
282
+ })
283
+
284
+ try:
285
+ response = self.client.enableInboundIntegrationEndpoint(
286
+ id=endpoint_id,
287
+ **self._build_context_params()
288
+ )
289
+ except Exception as e:
290
+ if "404" in str(e):
291
+ raise NotFoundError(endpoint_id, "InboundIntegrationEndpoint")
292
+ raise
293
+
294
+ self._check_for_api_error(response, endpoint_id, "InboundIntegrationEndpoint")
295
+
296
+ if isinstance(response, dict):
297
+ return response
298
+ return {"success": True, "endpoint": endpoint_id, "action": "enabled"}
299
+
300
+ @handle_rest_errors
301
+ def disable_endpoint(self, endpoint_id: str) -> dict[str, Any]:
302
+ """Disable an inbound integration endpoint.
303
+
304
+ Disables the endpoint so it will not accept uploads or process data.
305
+ Can be called regardless of the endpoint's current status.
306
+
307
+ Args:
308
+ endpoint_id: ID of the inbound integration endpoint
309
+
310
+ Returns:
311
+ Response from the disable operation
312
+
313
+ Raises:
314
+ ValidationError: If endpoint_id is missing
315
+ NotFoundError: If endpoint cannot be found
316
+ RestApiError: For API errors
317
+ """
318
+ self._validate_required_params(
319
+ {"endpoint_id": endpoint_id},
320
+ ["endpoint_id"]
321
+ )
322
+
323
+ self._log_operation("disableInboundIntegrationEndpoint", {
324
+ "endpointId": endpoint_id
325
+ })
326
+
327
+ try:
328
+ response = self.client.disableInboundIntegrationEndpoint(
329
+ id=endpoint_id,
330
+ **self._build_context_params()
331
+ )
332
+ except Exception as e:
333
+ if "404" in str(e):
334
+ raise NotFoundError(endpoint_id, "InboundIntegrationEndpoint")
335
+ raise
336
+
337
+ self._check_for_api_error(response, endpoint_id, "InboundIntegrationEndpoint")
338
+
339
+ if isinstance(response, dict):
340
+ return response
341
+ return {"success": True, "endpoint": endpoint_id, "action": "disabled"}
342
+
343
+ @handle_rest_errors
344
+ def get_execution_report(self, endpoint_id: str) -> list[dict[str, Any]]:
345
+ """Get the execution report for an inbound endpoint's main process.
346
+
347
+ Returns detailed information about the last execution or current state.
348
+
349
+ Args:
350
+ endpoint_id: ID of the inbound integration endpoint
351
+
352
+ Returns:
353
+ List of execution report entries with details about operations performed
354
+
355
+ Raises:
356
+ ValidationError: If endpoint_id is missing
357
+ NotFoundError: If endpoint cannot be found
358
+ RestApiError: For API errors
359
+ """
360
+ self._validate_required_params(
361
+ {"endpoint_id": endpoint_id},
362
+ ["endpoint_id"]
363
+ )
364
+
365
+ self._log_operation("getInboundIntegrationEndpointExecutionReport", {
366
+ "endpointId": endpoint_id
367
+ })
368
+
369
+ try:
370
+ response = self.client.getInboundIntegrationEndpointExecutionReport(
371
+ id=endpoint_id,
372
+ **self._build_context_params()
373
+ )
374
+ except Exception as e:
375
+ if "404" in str(e):
376
+ raise NotFoundError(endpoint_id, "InboundIntegrationEndpoint")
377
+ raise
378
+
379
+ self._check_for_api_error(response, endpoint_id, "InboundIntegrationEndpoint")
380
+
381
+ if isinstance(response, (list, dict)):
382
+ return self._coerce_list_payload(response)
383
+ if response is not None:
384
+ return [response]
385
+ return []
386
+
387
+ @handle_rest_errors
388
+ def get_statistics(self, endpoint_id: str) -> dict[str, Any]:
389
+ """Get statistics for an inbound integration endpoint.
390
+
391
+ Returns operational statistics and metrics about the endpoint.
392
+
393
+ Args:
394
+ endpoint_id: ID of the inbound integration endpoint
395
+
396
+ Returns:
397
+ Dictionary with statistics (message counts, error counts, etc.)
398
+
399
+ Raises:
400
+ ValidationError: If endpoint_id is missing
401
+ NotFoundError: If endpoint cannot be found
402
+ RestApiError: For API errors
403
+ """
404
+ self._validate_required_params(
405
+ {"endpoint_id": endpoint_id},
406
+ ["endpoint_id"]
407
+ )
408
+
409
+ self._log_operation("getInboundIntegrationEndpointStatistics", {
410
+ "endpointId": endpoint_id
411
+ })
412
+
413
+ try:
414
+ response = self.client.getInboundIntegrationEndpointStatistics(
415
+ id=endpoint_id,
416
+ **self._build_context_params()
417
+ )
418
+ except Exception as e:
419
+ if "404" in str(e):
420
+ raise NotFoundError(endpoint_id, "InboundIntegrationEndpoint")
421
+ raise
422
+
423
+ self._check_for_api_error(response, endpoint_id, "InboundIntegrationEndpoint")
424
+
425
+ if isinstance(response, dict):
426
+ return response
427
+ return {}
428
+
429
+ @handle_rest_errors
430
+ def get_worker_processes(self, endpoint_id: str,
431
+ status_filter: str | None = None) -> list[str]:
432
+ """Get background process IDs started by this endpoint.
433
+
434
+ Args:
435
+ endpoint_id: ID of the inbound integration endpoint
436
+ status_filter: Optional filter by process status (PENDING, PROCESSING, COMPLETED, FAILED)
437
+
438
+ Returns:
439
+ List of background process IDs
440
+
441
+ Raises:
442
+ ValidationError: If endpoint_id is missing
443
+ NotFoundError: If endpoint cannot be found
444
+ RestApiError: For API errors
445
+ """
446
+ self._validate_required_params(
447
+ {"endpoint_id": endpoint_id},
448
+ ["endpoint_id"]
449
+ )
450
+
451
+ params: dict[str, Any] = self._build_context_params()
452
+ if status_filter:
453
+ params["status"] = status_filter
454
+
455
+ self._log_operation("getInboundIntegrationEndpointWorkerProcesses", {
456
+ "endpointId": endpoint_id,
457
+ "statusFilter": status_filter
458
+ })
459
+
460
+ try:
461
+ response = self.client.getInboundIntegrationEndpointWorkerProcesses(
462
+ id=endpoint_id,
463
+ **params
464
+ )
465
+ except Exception as e:
466
+ if "404" in str(e):
467
+ raise NotFoundError(endpoint_id, "InboundIntegrationEndpoint")
468
+ raise
469
+
470
+ self._check_for_api_error(response, endpoint_id, "InboundIntegrationEndpoint")
471
+
472
+ return self._coerce_list_payload(response)