phenoml 0.0.2__py3-none-any.whl → 0.0.17__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 (149) hide show
  1. phenoml/agent/__init__.py +6 -8
  2. phenoml/agent/client.py +85 -67
  3. phenoml/agent/raw_client.py +61 -77
  4. phenoml/agent/types/__init__.py +6 -8
  5. phenoml/agent/types/agent_create_request.py +53 -0
  6. phenoml/agent/types/agent_create_request_provider.py +5 -0
  7. phenoml/agent/types/agent_template.py +3 -6
  8. phenoml/agent/types/agent_template_provider.py +5 -0
  9. phenoml/agent/types/json_patch_operation.py +5 -1
  10. phenoml/client.py +12 -0
  11. phenoml/construe/__init__.py +2 -16
  12. phenoml/construe/client.py +0 -90
  13. phenoml/construe/raw_client.py +0 -180
  14. phenoml/construe/types/__init__.py +2 -20
  15. phenoml/construe/types/extract_request_config.py +33 -4
  16. phenoml/construe/types/extract_request_config_chunking_method.py +3 -1
  17. phenoml/construe/types/extract_request_config_validation_method.py +5 -0
  18. phenoml/construe/types/extract_request_system.py +2 -0
  19. phenoml/core/client_wrapper.py +2 -2
  20. phenoml/fhir/__init__.py +36 -0
  21. phenoml/fhir/client.py +1072 -0
  22. phenoml/fhir/errors/__init__.py +10 -0
  23. phenoml/fhir/errors/bad_request_error.py +10 -0
  24. phenoml/fhir/errors/internal_server_error.py +10 -0
  25. phenoml/fhir/errors/not_found_error.py +10 -0
  26. phenoml/fhir/errors/unauthorized_error.py +10 -0
  27. phenoml/fhir/raw_client.py +1469 -0
  28. phenoml/fhir/types/__init__.py +29 -0
  29. phenoml/{agent/types/chat_fhir_client_config.py → fhir/types/error_response.py} +11 -6
  30. phenoml/fhir/types/fhir_bundle.py +43 -0
  31. phenoml/fhir/types/fhir_bundle_entry_item.py +34 -0
  32. phenoml/fhir/types/fhir_bundle_entry_item_request.py +25 -0
  33. phenoml/fhir/types/fhir_bundle_entry_item_request_method.py +5 -0
  34. phenoml/{construe/types/bad_request_error_body.py → fhir/types/fhir_bundle_entry_item_response.py} +4 -7
  35. phenoml/fhir/types/fhir_patch_request_body_item.py +40 -0
  36. phenoml/fhir/types/fhir_patch_request_body_item_op.py +7 -0
  37. phenoml/fhir/types/fhir_resource.py +40 -0
  38. phenoml/fhir/types/fhir_resource_meta.py +28 -0
  39. phenoml/fhir/types/fhir_search_response.py +8 -0
  40. phenoml/fhir_provider/__init__.py +45 -0
  41. phenoml/fhir_provider/client.py +748 -0
  42. phenoml/fhir_provider/errors/__init__.py +11 -0
  43. phenoml/fhir_provider/errors/bad_request_error.py +10 -0
  44. phenoml/fhir_provider/errors/forbidden_error.py +10 -0
  45. phenoml/fhir_provider/errors/internal_server_error.py +10 -0
  46. phenoml/fhir_provider/errors/not_found_error.py +10 -0
  47. phenoml/fhir_provider/errors/unauthorized_error.py +10 -0
  48. phenoml/fhir_provider/raw_client.py +1462 -0
  49. phenoml/fhir_provider/types/__init__.py +37 -0
  50. phenoml/fhir_provider/types/auth_method.py +7 -0
  51. phenoml/fhir_provider/types/fhir_provider_auth_config.py +53 -0
  52. phenoml/fhir_provider/types/fhir_provider_delete_response.py +20 -0
  53. phenoml/fhir_provider/types/fhir_provider_list_response.py +22 -0
  54. phenoml/fhir_provider/types/fhir_provider_remove_auth_config_response.py +22 -0
  55. phenoml/fhir_provider/types/fhir_provider_response.py +22 -0
  56. phenoml/fhir_provider/types/fhir_provider_set_active_auth_config_response.py +22 -0
  57. phenoml/fhir_provider/types/fhir_provider_template.py +66 -0
  58. phenoml/fhir_provider/types/fhir_query_response.py +27 -0
  59. phenoml/fhir_provider/types/fhir_query_response_data.py +5 -0
  60. phenoml/fhir_provider/types/json_web_key.py +51 -0
  61. phenoml/fhir_provider/types/provider.py +8 -0
  62. phenoml/fhir_provider/types/role.py +27 -0
  63. phenoml/fhir_provider/types/service_account_key.py +35 -0
  64. phenoml/fhir_provider/types/smart_configuration.py +46 -0
  65. phenoml/lang2fhir/__init__.py +10 -0
  66. phenoml/lang2fhir/client.py +111 -6
  67. phenoml/lang2fhir/raw_client.py +189 -0
  68. phenoml/lang2fhir/types/__init__.py +10 -0
  69. phenoml/lang2fhir/types/create_multi_response.py +39 -0
  70. phenoml/lang2fhir/types/create_multi_response_bundle.py +28 -0
  71. phenoml/lang2fhir/types/create_multi_response_bundle_entry_item.py +24 -0
  72. phenoml/lang2fhir/types/create_multi_response_bundle_entry_item_request.py +20 -0
  73. phenoml/{construe/types/construe_cohort_response_queries_item_code_extract_results_item_codes_item.py → lang2fhir/types/create_multi_response_resources_item.py} +13 -7
  74. phenoml/summary/__init__.py +41 -0
  75. phenoml/summary/client.py +668 -0
  76. phenoml/summary/errors/__init__.py +11 -0
  77. phenoml/summary/errors/bad_request_error.py +10 -0
  78. phenoml/summary/errors/forbidden_error.py +10 -0
  79. phenoml/summary/errors/internal_server_error.py +10 -0
  80. phenoml/summary/errors/not_found_error.py +10 -0
  81. phenoml/summary/errors/unauthorized_error.py +10 -0
  82. phenoml/summary/raw_client.py +1202 -0
  83. phenoml/summary/types/__init__.py +33 -0
  84. phenoml/summary/types/create_summary_request_fhir_resources.py +8 -0
  85. phenoml/summary/types/create_summary_request_mode.py +5 -0
  86. phenoml/{agent/types/agent_fhir_config.py → summary/types/create_summary_response.py} +7 -9
  87. phenoml/summary/types/create_summary_template_response.py +23 -0
  88. phenoml/{construe/types/unauthorized_error_body.py → summary/types/error_response.py} +4 -8
  89. phenoml/summary/types/fhir_bundle.py +23 -0
  90. phenoml/summary/types/fhir_bundle_entry_item.py +20 -0
  91. phenoml/summary/types/fhir_resource.py +24 -0
  92. phenoml/summary/types/summary_delete_template_response.py +20 -0
  93. phenoml/summary/types/summary_get_template_response.py +21 -0
  94. phenoml/summary/types/summary_list_templates_response.py +21 -0
  95. phenoml/summary/types/summary_template.py +41 -0
  96. phenoml/summary/types/summary_update_template_response.py +22 -0
  97. phenoml/tools/__init__.py +6 -8
  98. phenoml/tools/client.py +259 -44
  99. phenoml/tools/raw_client.py +347 -55
  100. phenoml/tools/types/__init__.py +6 -8
  101. phenoml/tools/types/lang2fhir_and_create_multi_response.py +41 -0
  102. phenoml/{construe/types/construe_cohort_response_queries_item_code_extract_results_item.py → tools/types/lang2fhir_and_create_multi_response_resource_info_item.py} +14 -7
  103. phenoml/tools/types/lang2fhir_and_create_multi_response_response_bundle.py +27 -0
  104. phenoml/workflows/__init__.py +61 -0
  105. phenoml/workflows/client.py +694 -0
  106. phenoml/workflows/errors/__init__.py +11 -0
  107. phenoml/workflows/errors/bad_request_error.py +10 -0
  108. phenoml/workflows/errors/forbidden_error.py +10 -0
  109. phenoml/workflows/errors/internal_server_error.py +10 -0
  110. phenoml/workflows/errors/not_found_error.py +10 -0
  111. phenoml/workflows/errors/unauthorized_error.py +10 -0
  112. phenoml/workflows/raw_client.py +1266 -0
  113. phenoml/workflows/types/__init__.py +53 -0
  114. phenoml/workflows/types/create_workflow_request_fhir_provider_id.py +5 -0
  115. phenoml/workflows/types/create_workflow_response.py +44 -0
  116. phenoml/{tools/types/fhir_client_config.py → workflows/types/decision_node_definition.py} +7 -6
  117. phenoml/workflows/types/execute_workflow_response.py +30 -0
  118. phenoml/{construe/types/internal_server_error_body.py → workflows/types/execute_workflow_response_results.py} +3 -8
  119. phenoml/workflows/types/lang2fhir_create_definition.py +37 -0
  120. phenoml/workflows/types/lang2fhir_search_definition.py +42 -0
  121. phenoml/workflows/types/list_workflows_response.py +39 -0
  122. phenoml/workflows/types/step_operation.py +26 -0
  123. phenoml/workflows/types/sub_workflow_definition.py +32 -0
  124. phenoml/workflows/types/update_workflow_request_fhir_provider_id.py +5 -0
  125. phenoml/workflows/types/workflow_config.py +27 -0
  126. phenoml/workflows/types/workflow_definition.py +57 -0
  127. phenoml/workflows/types/workflow_graph.py +23 -0
  128. phenoml/workflows/types/workflow_response.py +61 -0
  129. phenoml/workflows/types/workflow_response_graph.py +23 -0
  130. phenoml/workflows/types/workflow_step.py +55 -0
  131. phenoml/workflows/types/workflow_step_summary.py +47 -0
  132. phenoml/workflows/types/workflow_step_summary_type.py +5 -0
  133. phenoml/workflows/types/workflow_step_type.py +5 -0
  134. phenoml/workflows/types/workflows_delete_response.py +20 -0
  135. phenoml/workflows/types/workflows_get_response.py +26 -0
  136. phenoml/workflows/types/workflows_update_response.py +31 -0
  137. phenoml-0.0.17.dist-info/LICENSE +21 -0
  138. {phenoml-0.0.2.dist-info → phenoml-0.0.17.dist-info}/METADATA +1 -1
  139. phenoml-0.0.17.dist-info/RECORD +251 -0
  140. phenoml/agent/types/agent_provider.py +0 -7
  141. phenoml/agent/types/provider_type.py +0 -5
  142. phenoml/construe/types/construe_cohort_request_config.py +0 -37
  143. phenoml/construe/types/construe_cohort_response.py +0 -33
  144. phenoml/construe/types/construe_cohort_response_queries_item.py +0 -49
  145. phenoml/tools/types/cohort_request_provider.py +0 -5
  146. phenoml/tools/types/lang2fhir_and_create_request_provider.py +0 -7
  147. phenoml/tools/types/lang2fhir_and_search_request_provider.py +0 -7
  148. phenoml-0.0.2.dist-info/RECORD +0 -153
  149. {phenoml-0.0.2.dist-info → phenoml-0.0.17.dist-info}/WHEEL +0 -0
@@ -0,0 +1,1469 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ import typing
4
+ from json.decoder import JSONDecodeError
5
+
6
+ from ..core.api_error import ApiError
7
+ from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
8
+ from ..core.http_response import AsyncHttpResponse, HttpResponse
9
+ from ..core.jsonable_encoder import jsonable_encoder
10
+ from ..core.pydantic_utilities import parse_obj_as
11
+ from ..core.request_options import RequestOptions
12
+ from ..core.serialization import convert_and_respect_annotation_metadata
13
+ from .errors.bad_request_error import BadRequestError
14
+ from .errors.internal_server_error import InternalServerError
15
+ from .errors.not_found_error import NotFoundError
16
+ from .errors.unauthorized_error import UnauthorizedError
17
+ from .types.fhir_bundle import FhirBundle
18
+ from .types.fhir_bundle_entry_item import FhirBundleEntryItem
19
+ from .types.fhir_patch_request_body_item import FhirPatchRequestBodyItem
20
+ from .types.fhir_resource import FhirResource
21
+ from .types.fhir_resource_meta import FhirResourceMeta
22
+ from .types.fhir_search_response import FhirSearchResponse
23
+
24
+ # this is used as the default value for optional parameters
25
+ OMIT = typing.cast(typing.Any, ...)
26
+
27
+
28
+ class RawFhirClient:
29
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
30
+ self._client_wrapper = client_wrapper
31
+
32
+ def search(
33
+ self,
34
+ fhir_provider_id: str,
35
+ fhir_path: str,
36
+ *,
37
+ query_parameters: typing.Optional[typing.Dict[str, typing.Optional[str]]] = None,
38
+ phenoml_on_behalf_of: typing.Optional[str] = None,
39
+ phenoml_fhir_provider: typing.Optional[str] = None,
40
+ request_options: typing.Optional[RequestOptions] = None,
41
+ ) -> HttpResponse[FhirSearchResponse]:
42
+ """
43
+ Retrieves FHIR resources from the specified provider. Supports both individual resource retrieval and search operations based on the FHIR path and query parameters.
44
+
45
+ The request is proxied to the configured FHIR server with appropriate authentication headers.
46
+
47
+ Parameters
48
+ ----------
49
+ fhir_provider_id : str
50
+ The ID of the FHIR provider to use. Can be either:
51
+ - A UUID representing the provider ID
52
+ - A provider name (legacy support - will just use the most recently updated provider with this name)
53
+
54
+ fhir_path : str
55
+ The FHIR resource path to operate on. This follows FHIR RESTful API conventions.
56
+ Examples:
57
+ - "Patient" (for resource type operations)
58
+ - "Patient/123" (for specific resource operations)
59
+ - "Patient/123/_history" (for history operations)
60
+
61
+ query_parameters : typing.Optional[typing.Dict[str, typing.Optional[str]]]
62
+ FHIR-compliant query parameters for search operations. Supports standard FHIR search parameters including:
63
+ - Resource-specific search parameters (e.g., name for Patient, status for Observation)
64
+ - Common search parameters (_id, _lastUpdated, _tag, _profile, _security, _text, _content, _filter)
65
+ - Result parameters (_count, _offset, _sort, _include, _revinclude, _summary, _elements)
66
+ - Search prefixes for dates, numbers, quantities (eq, ne, gt, ge, lt, le, sa, eb, ap)
67
+
68
+ phenoml_on_behalf_of : typing.Optional[str]
69
+ Optional header for on-behalf-of authentication. Used when making requests on behalf of another user or entity.
70
+ Must be in the format: Patient/{uuid} or Practitioner/{uuid}
71
+
72
+ phenoml_fhir_provider : typing.Optional[str]
73
+ Optional header for FHIR provider authentication. Contains credentials in the format {fhir_provider_id}:{oauth2_token}.
74
+ Multiple FHIR provider integrations can be provided as comma-separated values.
75
+
76
+ request_options : typing.Optional[RequestOptions]
77
+ Request-specific configuration.
78
+
79
+ Returns
80
+ -------
81
+ HttpResponse[FhirSearchResponse]
82
+ Successfully retrieved FHIR resource(s)
83
+ """
84
+ _response = self._client_wrapper.httpx_client.request(
85
+ f"fhir-provider/{jsonable_encoder(fhir_provider_id)}/fhir/{jsonable_encoder(fhir_path)}",
86
+ method="GET",
87
+ params={
88
+ "query_parameters": query_parameters,
89
+ },
90
+ headers={
91
+ "X-Phenoml-On-Behalf-Of": str(phenoml_on_behalf_of) if phenoml_on_behalf_of is not None else None,
92
+ "X-Phenoml-Fhir-Provider": str(phenoml_fhir_provider) if phenoml_fhir_provider is not None else None,
93
+ },
94
+ request_options=request_options,
95
+ )
96
+ try:
97
+ if 200 <= _response.status_code < 300:
98
+ _data = typing.cast(
99
+ FhirSearchResponse,
100
+ parse_obj_as(
101
+ type_=FhirSearchResponse, # type: ignore
102
+ object_=_response.json(),
103
+ ),
104
+ )
105
+ return HttpResponse(response=_response, data=_data)
106
+ if _response.status_code == 400:
107
+ raise BadRequestError(
108
+ headers=dict(_response.headers),
109
+ body=typing.cast(
110
+ typing.Optional[typing.Any],
111
+ parse_obj_as(
112
+ type_=typing.Optional[typing.Any], # type: ignore
113
+ object_=_response.json(),
114
+ ),
115
+ ),
116
+ )
117
+ if _response.status_code == 401:
118
+ raise UnauthorizedError(
119
+ headers=dict(_response.headers),
120
+ body=typing.cast(
121
+ typing.Optional[typing.Any],
122
+ parse_obj_as(
123
+ type_=typing.Optional[typing.Any], # type: ignore
124
+ object_=_response.json(),
125
+ ),
126
+ ),
127
+ )
128
+ if _response.status_code == 404:
129
+ raise NotFoundError(
130
+ headers=dict(_response.headers),
131
+ body=typing.cast(
132
+ typing.Optional[typing.Any],
133
+ parse_obj_as(
134
+ type_=typing.Optional[typing.Any], # type: ignore
135
+ object_=_response.json(),
136
+ ),
137
+ ),
138
+ )
139
+ if _response.status_code == 500:
140
+ raise InternalServerError(
141
+ headers=dict(_response.headers),
142
+ body=typing.cast(
143
+ typing.Optional[typing.Any],
144
+ parse_obj_as(
145
+ type_=typing.Optional[typing.Any], # type: ignore
146
+ object_=_response.json(),
147
+ ),
148
+ ),
149
+ )
150
+ _response_json = _response.json()
151
+ except JSONDecodeError:
152
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
153
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
154
+
155
+ def create(
156
+ self,
157
+ fhir_provider_id: str,
158
+ fhir_path: str,
159
+ *,
160
+ resource_type: str,
161
+ phenoml_on_behalf_of: typing.Optional[str] = None,
162
+ phenoml_fhir_provider: typing.Optional[str] = None,
163
+ id: typing.Optional[str] = OMIT,
164
+ meta: typing.Optional[FhirResourceMeta] = OMIT,
165
+ request_options: typing.Optional[RequestOptions] = None,
166
+ ) -> HttpResponse[FhirResource]:
167
+ """
168
+ Creates a new FHIR resource on the specified provider. The request body should contain a valid FHIR resource in JSON format.
169
+
170
+ The request is proxied to the configured FHIR server with appropriate authentication headers.
171
+
172
+ Parameters
173
+ ----------
174
+ fhir_provider_id : str
175
+ The ID of the FHIR provider to use. Can be either:
176
+ - A UUID representing the provider ID
177
+ - A provider name (legacy support - will just use the most recently updated provider with this name)
178
+
179
+ fhir_path : str
180
+ The FHIR resource path to operate on. This follows FHIR RESTful API conventions.
181
+ Examples:
182
+ - "Patient" (for resource type operations)
183
+ - "Patient/123" (for specific resource operations)
184
+ - "Patient/123/_history" (for history operations)
185
+
186
+ resource_type : str
187
+ The type of FHIR resource (e.g., Patient, Observation, etc.)
188
+
189
+ phenoml_on_behalf_of : typing.Optional[str]
190
+ Optional header for on-behalf-of authentication. Used when making requests on behalf of another user or entity.
191
+ Must be in the format: Patient/{uuid} or Practitioner/{uuid}
192
+
193
+ phenoml_fhir_provider : typing.Optional[str]
194
+ Optional header for FHIR provider authentication. Contains credentials in the format {fhir_provider_id}:{oauth2_token}.
195
+ Multiple FHIR provider integrations can be provided as comma-separated values.
196
+
197
+ id : typing.Optional[str]
198
+ Logical ID of the resource
199
+
200
+ meta : typing.Optional[FhirResourceMeta]
201
+ Metadata about the resource
202
+
203
+ request_options : typing.Optional[RequestOptions]
204
+ Request-specific configuration.
205
+
206
+ Returns
207
+ -------
208
+ HttpResponse[FhirResource]
209
+ Resource created successfully
210
+ """
211
+ _response = self._client_wrapper.httpx_client.request(
212
+ f"fhir-provider/{jsonable_encoder(fhir_provider_id)}/fhir/{jsonable_encoder(fhir_path)}",
213
+ method="POST",
214
+ json={
215
+ "resourceType": resource_type,
216
+ "id": id,
217
+ "meta": convert_and_respect_annotation_metadata(
218
+ object_=meta, annotation=FhirResourceMeta, direction="write"
219
+ ),
220
+ },
221
+ headers={
222
+ "content-type": "application/fhir+json",
223
+ "X-Phenoml-On-Behalf-Of": str(phenoml_on_behalf_of) if phenoml_on_behalf_of is not None else None,
224
+ "X-Phenoml-Fhir-Provider": str(phenoml_fhir_provider) if phenoml_fhir_provider is not None else None,
225
+ },
226
+ request_options=request_options,
227
+ omit=OMIT,
228
+ )
229
+ try:
230
+ if 200 <= _response.status_code < 300:
231
+ _data = typing.cast(
232
+ FhirResource,
233
+ parse_obj_as(
234
+ type_=FhirResource, # type: ignore
235
+ object_=_response.json(),
236
+ ),
237
+ )
238
+ return HttpResponse(response=_response, data=_data)
239
+ if _response.status_code == 400:
240
+ raise BadRequestError(
241
+ headers=dict(_response.headers),
242
+ body=typing.cast(
243
+ typing.Optional[typing.Any],
244
+ parse_obj_as(
245
+ type_=typing.Optional[typing.Any], # type: ignore
246
+ object_=_response.json(),
247
+ ),
248
+ ),
249
+ )
250
+ if _response.status_code == 401:
251
+ raise UnauthorizedError(
252
+ headers=dict(_response.headers),
253
+ body=typing.cast(
254
+ typing.Optional[typing.Any],
255
+ parse_obj_as(
256
+ type_=typing.Optional[typing.Any], # type: ignore
257
+ object_=_response.json(),
258
+ ),
259
+ ),
260
+ )
261
+ if _response.status_code == 500:
262
+ raise InternalServerError(
263
+ headers=dict(_response.headers),
264
+ body=typing.cast(
265
+ typing.Optional[typing.Any],
266
+ parse_obj_as(
267
+ type_=typing.Optional[typing.Any], # type: ignore
268
+ object_=_response.json(),
269
+ ),
270
+ ),
271
+ )
272
+ _response_json = _response.json()
273
+ except JSONDecodeError:
274
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
275
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
276
+
277
+ def upsert(
278
+ self,
279
+ fhir_provider_id: str,
280
+ fhir_path: str,
281
+ *,
282
+ resource_type: str,
283
+ phenoml_on_behalf_of: typing.Optional[str] = None,
284
+ phenoml_fhir_provider: typing.Optional[str] = None,
285
+ id: typing.Optional[str] = OMIT,
286
+ meta: typing.Optional[FhirResourceMeta] = OMIT,
287
+ request_options: typing.Optional[RequestOptions] = None,
288
+ ) -> HttpResponse[FhirResource]:
289
+ """
290
+ Creates or updates a FHIR resource on the specified provider. If the resource exists, it will be updated; otherwise, it will be created.
291
+
292
+ The request is proxied to the configured FHIR server with appropriate authentication headers.
293
+
294
+ Parameters
295
+ ----------
296
+ fhir_provider_id : str
297
+ The ID of the FHIR provider to use. Can be either:
298
+ - A UUID representing the provider ID
299
+ - A provider name (legacy support - will just use the most recently updated provider with this name)
300
+
301
+ fhir_path : str
302
+ The FHIR resource path to operate on. This follows FHIR RESTful API conventions.
303
+ Examples:
304
+ - "Patient" (for resource type operations)
305
+ - "Patient/123" (for specific resource operations)
306
+ - "Patient/123/_history" (for history operations)
307
+
308
+ resource_type : str
309
+ The type of FHIR resource (e.g., Patient, Observation, etc.)
310
+
311
+ phenoml_on_behalf_of : typing.Optional[str]
312
+ Optional header for on-behalf-of authentication. Used when making requests on behalf of another user or entity.
313
+ Must be in the format: Patient/{uuid} or Practitioner/{uuid}
314
+
315
+ phenoml_fhir_provider : typing.Optional[str]
316
+ Optional header for FHIR provider authentication. Contains credentials in the format {fhir_provider_id}:{oauth2_token}.
317
+ Multiple FHIR provider integrations can be provided as comma-separated values.
318
+
319
+ id : typing.Optional[str]
320
+ Logical ID of the resource
321
+
322
+ meta : typing.Optional[FhirResourceMeta]
323
+ Metadata about the resource
324
+
325
+ request_options : typing.Optional[RequestOptions]
326
+ Request-specific configuration.
327
+
328
+ Returns
329
+ -------
330
+ HttpResponse[FhirResource]
331
+ Resource upserted successfully
332
+ """
333
+ _response = self._client_wrapper.httpx_client.request(
334
+ f"fhir-provider/{jsonable_encoder(fhir_provider_id)}/fhir/{jsonable_encoder(fhir_path)}",
335
+ method="PUT",
336
+ json={
337
+ "resourceType": resource_type,
338
+ "id": id,
339
+ "meta": convert_and_respect_annotation_metadata(
340
+ object_=meta, annotation=FhirResourceMeta, direction="write"
341
+ ),
342
+ },
343
+ headers={
344
+ "content-type": "application/fhir+json",
345
+ "X-Phenoml-On-Behalf-Of": str(phenoml_on_behalf_of) if phenoml_on_behalf_of is not None else None,
346
+ "X-Phenoml-Fhir-Provider": str(phenoml_fhir_provider) if phenoml_fhir_provider is not None else None,
347
+ },
348
+ request_options=request_options,
349
+ omit=OMIT,
350
+ )
351
+ try:
352
+ if 200 <= _response.status_code < 300:
353
+ _data = typing.cast(
354
+ FhirResource,
355
+ parse_obj_as(
356
+ type_=FhirResource, # type: ignore
357
+ object_=_response.json(),
358
+ ),
359
+ )
360
+ return HttpResponse(response=_response, data=_data)
361
+ if _response.status_code == 400:
362
+ raise BadRequestError(
363
+ headers=dict(_response.headers),
364
+ body=typing.cast(
365
+ typing.Optional[typing.Any],
366
+ parse_obj_as(
367
+ type_=typing.Optional[typing.Any], # type: ignore
368
+ object_=_response.json(),
369
+ ),
370
+ ),
371
+ )
372
+ if _response.status_code == 401:
373
+ raise UnauthorizedError(
374
+ headers=dict(_response.headers),
375
+ body=typing.cast(
376
+ typing.Optional[typing.Any],
377
+ parse_obj_as(
378
+ type_=typing.Optional[typing.Any], # type: ignore
379
+ object_=_response.json(),
380
+ ),
381
+ ),
382
+ )
383
+ if _response.status_code == 500:
384
+ raise InternalServerError(
385
+ headers=dict(_response.headers),
386
+ body=typing.cast(
387
+ typing.Optional[typing.Any],
388
+ parse_obj_as(
389
+ type_=typing.Optional[typing.Any], # type: ignore
390
+ object_=_response.json(),
391
+ ),
392
+ ),
393
+ )
394
+ _response_json = _response.json()
395
+ except JSONDecodeError:
396
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
397
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
398
+
399
+ def delete(
400
+ self,
401
+ fhir_provider_id: str,
402
+ fhir_path: str,
403
+ *,
404
+ phenoml_on_behalf_of: typing.Optional[str] = None,
405
+ phenoml_fhir_provider: typing.Optional[str] = None,
406
+ request_options: typing.Optional[RequestOptions] = None,
407
+ ) -> HttpResponse[typing.Dict[str, typing.Optional[typing.Any]]]:
408
+ """
409
+ Deletes a FHIR resource from the specified provider.
410
+
411
+ The request is proxied to the configured FHIR server with appropriate authentication headers.
412
+
413
+ Parameters
414
+ ----------
415
+ fhir_provider_id : str
416
+ The ID of the FHIR provider to use. Can be either:
417
+ - A UUID representing the provider ID
418
+ - A provider name (legacy support - will just use the most recently updated provider with this name)
419
+
420
+ fhir_path : str
421
+ The FHIR resource path to operate on. This follows FHIR RESTful API conventions.
422
+ Examples:
423
+ - "Patient" (for resource type operations)
424
+ - "Patient/123" (for specific resource operations)
425
+ - "Patient/123/_history" (for history operations)
426
+
427
+ phenoml_on_behalf_of : typing.Optional[str]
428
+ Optional header for on-behalf-of authentication. Used when making requests on behalf of another user or entity.
429
+ Must be in the format: Patient/{uuid} or Practitioner/{uuid}
430
+
431
+ phenoml_fhir_provider : typing.Optional[str]
432
+ Optional header for FHIR provider authentication. Contains credentials in the format {fhir_provider_id}:{oauth2_token}.
433
+ Multiple FHIR provider integrations can be provided as comma-separated values.
434
+
435
+ request_options : typing.Optional[RequestOptions]
436
+ Request-specific configuration.
437
+
438
+ Returns
439
+ -------
440
+ HttpResponse[typing.Dict[str, typing.Optional[typing.Any]]]
441
+ Resource deleted successfully
442
+ """
443
+ _response = self._client_wrapper.httpx_client.request(
444
+ f"fhir-provider/{jsonable_encoder(fhir_provider_id)}/fhir/{jsonable_encoder(fhir_path)}",
445
+ method="DELETE",
446
+ headers={
447
+ "X-Phenoml-On-Behalf-Of": str(phenoml_on_behalf_of) if phenoml_on_behalf_of is not None else None,
448
+ "X-Phenoml-Fhir-Provider": str(phenoml_fhir_provider) if phenoml_fhir_provider is not None else None,
449
+ },
450
+ request_options=request_options,
451
+ )
452
+ try:
453
+ if 200 <= _response.status_code < 300:
454
+ _data = typing.cast(
455
+ typing.Dict[str, typing.Optional[typing.Any]],
456
+ parse_obj_as(
457
+ type_=typing.Dict[str, typing.Optional[typing.Any]], # type: ignore
458
+ object_=_response.json(),
459
+ ),
460
+ )
461
+ return HttpResponse(response=_response, data=_data)
462
+ if _response.status_code == 400:
463
+ raise BadRequestError(
464
+ headers=dict(_response.headers),
465
+ body=typing.cast(
466
+ typing.Optional[typing.Any],
467
+ parse_obj_as(
468
+ type_=typing.Optional[typing.Any], # type: ignore
469
+ object_=_response.json(),
470
+ ),
471
+ ),
472
+ )
473
+ if _response.status_code == 401:
474
+ raise UnauthorizedError(
475
+ headers=dict(_response.headers),
476
+ body=typing.cast(
477
+ typing.Optional[typing.Any],
478
+ parse_obj_as(
479
+ type_=typing.Optional[typing.Any], # type: ignore
480
+ object_=_response.json(),
481
+ ),
482
+ ),
483
+ )
484
+ if _response.status_code == 404:
485
+ raise NotFoundError(
486
+ headers=dict(_response.headers),
487
+ body=typing.cast(
488
+ typing.Optional[typing.Any],
489
+ parse_obj_as(
490
+ type_=typing.Optional[typing.Any], # type: ignore
491
+ object_=_response.json(),
492
+ ),
493
+ ),
494
+ )
495
+ if _response.status_code == 500:
496
+ raise InternalServerError(
497
+ headers=dict(_response.headers),
498
+ body=typing.cast(
499
+ typing.Optional[typing.Any],
500
+ parse_obj_as(
501
+ type_=typing.Optional[typing.Any], # type: ignore
502
+ object_=_response.json(),
503
+ ),
504
+ ),
505
+ )
506
+ _response_json = _response.json()
507
+ except JSONDecodeError:
508
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
509
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
510
+
511
+ def patch(
512
+ self,
513
+ fhir_provider_id: str,
514
+ fhir_path: str,
515
+ *,
516
+ request: typing.Sequence[FhirPatchRequestBodyItem],
517
+ phenoml_on_behalf_of: typing.Optional[str] = None,
518
+ phenoml_fhir_provider: typing.Optional[str] = None,
519
+ request_options: typing.Optional[RequestOptions] = None,
520
+ ) -> HttpResponse[FhirResource]:
521
+ """
522
+ Partially updates a FHIR resource on the specified provider using JSON Patch operations as defined in RFC 6902.
523
+
524
+ The request body should contain an array of JSON Patch operations. Each operation specifies:
525
+ - `op`: The operation type (add, remove, replace, move, copy, test)
526
+ - `path`: JSON Pointer to the target location in the resource
527
+ - `value`: The value to use (required for add, replace, and test operations)
528
+
529
+ The request is proxied to the configured FHIR server with appropriate authentication headers.
530
+
531
+ Parameters
532
+ ----------
533
+ fhir_provider_id : str
534
+ The ID of the FHIR provider to use. Can be either:
535
+ - A UUID representing the provider ID
536
+ - A provider name (legacy support - will just use the most recently updated provider with this name)
537
+
538
+ fhir_path : str
539
+ The FHIR resource path to operate on. This follows FHIR RESTful API conventions.
540
+ Examples:
541
+ - "Patient" (for resource type operations)
542
+ - "Patient/123" (for specific resource operations)
543
+ - "Patient/123/_history" (for history operations)
544
+
545
+ request : typing.Sequence[FhirPatchRequestBodyItem]
546
+
547
+ phenoml_on_behalf_of : typing.Optional[str]
548
+ Optional header for on-behalf-of authentication. Used when making requests on behalf of another user or entity.
549
+ Must be in the format: Patient/{uuid} or Practitioner/{uuid}
550
+
551
+ phenoml_fhir_provider : typing.Optional[str]
552
+ Optional header for FHIR provider authentication. Contains credentials in the format {fhir_provider_id}:{oauth2_token}.
553
+ Multiple FHIR provider integrations can be provided as comma-separated values.
554
+
555
+ request_options : typing.Optional[RequestOptions]
556
+ Request-specific configuration.
557
+
558
+ Returns
559
+ -------
560
+ HttpResponse[FhirResource]
561
+ Resource patched successfully
562
+ """
563
+ _response = self._client_wrapper.httpx_client.request(
564
+ f"fhir-provider/{jsonable_encoder(fhir_provider_id)}/fhir/{jsonable_encoder(fhir_path)}",
565
+ method="PATCH",
566
+ json=convert_and_respect_annotation_metadata(
567
+ object_=request, annotation=typing.Sequence[FhirPatchRequestBodyItem], direction="write"
568
+ ),
569
+ headers={
570
+ "content-type": "application/json-patch+json",
571
+ "X-Phenoml-On-Behalf-Of": str(phenoml_on_behalf_of) if phenoml_on_behalf_of is not None else None,
572
+ "X-Phenoml-Fhir-Provider": str(phenoml_fhir_provider) if phenoml_fhir_provider is not None else None,
573
+ },
574
+ request_options=request_options,
575
+ omit=OMIT,
576
+ )
577
+ try:
578
+ if 200 <= _response.status_code < 300:
579
+ _data = typing.cast(
580
+ FhirResource,
581
+ parse_obj_as(
582
+ type_=FhirResource, # type: ignore
583
+ object_=_response.json(),
584
+ ),
585
+ )
586
+ return HttpResponse(response=_response, data=_data)
587
+ if _response.status_code == 400:
588
+ raise BadRequestError(
589
+ headers=dict(_response.headers),
590
+ body=typing.cast(
591
+ typing.Optional[typing.Any],
592
+ parse_obj_as(
593
+ type_=typing.Optional[typing.Any], # type: ignore
594
+ object_=_response.json(),
595
+ ),
596
+ ),
597
+ )
598
+ if _response.status_code == 401:
599
+ raise UnauthorizedError(
600
+ headers=dict(_response.headers),
601
+ body=typing.cast(
602
+ typing.Optional[typing.Any],
603
+ parse_obj_as(
604
+ type_=typing.Optional[typing.Any], # type: ignore
605
+ object_=_response.json(),
606
+ ),
607
+ ),
608
+ )
609
+ if _response.status_code == 404:
610
+ raise NotFoundError(
611
+ headers=dict(_response.headers),
612
+ body=typing.cast(
613
+ typing.Optional[typing.Any],
614
+ parse_obj_as(
615
+ type_=typing.Optional[typing.Any], # type: ignore
616
+ object_=_response.json(),
617
+ ),
618
+ ),
619
+ )
620
+ if _response.status_code == 500:
621
+ raise InternalServerError(
622
+ headers=dict(_response.headers),
623
+ body=typing.cast(
624
+ typing.Optional[typing.Any],
625
+ parse_obj_as(
626
+ type_=typing.Optional[typing.Any], # type: ignore
627
+ object_=_response.json(),
628
+ ),
629
+ ),
630
+ )
631
+ _response_json = _response.json()
632
+ except JSONDecodeError:
633
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
634
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
635
+
636
+ def execute_bundle(
637
+ self,
638
+ fhir_provider_id: str,
639
+ *,
640
+ entry: typing.Sequence[FhirBundleEntryItem],
641
+ phenoml_on_behalf_of: typing.Optional[str] = None,
642
+ phenoml_fhir_provider: typing.Optional[str] = None,
643
+ total: typing.Optional[int] = OMIT,
644
+ request_options: typing.Optional[RequestOptions] = None,
645
+ ) -> HttpResponse[FhirBundle]:
646
+ """
647
+ Executes a FHIR Bundle transaction or batch operation on the specified provider. This allows multiple FHIR resources to be processed in a single request.
648
+
649
+ The request body should contain a valid FHIR Bundle resource with transaction or batch type.
650
+
651
+ The request is proxied to the configured FHIR server with appropriate authentication headers.
652
+
653
+ Parameters
654
+ ----------
655
+ fhir_provider_id : str
656
+ The ID of the FHIR provider to use. Can be either:
657
+ - A UUID representing the provider ID
658
+ - A provider name (legacy support - will just use the most recently updated provider with this name)
659
+
660
+ entry : typing.Sequence[FhirBundleEntryItem]
661
+ Array of bundle entries containing resources or operation results
662
+
663
+ phenoml_on_behalf_of : typing.Optional[str]
664
+ Optional header for on-behalf-of authentication. Used when making requests on behalf of another user or entity.
665
+ Must be in the format: Patient/{uuid} or Practitioner/{uuid}
666
+
667
+ phenoml_fhir_provider : typing.Optional[str]
668
+ Optional header for FHIR provider authentication. Contains credentials in the format {fhir_provider_id}:{oauth2_token}.
669
+ Multiple FHIR provider integrations can be provided as comma-separated values.
670
+
671
+ total : typing.Optional[int]
672
+ Total number of resources that match the search criteria.
673
+ Optional field as not all FHIR servers include it (e.g., Medplum).
674
+
675
+ request_options : typing.Optional[RequestOptions]
676
+ Request-specific configuration.
677
+
678
+ Returns
679
+ -------
680
+ HttpResponse[FhirBundle]
681
+ Bundle executed successfully
682
+ """
683
+ _response = self._client_wrapper.httpx_client.request(
684
+ f"fhir-provider/{jsonable_encoder(fhir_provider_id)}/fhir",
685
+ method="POST",
686
+ json={
687
+ "total": total,
688
+ "entry": convert_and_respect_annotation_metadata(
689
+ object_=entry, annotation=typing.Sequence[FhirBundleEntryItem], direction="write"
690
+ ),
691
+ "resourceType": "Bundle",
692
+ },
693
+ headers={
694
+ "content-type": "application/fhir+json",
695
+ "X-Phenoml-On-Behalf-Of": str(phenoml_on_behalf_of) if phenoml_on_behalf_of is not None else None,
696
+ "X-Phenoml-Fhir-Provider": str(phenoml_fhir_provider) if phenoml_fhir_provider is not None else None,
697
+ },
698
+ request_options=request_options,
699
+ omit=OMIT,
700
+ )
701
+ try:
702
+ if 200 <= _response.status_code < 300:
703
+ _data = typing.cast(
704
+ FhirBundle,
705
+ parse_obj_as(
706
+ type_=FhirBundle, # type: ignore
707
+ object_=_response.json(),
708
+ ),
709
+ )
710
+ return HttpResponse(response=_response, data=_data)
711
+ if _response.status_code == 400:
712
+ raise BadRequestError(
713
+ headers=dict(_response.headers),
714
+ body=typing.cast(
715
+ typing.Optional[typing.Any],
716
+ parse_obj_as(
717
+ type_=typing.Optional[typing.Any], # type: ignore
718
+ object_=_response.json(),
719
+ ),
720
+ ),
721
+ )
722
+ if _response.status_code == 401:
723
+ raise UnauthorizedError(
724
+ headers=dict(_response.headers),
725
+ body=typing.cast(
726
+ typing.Optional[typing.Any],
727
+ parse_obj_as(
728
+ type_=typing.Optional[typing.Any], # type: ignore
729
+ object_=_response.json(),
730
+ ),
731
+ ),
732
+ )
733
+ if _response.status_code == 500:
734
+ raise InternalServerError(
735
+ headers=dict(_response.headers),
736
+ body=typing.cast(
737
+ typing.Optional[typing.Any],
738
+ parse_obj_as(
739
+ type_=typing.Optional[typing.Any], # type: ignore
740
+ object_=_response.json(),
741
+ ),
742
+ ),
743
+ )
744
+ _response_json = _response.json()
745
+ except JSONDecodeError:
746
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
747
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
748
+
749
+
750
+ class AsyncRawFhirClient:
751
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
752
+ self._client_wrapper = client_wrapper
753
+
754
+ async def search(
755
+ self,
756
+ fhir_provider_id: str,
757
+ fhir_path: str,
758
+ *,
759
+ query_parameters: typing.Optional[typing.Dict[str, typing.Optional[str]]] = None,
760
+ phenoml_on_behalf_of: typing.Optional[str] = None,
761
+ phenoml_fhir_provider: typing.Optional[str] = None,
762
+ request_options: typing.Optional[RequestOptions] = None,
763
+ ) -> AsyncHttpResponse[FhirSearchResponse]:
764
+ """
765
+ Retrieves FHIR resources from the specified provider. Supports both individual resource retrieval and search operations based on the FHIR path and query parameters.
766
+
767
+ The request is proxied to the configured FHIR server with appropriate authentication headers.
768
+
769
+ Parameters
770
+ ----------
771
+ fhir_provider_id : str
772
+ The ID of the FHIR provider to use. Can be either:
773
+ - A UUID representing the provider ID
774
+ - A provider name (legacy support - will just use the most recently updated provider with this name)
775
+
776
+ fhir_path : str
777
+ The FHIR resource path to operate on. This follows FHIR RESTful API conventions.
778
+ Examples:
779
+ - "Patient" (for resource type operations)
780
+ - "Patient/123" (for specific resource operations)
781
+ - "Patient/123/_history" (for history operations)
782
+
783
+ query_parameters : typing.Optional[typing.Dict[str, typing.Optional[str]]]
784
+ FHIR-compliant query parameters for search operations. Supports standard FHIR search parameters including:
785
+ - Resource-specific search parameters (e.g., name for Patient, status for Observation)
786
+ - Common search parameters (_id, _lastUpdated, _tag, _profile, _security, _text, _content, _filter)
787
+ - Result parameters (_count, _offset, _sort, _include, _revinclude, _summary, _elements)
788
+ - Search prefixes for dates, numbers, quantities (eq, ne, gt, ge, lt, le, sa, eb, ap)
789
+
790
+ phenoml_on_behalf_of : typing.Optional[str]
791
+ Optional header for on-behalf-of authentication. Used when making requests on behalf of another user or entity.
792
+ Must be in the format: Patient/{uuid} or Practitioner/{uuid}
793
+
794
+ phenoml_fhir_provider : typing.Optional[str]
795
+ Optional header for FHIR provider authentication. Contains credentials in the format {fhir_provider_id}:{oauth2_token}.
796
+ Multiple FHIR provider integrations can be provided as comma-separated values.
797
+
798
+ request_options : typing.Optional[RequestOptions]
799
+ Request-specific configuration.
800
+
801
+ Returns
802
+ -------
803
+ AsyncHttpResponse[FhirSearchResponse]
804
+ Successfully retrieved FHIR resource(s)
805
+ """
806
+ _response = await self._client_wrapper.httpx_client.request(
807
+ f"fhir-provider/{jsonable_encoder(fhir_provider_id)}/fhir/{jsonable_encoder(fhir_path)}",
808
+ method="GET",
809
+ params={
810
+ "query_parameters": query_parameters,
811
+ },
812
+ headers={
813
+ "X-Phenoml-On-Behalf-Of": str(phenoml_on_behalf_of) if phenoml_on_behalf_of is not None else None,
814
+ "X-Phenoml-Fhir-Provider": str(phenoml_fhir_provider) if phenoml_fhir_provider is not None else None,
815
+ },
816
+ request_options=request_options,
817
+ )
818
+ try:
819
+ if 200 <= _response.status_code < 300:
820
+ _data = typing.cast(
821
+ FhirSearchResponse,
822
+ parse_obj_as(
823
+ type_=FhirSearchResponse, # type: ignore
824
+ object_=_response.json(),
825
+ ),
826
+ )
827
+ return AsyncHttpResponse(response=_response, data=_data)
828
+ if _response.status_code == 400:
829
+ raise BadRequestError(
830
+ headers=dict(_response.headers),
831
+ body=typing.cast(
832
+ typing.Optional[typing.Any],
833
+ parse_obj_as(
834
+ type_=typing.Optional[typing.Any], # type: ignore
835
+ object_=_response.json(),
836
+ ),
837
+ ),
838
+ )
839
+ if _response.status_code == 401:
840
+ raise UnauthorizedError(
841
+ headers=dict(_response.headers),
842
+ body=typing.cast(
843
+ typing.Optional[typing.Any],
844
+ parse_obj_as(
845
+ type_=typing.Optional[typing.Any], # type: ignore
846
+ object_=_response.json(),
847
+ ),
848
+ ),
849
+ )
850
+ if _response.status_code == 404:
851
+ raise NotFoundError(
852
+ headers=dict(_response.headers),
853
+ body=typing.cast(
854
+ typing.Optional[typing.Any],
855
+ parse_obj_as(
856
+ type_=typing.Optional[typing.Any], # type: ignore
857
+ object_=_response.json(),
858
+ ),
859
+ ),
860
+ )
861
+ if _response.status_code == 500:
862
+ raise InternalServerError(
863
+ headers=dict(_response.headers),
864
+ body=typing.cast(
865
+ typing.Optional[typing.Any],
866
+ parse_obj_as(
867
+ type_=typing.Optional[typing.Any], # type: ignore
868
+ object_=_response.json(),
869
+ ),
870
+ ),
871
+ )
872
+ _response_json = _response.json()
873
+ except JSONDecodeError:
874
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
875
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
876
+
877
+ async def create(
878
+ self,
879
+ fhir_provider_id: str,
880
+ fhir_path: str,
881
+ *,
882
+ resource_type: str,
883
+ phenoml_on_behalf_of: typing.Optional[str] = None,
884
+ phenoml_fhir_provider: typing.Optional[str] = None,
885
+ id: typing.Optional[str] = OMIT,
886
+ meta: typing.Optional[FhirResourceMeta] = OMIT,
887
+ request_options: typing.Optional[RequestOptions] = None,
888
+ ) -> AsyncHttpResponse[FhirResource]:
889
+ """
890
+ Creates a new FHIR resource on the specified provider. The request body should contain a valid FHIR resource in JSON format.
891
+
892
+ The request is proxied to the configured FHIR server with appropriate authentication headers.
893
+
894
+ Parameters
895
+ ----------
896
+ fhir_provider_id : str
897
+ The ID of the FHIR provider to use. Can be either:
898
+ - A UUID representing the provider ID
899
+ - A provider name (legacy support - will just use the most recently updated provider with this name)
900
+
901
+ fhir_path : str
902
+ The FHIR resource path to operate on. This follows FHIR RESTful API conventions.
903
+ Examples:
904
+ - "Patient" (for resource type operations)
905
+ - "Patient/123" (for specific resource operations)
906
+ - "Patient/123/_history" (for history operations)
907
+
908
+ resource_type : str
909
+ The type of FHIR resource (e.g., Patient, Observation, etc.)
910
+
911
+ phenoml_on_behalf_of : typing.Optional[str]
912
+ Optional header for on-behalf-of authentication. Used when making requests on behalf of another user or entity.
913
+ Must be in the format: Patient/{uuid} or Practitioner/{uuid}
914
+
915
+ phenoml_fhir_provider : typing.Optional[str]
916
+ Optional header for FHIR provider authentication. Contains credentials in the format {fhir_provider_id}:{oauth2_token}.
917
+ Multiple FHIR provider integrations can be provided as comma-separated values.
918
+
919
+ id : typing.Optional[str]
920
+ Logical ID of the resource
921
+
922
+ meta : typing.Optional[FhirResourceMeta]
923
+ Metadata about the resource
924
+
925
+ request_options : typing.Optional[RequestOptions]
926
+ Request-specific configuration.
927
+
928
+ Returns
929
+ -------
930
+ AsyncHttpResponse[FhirResource]
931
+ Resource created successfully
932
+ """
933
+ _response = await self._client_wrapper.httpx_client.request(
934
+ f"fhir-provider/{jsonable_encoder(fhir_provider_id)}/fhir/{jsonable_encoder(fhir_path)}",
935
+ method="POST",
936
+ json={
937
+ "resourceType": resource_type,
938
+ "id": id,
939
+ "meta": convert_and_respect_annotation_metadata(
940
+ object_=meta, annotation=FhirResourceMeta, direction="write"
941
+ ),
942
+ },
943
+ headers={
944
+ "content-type": "application/fhir+json",
945
+ "X-Phenoml-On-Behalf-Of": str(phenoml_on_behalf_of) if phenoml_on_behalf_of is not None else None,
946
+ "X-Phenoml-Fhir-Provider": str(phenoml_fhir_provider) if phenoml_fhir_provider is not None else None,
947
+ },
948
+ request_options=request_options,
949
+ omit=OMIT,
950
+ )
951
+ try:
952
+ if 200 <= _response.status_code < 300:
953
+ _data = typing.cast(
954
+ FhirResource,
955
+ parse_obj_as(
956
+ type_=FhirResource, # type: ignore
957
+ object_=_response.json(),
958
+ ),
959
+ )
960
+ return AsyncHttpResponse(response=_response, data=_data)
961
+ if _response.status_code == 400:
962
+ raise BadRequestError(
963
+ headers=dict(_response.headers),
964
+ body=typing.cast(
965
+ typing.Optional[typing.Any],
966
+ parse_obj_as(
967
+ type_=typing.Optional[typing.Any], # type: ignore
968
+ object_=_response.json(),
969
+ ),
970
+ ),
971
+ )
972
+ if _response.status_code == 401:
973
+ raise UnauthorizedError(
974
+ headers=dict(_response.headers),
975
+ body=typing.cast(
976
+ typing.Optional[typing.Any],
977
+ parse_obj_as(
978
+ type_=typing.Optional[typing.Any], # type: ignore
979
+ object_=_response.json(),
980
+ ),
981
+ ),
982
+ )
983
+ if _response.status_code == 500:
984
+ raise InternalServerError(
985
+ headers=dict(_response.headers),
986
+ body=typing.cast(
987
+ typing.Optional[typing.Any],
988
+ parse_obj_as(
989
+ type_=typing.Optional[typing.Any], # type: ignore
990
+ object_=_response.json(),
991
+ ),
992
+ ),
993
+ )
994
+ _response_json = _response.json()
995
+ except JSONDecodeError:
996
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
997
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
998
+
999
+ async def upsert(
1000
+ self,
1001
+ fhir_provider_id: str,
1002
+ fhir_path: str,
1003
+ *,
1004
+ resource_type: str,
1005
+ phenoml_on_behalf_of: typing.Optional[str] = None,
1006
+ phenoml_fhir_provider: typing.Optional[str] = None,
1007
+ id: typing.Optional[str] = OMIT,
1008
+ meta: typing.Optional[FhirResourceMeta] = OMIT,
1009
+ request_options: typing.Optional[RequestOptions] = None,
1010
+ ) -> AsyncHttpResponse[FhirResource]:
1011
+ """
1012
+ Creates or updates a FHIR resource on the specified provider. If the resource exists, it will be updated; otherwise, it will be created.
1013
+
1014
+ The request is proxied to the configured FHIR server with appropriate authentication headers.
1015
+
1016
+ Parameters
1017
+ ----------
1018
+ fhir_provider_id : str
1019
+ The ID of the FHIR provider to use. Can be either:
1020
+ - A UUID representing the provider ID
1021
+ - A provider name (legacy support - will just use the most recently updated provider with this name)
1022
+
1023
+ fhir_path : str
1024
+ The FHIR resource path to operate on. This follows FHIR RESTful API conventions.
1025
+ Examples:
1026
+ - "Patient" (for resource type operations)
1027
+ - "Patient/123" (for specific resource operations)
1028
+ - "Patient/123/_history" (for history operations)
1029
+
1030
+ resource_type : str
1031
+ The type of FHIR resource (e.g., Patient, Observation, etc.)
1032
+
1033
+ phenoml_on_behalf_of : typing.Optional[str]
1034
+ Optional header for on-behalf-of authentication. Used when making requests on behalf of another user or entity.
1035
+ Must be in the format: Patient/{uuid} or Practitioner/{uuid}
1036
+
1037
+ phenoml_fhir_provider : typing.Optional[str]
1038
+ Optional header for FHIR provider authentication. Contains credentials in the format {fhir_provider_id}:{oauth2_token}.
1039
+ Multiple FHIR provider integrations can be provided as comma-separated values.
1040
+
1041
+ id : typing.Optional[str]
1042
+ Logical ID of the resource
1043
+
1044
+ meta : typing.Optional[FhirResourceMeta]
1045
+ Metadata about the resource
1046
+
1047
+ request_options : typing.Optional[RequestOptions]
1048
+ Request-specific configuration.
1049
+
1050
+ Returns
1051
+ -------
1052
+ AsyncHttpResponse[FhirResource]
1053
+ Resource upserted successfully
1054
+ """
1055
+ _response = await self._client_wrapper.httpx_client.request(
1056
+ f"fhir-provider/{jsonable_encoder(fhir_provider_id)}/fhir/{jsonable_encoder(fhir_path)}",
1057
+ method="PUT",
1058
+ json={
1059
+ "resourceType": resource_type,
1060
+ "id": id,
1061
+ "meta": convert_and_respect_annotation_metadata(
1062
+ object_=meta, annotation=FhirResourceMeta, direction="write"
1063
+ ),
1064
+ },
1065
+ headers={
1066
+ "content-type": "application/fhir+json",
1067
+ "X-Phenoml-On-Behalf-Of": str(phenoml_on_behalf_of) if phenoml_on_behalf_of is not None else None,
1068
+ "X-Phenoml-Fhir-Provider": str(phenoml_fhir_provider) if phenoml_fhir_provider is not None else None,
1069
+ },
1070
+ request_options=request_options,
1071
+ omit=OMIT,
1072
+ )
1073
+ try:
1074
+ if 200 <= _response.status_code < 300:
1075
+ _data = typing.cast(
1076
+ FhirResource,
1077
+ parse_obj_as(
1078
+ type_=FhirResource, # type: ignore
1079
+ object_=_response.json(),
1080
+ ),
1081
+ )
1082
+ return AsyncHttpResponse(response=_response, data=_data)
1083
+ if _response.status_code == 400:
1084
+ raise BadRequestError(
1085
+ headers=dict(_response.headers),
1086
+ body=typing.cast(
1087
+ typing.Optional[typing.Any],
1088
+ parse_obj_as(
1089
+ type_=typing.Optional[typing.Any], # type: ignore
1090
+ object_=_response.json(),
1091
+ ),
1092
+ ),
1093
+ )
1094
+ if _response.status_code == 401:
1095
+ raise UnauthorizedError(
1096
+ headers=dict(_response.headers),
1097
+ body=typing.cast(
1098
+ typing.Optional[typing.Any],
1099
+ parse_obj_as(
1100
+ type_=typing.Optional[typing.Any], # type: ignore
1101
+ object_=_response.json(),
1102
+ ),
1103
+ ),
1104
+ )
1105
+ if _response.status_code == 500:
1106
+ raise InternalServerError(
1107
+ headers=dict(_response.headers),
1108
+ body=typing.cast(
1109
+ typing.Optional[typing.Any],
1110
+ parse_obj_as(
1111
+ type_=typing.Optional[typing.Any], # type: ignore
1112
+ object_=_response.json(),
1113
+ ),
1114
+ ),
1115
+ )
1116
+ _response_json = _response.json()
1117
+ except JSONDecodeError:
1118
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
1119
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
1120
+
1121
+ async def delete(
1122
+ self,
1123
+ fhir_provider_id: str,
1124
+ fhir_path: str,
1125
+ *,
1126
+ phenoml_on_behalf_of: typing.Optional[str] = None,
1127
+ phenoml_fhir_provider: typing.Optional[str] = None,
1128
+ request_options: typing.Optional[RequestOptions] = None,
1129
+ ) -> AsyncHttpResponse[typing.Dict[str, typing.Optional[typing.Any]]]:
1130
+ """
1131
+ Deletes a FHIR resource from the specified provider.
1132
+
1133
+ The request is proxied to the configured FHIR server with appropriate authentication headers.
1134
+
1135
+ Parameters
1136
+ ----------
1137
+ fhir_provider_id : str
1138
+ The ID of the FHIR provider to use. Can be either:
1139
+ - A UUID representing the provider ID
1140
+ - A provider name (legacy support - will just use the most recently updated provider with this name)
1141
+
1142
+ fhir_path : str
1143
+ The FHIR resource path to operate on. This follows FHIR RESTful API conventions.
1144
+ Examples:
1145
+ - "Patient" (for resource type operations)
1146
+ - "Patient/123" (for specific resource operations)
1147
+ - "Patient/123/_history" (for history operations)
1148
+
1149
+ phenoml_on_behalf_of : typing.Optional[str]
1150
+ Optional header for on-behalf-of authentication. Used when making requests on behalf of another user or entity.
1151
+ Must be in the format: Patient/{uuid} or Practitioner/{uuid}
1152
+
1153
+ phenoml_fhir_provider : typing.Optional[str]
1154
+ Optional header for FHIR provider authentication. Contains credentials in the format {fhir_provider_id}:{oauth2_token}.
1155
+ Multiple FHIR provider integrations can be provided as comma-separated values.
1156
+
1157
+ request_options : typing.Optional[RequestOptions]
1158
+ Request-specific configuration.
1159
+
1160
+ Returns
1161
+ -------
1162
+ AsyncHttpResponse[typing.Dict[str, typing.Optional[typing.Any]]]
1163
+ Resource deleted successfully
1164
+ """
1165
+ _response = await self._client_wrapper.httpx_client.request(
1166
+ f"fhir-provider/{jsonable_encoder(fhir_provider_id)}/fhir/{jsonable_encoder(fhir_path)}",
1167
+ method="DELETE",
1168
+ headers={
1169
+ "X-Phenoml-On-Behalf-Of": str(phenoml_on_behalf_of) if phenoml_on_behalf_of is not None else None,
1170
+ "X-Phenoml-Fhir-Provider": str(phenoml_fhir_provider) if phenoml_fhir_provider is not None else None,
1171
+ },
1172
+ request_options=request_options,
1173
+ )
1174
+ try:
1175
+ if 200 <= _response.status_code < 300:
1176
+ _data = typing.cast(
1177
+ typing.Dict[str, typing.Optional[typing.Any]],
1178
+ parse_obj_as(
1179
+ type_=typing.Dict[str, typing.Optional[typing.Any]], # type: ignore
1180
+ object_=_response.json(),
1181
+ ),
1182
+ )
1183
+ return AsyncHttpResponse(response=_response, data=_data)
1184
+ if _response.status_code == 400:
1185
+ raise BadRequestError(
1186
+ headers=dict(_response.headers),
1187
+ body=typing.cast(
1188
+ typing.Optional[typing.Any],
1189
+ parse_obj_as(
1190
+ type_=typing.Optional[typing.Any], # type: ignore
1191
+ object_=_response.json(),
1192
+ ),
1193
+ ),
1194
+ )
1195
+ if _response.status_code == 401:
1196
+ raise UnauthorizedError(
1197
+ headers=dict(_response.headers),
1198
+ body=typing.cast(
1199
+ typing.Optional[typing.Any],
1200
+ parse_obj_as(
1201
+ type_=typing.Optional[typing.Any], # type: ignore
1202
+ object_=_response.json(),
1203
+ ),
1204
+ ),
1205
+ )
1206
+ if _response.status_code == 404:
1207
+ raise NotFoundError(
1208
+ headers=dict(_response.headers),
1209
+ body=typing.cast(
1210
+ typing.Optional[typing.Any],
1211
+ parse_obj_as(
1212
+ type_=typing.Optional[typing.Any], # type: ignore
1213
+ object_=_response.json(),
1214
+ ),
1215
+ ),
1216
+ )
1217
+ if _response.status_code == 500:
1218
+ raise InternalServerError(
1219
+ headers=dict(_response.headers),
1220
+ body=typing.cast(
1221
+ typing.Optional[typing.Any],
1222
+ parse_obj_as(
1223
+ type_=typing.Optional[typing.Any], # type: ignore
1224
+ object_=_response.json(),
1225
+ ),
1226
+ ),
1227
+ )
1228
+ _response_json = _response.json()
1229
+ except JSONDecodeError:
1230
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
1231
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
1232
+
1233
+ async def patch(
1234
+ self,
1235
+ fhir_provider_id: str,
1236
+ fhir_path: str,
1237
+ *,
1238
+ request: typing.Sequence[FhirPatchRequestBodyItem],
1239
+ phenoml_on_behalf_of: typing.Optional[str] = None,
1240
+ phenoml_fhir_provider: typing.Optional[str] = None,
1241
+ request_options: typing.Optional[RequestOptions] = None,
1242
+ ) -> AsyncHttpResponse[FhirResource]:
1243
+ """
1244
+ Partially updates a FHIR resource on the specified provider using JSON Patch operations as defined in RFC 6902.
1245
+
1246
+ The request body should contain an array of JSON Patch operations. Each operation specifies:
1247
+ - `op`: The operation type (add, remove, replace, move, copy, test)
1248
+ - `path`: JSON Pointer to the target location in the resource
1249
+ - `value`: The value to use (required for add, replace, and test operations)
1250
+
1251
+ The request is proxied to the configured FHIR server with appropriate authentication headers.
1252
+
1253
+ Parameters
1254
+ ----------
1255
+ fhir_provider_id : str
1256
+ The ID of the FHIR provider to use. Can be either:
1257
+ - A UUID representing the provider ID
1258
+ - A provider name (legacy support - will just use the most recently updated provider with this name)
1259
+
1260
+ fhir_path : str
1261
+ The FHIR resource path to operate on. This follows FHIR RESTful API conventions.
1262
+ Examples:
1263
+ - "Patient" (for resource type operations)
1264
+ - "Patient/123" (for specific resource operations)
1265
+ - "Patient/123/_history" (for history operations)
1266
+
1267
+ request : typing.Sequence[FhirPatchRequestBodyItem]
1268
+
1269
+ phenoml_on_behalf_of : typing.Optional[str]
1270
+ Optional header for on-behalf-of authentication. Used when making requests on behalf of another user or entity.
1271
+ Must be in the format: Patient/{uuid} or Practitioner/{uuid}
1272
+
1273
+ phenoml_fhir_provider : typing.Optional[str]
1274
+ Optional header for FHIR provider authentication. Contains credentials in the format {fhir_provider_id}:{oauth2_token}.
1275
+ Multiple FHIR provider integrations can be provided as comma-separated values.
1276
+
1277
+ request_options : typing.Optional[RequestOptions]
1278
+ Request-specific configuration.
1279
+
1280
+ Returns
1281
+ -------
1282
+ AsyncHttpResponse[FhirResource]
1283
+ Resource patched successfully
1284
+ """
1285
+ _response = await self._client_wrapper.httpx_client.request(
1286
+ f"fhir-provider/{jsonable_encoder(fhir_provider_id)}/fhir/{jsonable_encoder(fhir_path)}",
1287
+ method="PATCH",
1288
+ json=convert_and_respect_annotation_metadata(
1289
+ object_=request, annotation=typing.Sequence[FhirPatchRequestBodyItem], direction="write"
1290
+ ),
1291
+ headers={
1292
+ "content-type": "application/json-patch+json",
1293
+ "X-Phenoml-On-Behalf-Of": str(phenoml_on_behalf_of) if phenoml_on_behalf_of is not None else None,
1294
+ "X-Phenoml-Fhir-Provider": str(phenoml_fhir_provider) if phenoml_fhir_provider is not None else None,
1295
+ },
1296
+ request_options=request_options,
1297
+ omit=OMIT,
1298
+ )
1299
+ try:
1300
+ if 200 <= _response.status_code < 300:
1301
+ _data = typing.cast(
1302
+ FhirResource,
1303
+ parse_obj_as(
1304
+ type_=FhirResource, # type: ignore
1305
+ object_=_response.json(),
1306
+ ),
1307
+ )
1308
+ return AsyncHttpResponse(response=_response, data=_data)
1309
+ if _response.status_code == 400:
1310
+ raise BadRequestError(
1311
+ headers=dict(_response.headers),
1312
+ body=typing.cast(
1313
+ typing.Optional[typing.Any],
1314
+ parse_obj_as(
1315
+ type_=typing.Optional[typing.Any], # type: ignore
1316
+ object_=_response.json(),
1317
+ ),
1318
+ ),
1319
+ )
1320
+ if _response.status_code == 401:
1321
+ raise UnauthorizedError(
1322
+ headers=dict(_response.headers),
1323
+ body=typing.cast(
1324
+ typing.Optional[typing.Any],
1325
+ parse_obj_as(
1326
+ type_=typing.Optional[typing.Any], # type: ignore
1327
+ object_=_response.json(),
1328
+ ),
1329
+ ),
1330
+ )
1331
+ if _response.status_code == 404:
1332
+ raise NotFoundError(
1333
+ headers=dict(_response.headers),
1334
+ body=typing.cast(
1335
+ typing.Optional[typing.Any],
1336
+ parse_obj_as(
1337
+ type_=typing.Optional[typing.Any], # type: ignore
1338
+ object_=_response.json(),
1339
+ ),
1340
+ ),
1341
+ )
1342
+ if _response.status_code == 500:
1343
+ raise InternalServerError(
1344
+ headers=dict(_response.headers),
1345
+ body=typing.cast(
1346
+ typing.Optional[typing.Any],
1347
+ parse_obj_as(
1348
+ type_=typing.Optional[typing.Any], # type: ignore
1349
+ object_=_response.json(),
1350
+ ),
1351
+ ),
1352
+ )
1353
+ _response_json = _response.json()
1354
+ except JSONDecodeError:
1355
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
1356
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
1357
+
1358
+ async def execute_bundle(
1359
+ self,
1360
+ fhir_provider_id: str,
1361
+ *,
1362
+ entry: typing.Sequence[FhirBundleEntryItem],
1363
+ phenoml_on_behalf_of: typing.Optional[str] = None,
1364
+ phenoml_fhir_provider: typing.Optional[str] = None,
1365
+ total: typing.Optional[int] = OMIT,
1366
+ request_options: typing.Optional[RequestOptions] = None,
1367
+ ) -> AsyncHttpResponse[FhirBundle]:
1368
+ """
1369
+ Executes a FHIR Bundle transaction or batch operation on the specified provider. This allows multiple FHIR resources to be processed in a single request.
1370
+
1371
+ The request body should contain a valid FHIR Bundle resource with transaction or batch type.
1372
+
1373
+ The request is proxied to the configured FHIR server with appropriate authentication headers.
1374
+
1375
+ Parameters
1376
+ ----------
1377
+ fhir_provider_id : str
1378
+ The ID of the FHIR provider to use. Can be either:
1379
+ - A UUID representing the provider ID
1380
+ - A provider name (legacy support - will just use the most recently updated provider with this name)
1381
+
1382
+ entry : typing.Sequence[FhirBundleEntryItem]
1383
+ Array of bundle entries containing resources or operation results
1384
+
1385
+ phenoml_on_behalf_of : typing.Optional[str]
1386
+ Optional header for on-behalf-of authentication. Used when making requests on behalf of another user or entity.
1387
+ Must be in the format: Patient/{uuid} or Practitioner/{uuid}
1388
+
1389
+ phenoml_fhir_provider : typing.Optional[str]
1390
+ Optional header for FHIR provider authentication. Contains credentials in the format {fhir_provider_id}:{oauth2_token}.
1391
+ Multiple FHIR provider integrations can be provided as comma-separated values.
1392
+
1393
+ total : typing.Optional[int]
1394
+ Total number of resources that match the search criteria.
1395
+ Optional field as not all FHIR servers include it (e.g., Medplum).
1396
+
1397
+ request_options : typing.Optional[RequestOptions]
1398
+ Request-specific configuration.
1399
+
1400
+ Returns
1401
+ -------
1402
+ AsyncHttpResponse[FhirBundle]
1403
+ Bundle executed successfully
1404
+ """
1405
+ _response = await self._client_wrapper.httpx_client.request(
1406
+ f"fhir-provider/{jsonable_encoder(fhir_provider_id)}/fhir",
1407
+ method="POST",
1408
+ json={
1409
+ "total": total,
1410
+ "entry": convert_and_respect_annotation_metadata(
1411
+ object_=entry, annotation=typing.Sequence[FhirBundleEntryItem], direction="write"
1412
+ ),
1413
+ "resourceType": "Bundle",
1414
+ },
1415
+ headers={
1416
+ "content-type": "application/fhir+json",
1417
+ "X-Phenoml-On-Behalf-Of": str(phenoml_on_behalf_of) if phenoml_on_behalf_of is not None else None,
1418
+ "X-Phenoml-Fhir-Provider": str(phenoml_fhir_provider) if phenoml_fhir_provider is not None else None,
1419
+ },
1420
+ request_options=request_options,
1421
+ omit=OMIT,
1422
+ )
1423
+ try:
1424
+ if 200 <= _response.status_code < 300:
1425
+ _data = typing.cast(
1426
+ FhirBundle,
1427
+ parse_obj_as(
1428
+ type_=FhirBundle, # type: ignore
1429
+ object_=_response.json(),
1430
+ ),
1431
+ )
1432
+ return AsyncHttpResponse(response=_response, data=_data)
1433
+ if _response.status_code == 400:
1434
+ raise BadRequestError(
1435
+ headers=dict(_response.headers),
1436
+ body=typing.cast(
1437
+ typing.Optional[typing.Any],
1438
+ parse_obj_as(
1439
+ type_=typing.Optional[typing.Any], # type: ignore
1440
+ object_=_response.json(),
1441
+ ),
1442
+ ),
1443
+ )
1444
+ if _response.status_code == 401:
1445
+ raise UnauthorizedError(
1446
+ headers=dict(_response.headers),
1447
+ body=typing.cast(
1448
+ typing.Optional[typing.Any],
1449
+ parse_obj_as(
1450
+ type_=typing.Optional[typing.Any], # type: ignore
1451
+ object_=_response.json(),
1452
+ ),
1453
+ ),
1454
+ )
1455
+ if _response.status_code == 500:
1456
+ raise InternalServerError(
1457
+ headers=dict(_response.headers),
1458
+ body=typing.cast(
1459
+ typing.Optional[typing.Any],
1460
+ parse_obj_as(
1461
+ type_=typing.Optional[typing.Any], # type: ignore
1462
+ object_=_response.json(),
1463
+ ),
1464
+ ),
1465
+ )
1466
+ _response_json = _response.json()
1467
+ except JSONDecodeError:
1468
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
1469
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)