retab 0.0.42__py3-none-any.whl → 0.0.44__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 (76) hide show
  1. retab/__init__.py +2 -1
  2. retab/client.py +26 -51
  3. retab/generate_types.py +180 -0
  4. retab/resources/consensus/client.py +1 -1
  5. retab/resources/consensus/responses.py +1 -1
  6. retab/resources/deployments/__init__.py +3 -0
  7. retab/resources/deployments/automations/__init__.py +9 -0
  8. retab/resources/deployments/automations/client.py +244 -0
  9. retab/resources/deployments/automations/endpoints.py +290 -0
  10. retab/resources/deployments/automations/links.py +303 -0
  11. retab/resources/deployments/automations/logs.py +222 -0
  12. retab/resources/deployments/automations/mailboxes.py +423 -0
  13. retab/resources/deployments/automations/outlook.py +377 -0
  14. retab/resources/deployments/automations/tests.py +161 -0
  15. retab/resources/deployments/client.py +148 -0
  16. retab/resources/documents/client.py +94 -68
  17. retab/resources/documents/extractions.py +55 -46
  18. retab/resources/evaluations/__init__.py +2 -2
  19. retab/resources/evaluations/client.py +61 -77
  20. retab/resources/evaluations/documents.py +48 -37
  21. retab/resources/evaluations/iterations.py +58 -40
  22. retab/resources/jsonlUtils.py +3 -4
  23. retab/resources/processors/automations/endpoints.py +49 -39
  24. retab/resources/processors/automations/links.py +52 -43
  25. retab/resources/processors/automations/mailboxes.py +74 -59
  26. retab/resources/processors/automations/outlook.py +104 -82
  27. retab/resources/processors/client.py +35 -30
  28. retab/resources/projects/__init__.py +3 -0
  29. retab/resources/projects/client.py +285 -0
  30. retab/resources/projects/documents.py +244 -0
  31. retab/resources/projects/iterations.py +470 -0
  32. retab/resources/usage.py +2 -0
  33. retab/types/ai_models.py +2 -1
  34. retab/types/deprecated_evals.py +195 -0
  35. retab/types/evaluations/__init__.py +5 -2
  36. retab/types/evaluations/iterations.py +9 -43
  37. retab/types/evaluations/model.py +19 -24
  38. retab/types/extractions.py +1 -0
  39. retab/types/jobs/base.py +1 -1
  40. retab/types/jobs/evaluation.py +1 -1
  41. retab/types/logs.py +5 -6
  42. retab/types/mime.py +1 -10
  43. retab/types/projects/__init__.py +34 -0
  44. retab/types/projects/documents.py +30 -0
  45. retab/types/projects/iterations.py +78 -0
  46. retab/types/projects/model.py +68 -0
  47. retab/types/schemas/enhance.py +22 -5
  48. retab/types/schemas/evaluate.py +2 -2
  49. retab/types/schemas/object.py +27 -25
  50. retab/types/standards.py +2 -2
  51. retab/utils/__init__.py +3 -0
  52. retab/utils/ai_models.py +127 -12
  53. retab/utils/hashing.py +24 -0
  54. retab/utils/json_schema.py +1 -26
  55. retab/utils/mime.py +0 -17
  56. retab/utils/usage/usage.py +0 -1
  57. {retab-0.0.42.dist-info → retab-0.0.44.dist-info}/METADATA +4 -6
  58. {retab-0.0.42.dist-info → retab-0.0.44.dist-info}/RECORD +60 -55
  59. retab/_utils/__init__.py +0 -0
  60. retab/_utils/_model_cards/anthropic.yaml +0 -59
  61. retab/_utils/_model_cards/auto.yaml +0 -43
  62. retab/_utils/_model_cards/gemini.yaml +0 -117
  63. retab/_utils/_model_cards/openai.yaml +0 -301
  64. retab/_utils/_model_cards/xai.yaml +0 -28
  65. retab/_utils/ai_models.py +0 -138
  66. retab/_utils/benchmarking.py +0 -484
  67. retab/_utils/chat.py +0 -327
  68. retab/_utils/display.py +0 -440
  69. retab/_utils/json_schema.py +0 -2156
  70. retab/_utils/mime.py +0 -165
  71. retab/_utils/responses.py +0 -169
  72. retab/_utils/stream_context_managers.py +0 -52
  73. retab/_utils/usage/__init__.py +0 -0
  74. retab/_utils/usage/usage.py +0 -301
  75. {retab-0.0.42.dist-info → retab-0.0.44.dist-info}/WHEEL +0 -0
  76. {retab-0.0.42.dist-info → retab-0.0.44.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,290 @@
1
+ from typing import Any, Literal, Optional
2
+
3
+ from ....types.standards import FieldUnset
4
+
5
+ from ...._resource import AsyncAPIResource, SyncAPIResource
6
+ from ....utils.ai_models import assert_valid_model_extraction
7
+ from ....types.automations.endpoints import Endpoint, ListEndpoints, UpdateEndpointRequest
8
+ from ....types.standards import PreparedRequest
9
+
10
+
11
+ class EndpointsMixin:
12
+ def prepare_create(
13
+ self,
14
+ processor_id: str,
15
+ name: str,
16
+ webhook_url: str,
17
+ model: str = "gpt-4o-mini",
18
+ webhook_headers: dict[str, str] = FieldUnset,
19
+ need_validation: bool = FieldUnset,
20
+ ) -> PreparedRequest:
21
+ assert_valid_model_extraction(model)
22
+
23
+ endpoint_dict: dict[str, Any] = {
24
+ 'processor_id': processor_id,
25
+ 'name': name,
26
+ 'webhook_url': webhook_url,
27
+ }
28
+ if webhook_headers is not FieldUnset:
29
+ endpoint_dict['webhook_headers'] = webhook_headers
30
+ if need_validation is not FieldUnset:
31
+ endpoint_dict['need_validation'] = need_validation
32
+
33
+ request = Endpoint(**endpoint_dict)
34
+ return PreparedRequest(method="POST", url="/v1/processors/automations/endpoints", data=request.model_dump(mode="json", exclude_unset=True))
35
+
36
+ def prepare_list(
37
+ self,
38
+ processor_id: str,
39
+ before: Optional[str] = None,
40
+ after: Optional[str] = None,
41
+ limit: Optional[int] = 10,
42
+ order: Optional[Literal["asc", "desc"]] = "desc",
43
+ # Filtering parameters
44
+ name: Optional[str] = None,
45
+ webhook_url: Optional[str] = None,
46
+ ) -> PreparedRequest:
47
+ params = {
48
+ "processor_id": processor_id,
49
+ "before": before,
50
+ "after": after,
51
+ "limit": limit,
52
+ "order": order,
53
+ "name": name,
54
+ "webhook_url": webhook_url,
55
+ }
56
+ # Remove None values
57
+ params = {k: v for k, v in params.items() if v is not None}
58
+
59
+ return PreparedRequest(method="GET", url="/v1/processors/automations/endpoints", params=params)
60
+
61
+ def prepare_get(self, endpoint_id: str) -> PreparedRequest:
62
+ """Get a specific endpoint configuration.
63
+
64
+ Args:
65
+ endpoint_id: ID of the endpoint
66
+
67
+ Returns:
68
+ Endpoint: The endpoint configuration
69
+ """
70
+ return PreparedRequest(method="GET", url=f"/v1/processors/automations/endpoints/{endpoint_id}")
71
+
72
+ def prepare_update(
73
+ self,
74
+ endpoint_id: str,
75
+ name: str = FieldUnset,
76
+ default_language: str = FieldUnset,
77
+ webhook_url: str = FieldUnset,
78
+ webhook_headers: dict[str, str] = FieldUnset,
79
+ need_validation: bool = FieldUnset,
80
+ ) -> PreparedRequest:
81
+ update_dict: dict[str, Any] = {}
82
+ if name is not FieldUnset:
83
+ update_dict['name'] = name
84
+ if default_language is not FieldUnset:
85
+ update_dict['default_language'] = default_language
86
+ if webhook_url is not FieldUnset:
87
+ update_dict['webhook_url'] = webhook_url
88
+ if webhook_headers is not FieldUnset:
89
+ update_dict['webhook_headers'] = webhook_headers
90
+ if need_validation is not FieldUnset:
91
+ update_dict['need_validation'] = need_validation
92
+
93
+ request = UpdateEndpointRequest(**update_dict)
94
+ return PreparedRequest(method="PUT", url=f"/v1/processors/automations/endpoints/{endpoint_id}", data=request.model_dump(mode="json", exclude_unset=True))
95
+
96
+ def prepare_delete(self, endpoint_id: str) -> PreparedRequest:
97
+ return PreparedRequest(method="DELETE", url=f"/v1/processors/automations/endpoints/{endpoint_id}")
98
+
99
+
100
+ class Endpoints(SyncAPIResource, EndpointsMixin):
101
+ """Endpoints API wrapper for managing endpoint configurations"""
102
+
103
+ def create(
104
+ self,
105
+ processor_id: str,
106
+ name: str,
107
+ webhook_url: str,
108
+ webhook_headers: dict[str, str] = FieldUnset,
109
+ need_validation: bool = FieldUnset,
110
+ ) -> Endpoint:
111
+ """Create a new endpoint configuration.
112
+
113
+ Args:
114
+ name: Name of the endpoint
115
+ webhook_url: Webhook endpoint URL
116
+ json_schema: JSON schema for the endpoint
117
+ webhook_headers: Optional HTTP headers for webhook requests
118
+ image_resolution_dpi: Optional image resolution DPI
119
+ browser_canvas: Optional browser canvas size
120
+ modality: Processing modality (currently only "native" supported)
121
+ model: AI model to use for processing
122
+ temperature: Model temperature setting
123
+ reasoning_effort: The effort level for the model to reason about the input data.
124
+ Returns:
125
+ Endpoint: The created endpoint configuration
126
+ """
127
+ request = self.prepare_create(
128
+ processor_id=processor_id,
129
+ name=name,
130
+ webhook_url=webhook_url,
131
+ webhook_headers=webhook_headers,
132
+ need_validation=need_validation,
133
+ )
134
+ response = self._client._prepared_request(request)
135
+ print(f"Endpoint Created. Url: https://www.retab.com/dashboard/processors/automations/{response['id']}")
136
+ return Endpoint.model_validate(response)
137
+
138
+ def list(
139
+ self,
140
+ processor_id: str,
141
+ before: Optional[str] = None,
142
+ after: Optional[str] = None,
143
+ limit: Optional[int] = 10,
144
+ order: Optional[Literal["asc", "desc"]] = "desc",
145
+ name: Optional[str] = None,
146
+ webhook_url: Optional[str] = None,
147
+ ) -> ListEndpoints:
148
+ """List endpoint configurations with pagination support.
149
+
150
+ Args:
151
+ before: Optional cursor for pagination before a specific endpoint ID
152
+ after: Optional cursor for pagination after a specific endpoint ID
153
+ limit: Optional limit on number of results (max 100)
154
+ order: Optional sort order ("asc" or "desc")
155
+ name: Optional filter by endpoint name
156
+ webhook_url: Optional filter by webhook URL
157
+
158
+ Returns:
159
+ ListEndpoints: Paginated list of endpoint configurations with metadata
160
+ """
161
+ request = self.prepare_list(processor_id, before, after, limit, order, name, webhook_url)
162
+ response = self._client._prepared_request(request)
163
+ return ListEndpoints.model_validate(response)
164
+
165
+ def get(self, endpoint_id: str) -> Endpoint:
166
+ """Get a specific endpoint configuration.
167
+
168
+ Args:
169
+ endpoint_id: ID of the endpoint
170
+
171
+ Returns:
172
+ Endpoint: The endpoint configuration
173
+ """
174
+ request = self.prepare_get(endpoint_id)
175
+ response = self._client._prepared_request(request)
176
+ return Endpoint.model_validate(response)
177
+
178
+ def update(
179
+ self,
180
+ endpoint_id: str,
181
+ name: str = FieldUnset,
182
+ default_language: str = FieldUnset,
183
+ webhook_url: str = FieldUnset,
184
+ webhook_headers: dict[str, str] = FieldUnset,
185
+ need_validation: bool = FieldUnset,
186
+ ) -> Endpoint:
187
+ """Update an endpoint configuration.
188
+
189
+ Args:
190
+ id: ID of the endpoint to update
191
+ name: New name for the endpoint
192
+ webhook_url: New webhook URL
193
+ webhook_headers: New webhook headers
194
+ json_schema: New JSON schema for the endpoint
195
+ image_resolution_dpi: New image resolution DPI
196
+ browser_canvas: New browser canvas size
197
+ modality: New processing modality
198
+ model: New AI model
199
+ temperature: New temperature setting
200
+ reasoning_effort: The effort level for the model to reason about the input data.
201
+ Returns:
202
+ Endpoint: The updated endpoint configuration
203
+ """
204
+ request = self.prepare_update(
205
+ endpoint_id=endpoint_id,
206
+ name=name,
207
+ default_language=default_language,
208
+ webhook_url=webhook_url,
209
+ webhook_headers=webhook_headers,
210
+ need_validation=need_validation,
211
+ )
212
+ response = self._client._prepared_request(request)
213
+ return Endpoint.model_validate(response)
214
+
215
+ def delete(self, endpoint_id: str) -> None:
216
+ """Delete an endpoint configuration.
217
+
218
+ Args:
219
+ id: ID of the endpoint to delete
220
+ """
221
+ request = self.prepare_delete(endpoint_id)
222
+ self._client._prepared_request(request)
223
+ print(f"Endpoint Deleted. ID: {endpoint_id}")
224
+
225
+
226
+ class AsyncEndpoints(AsyncAPIResource, EndpointsMixin):
227
+ """Async Endpoints API wrapper for managing endpoint configurations"""
228
+
229
+ async def create(
230
+ self,
231
+ processor_id: str,
232
+ name: str,
233
+ webhook_url: str,
234
+ webhook_headers: dict[str, str] = FieldUnset,
235
+ need_validation: bool = FieldUnset,
236
+ ) -> Endpoint:
237
+ request = self.prepare_create(
238
+ processor_id=processor_id,
239
+ name=name,
240
+ webhook_url=webhook_url,
241
+ webhook_headers=webhook_headers,
242
+ need_validation=need_validation,
243
+ )
244
+ response = await self._client._prepared_request(request)
245
+ print(f"Endpoint Created. Url: https://www.retab.com/dashboard/processors/automations/{response['id']}")
246
+
247
+ return Endpoint.model_validate(response)
248
+
249
+ async def list(
250
+ self,
251
+ processor_id: str,
252
+ before: Optional[str] = None,
253
+ after: Optional[str] = None,
254
+ limit: Optional[int] = 10,
255
+ order: Optional[Literal["asc", "desc"]] = "desc",
256
+ name: Optional[str] = None,
257
+ webhook_url: Optional[str] = None,
258
+ ) -> ListEndpoints:
259
+ request = self.prepare_list(processor_id, before, after, limit, order, name, webhook_url)
260
+ response = await self._client._prepared_request(request)
261
+ return ListEndpoints.model_validate(response)
262
+
263
+ async def get(self, endpoint_id: str) -> Endpoint:
264
+ request = self.prepare_get(endpoint_id)
265
+ response = await self._client._prepared_request(request)
266
+ return Endpoint.model_validate(response)
267
+
268
+ async def update(
269
+ self,
270
+ endpoint_id: str,
271
+ name: str = FieldUnset,
272
+ default_language: str = FieldUnset,
273
+ webhook_url: str = FieldUnset,
274
+ webhook_headers: dict[str, str] = FieldUnset,
275
+ need_validation: bool = FieldUnset,
276
+ ) -> Endpoint:
277
+ request = self.prepare_update(
278
+ endpoint_id=endpoint_id,
279
+ name=name,
280
+ default_language=default_language,
281
+ webhook_url=webhook_url,
282
+ webhook_headers=webhook_headers,
283
+ need_validation=need_validation,
284
+ )
285
+ response = await self._client._prepared_request(request)
286
+ return Endpoint.model_validate(response)
287
+
288
+ async def delete(self, endpoint_id: str) -> None:
289
+ request = self.prepare_delete(endpoint_id)
290
+ await self._client._prepared_request(request)
@@ -0,0 +1,303 @@
1
+ from typing import Any, Literal, Optional
2
+
3
+ from ...._resource import AsyncAPIResource, SyncAPIResource
4
+ from ....types.automations.links import Link, ListLinks, UpdateLinkRequest
5
+ from ....types.standards import PreparedRequest, FieldUnset
6
+
7
+
8
+ class LinksMixin:
9
+ links_base_url: str = "/v1/processors/automations/links"
10
+
11
+ def prepare_create(
12
+ self,
13
+ processor_id: str,
14
+ name: str,
15
+ webhook_url: str,
16
+ webhook_headers: dict[str, str] = FieldUnset,
17
+ need_validation: bool = FieldUnset,
18
+ password: str | None = FieldUnset,
19
+ ) -> PreparedRequest:
20
+ link_dict: dict[str, Any] = {
21
+ 'processor_id': processor_id,
22
+ 'name': name,
23
+ 'webhook_url': webhook_url,
24
+ }
25
+ if webhook_headers is not FieldUnset:
26
+ link_dict['webhook_headers'] = webhook_headers
27
+ if need_validation is not FieldUnset:
28
+ link_dict['need_validation'] = need_validation
29
+ if password is not FieldUnset:
30
+ link_dict['password'] = password
31
+
32
+ request = Link(**link_dict)
33
+ return PreparedRequest(method="POST", url=self.links_base_url, data=request.model_dump(mode="json", exclude_unset=True))
34
+
35
+ def prepare_list(
36
+ self,
37
+ before: Optional[str] = None,
38
+ after: Optional[str] = None,
39
+ limit: Optional[int] = 10,
40
+ order: Optional[Literal["asc", "desc"]] = "desc",
41
+ # Filtering parameters
42
+ processor_id: Optional[str] = None,
43
+ name: Optional[str] = None,
44
+ ) -> PreparedRequest:
45
+ params = {
46
+ "before": before,
47
+ "after": after,
48
+ "limit": limit,
49
+ "order": order,
50
+ "processor_id": processor_id,
51
+ "name": name,
52
+ }
53
+ # Remove None values
54
+ params = {k: v for k, v in params.items() if v is not None}
55
+
56
+ return PreparedRequest(method="GET", url=self.links_base_url, params=params)
57
+
58
+ def prepare_get(self, link_id: str) -> PreparedRequest:
59
+ """Get a specific extraction link configuration.
60
+
61
+ Args:
62
+ link_id: ID of the extraction link
63
+
64
+ Returns:
65
+ Link: The extraction link configuration
66
+ """
67
+ return PreparedRequest(method="GET", url=f"{self.links_base_url}/{link_id}")
68
+
69
+ def prepare_update(
70
+ self,
71
+ link_id: str,
72
+ name: str = FieldUnset,
73
+ webhook_url: str = FieldUnset,
74
+ webhook_headers: dict[str, str] = FieldUnset,
75
+ need_validation: bool = FieldUnset,
76
+ password: str | None = FieldUnset,
77
+ ) -> PreparedRequest:
78
+ update_dict: dict[str, Any] = {}
79
+ if name is not FieldUnset:
80
+ update_dict['name'] = name
81
+ if webhook_url is not FieldUnset:
82
+ update_dict['webhook_url'] = webhook_url
83
+ if webhook_headers is not FieldUnset:
84
+ update_dict['webhook_headers'] = webhook_headers
85
+ if need_validation is not FieldUnset:
86
+ update_dict['need_validation'] = need_validation
87
+ if password is not FieldUnset:
88
+ update_dict['password'] = password
89
+
90
+ request = UpdateLinkRequest(**update_dict)
91
+ return PreparedRequest(method="PUT", url=f"{self.links_base_url}/{link_id}", data=request.model_dump(mode="json", exclude_unset=True, exclude_defaults=True))
92
+
93
+ def prepare_delete(self, link_id: str) -> PreparedRequest:
94
+ return PreparedRequest(method="DELETE", url=f"{self.links_base_url}/{link_id}", raise_for_status=True)
95
+
96
+
97
+ class Links(SyncAPIResource, LinksMixin):
98
+ """Extraction Link API wrapper for managing extraction link configurations"""
99
+
100
+ def __init__(self, client: Any) -> None:
101
+ super().__init__(client=client)
102
+
103
+ def create(
104
+ self,
105
+ processor_id: str,
106
+ name: str,
107
+ webhook_url: str,
108
+ webhook_headers: dict[str, str] = FieldUnset,
109
+ need_validation: bool = FieldUnset,
110
+ password: str | None = FieldUnset,
111
+ ) -> Link:
112
+ """Create a new extraction link configuration.
113
+
114
+ Args:
115
+ name: Name of the extraction link
116
+ json_schema: JSON schema to validate extracted data
117
+ webhook_url: Webhook endpoint for forwarding processed files
118
+ webhook_headers: Optional HTTP headers for webhook requests
119
+ password: Optional password for protected links
120
+ image_resolution_dpi: Optional image resolution DPI
121
+ browser_canvas: Optional browser canvas
122
+ modality: Processing modality (currently only "native" supported)
123
+ model: AI model to use for processing
124
+ temperature: Model temperature setting
125
+ reasoning_effort: The effort level for the model to reason about the input data.
126
+ Returns:
127
+ Link: The created extraction link configuration
128
+ """
129
+
130
+ request = self.prepare_create(
131
+ processor_id=processor_id,
132
+ name=name,
133
+ webhook_url=webhook_url,
134
+ webhook_headers=webhook_headers,
135
+ need_validation=need_validation,
136
+ password=password,
137
+ )
138
+ response = self._client._prepared_request(request)
139
+
140
+ print(f"Link Created. Url: https://www.retab.com/dashboard/processors/automations/{response['id']}")
141
+ return Link.model_validate(response)
142
+
143
+ def list(
144
+ self,
145
+ before: Optional[str] = None,
146
+ after: Optional[str] = None,
147
+ limit: Optional[int] = 10,
148
+ order: Optional[Literal["asc", "desc"]] = "desc",
149
+ # Filtering parameters
150
+ processor_id: Optional[str] = None,
151
+ name: Optional[str] = None,
152
+ ) -> ListLinks:
153
+ """List extraction link configurations with pagination support.
154
+
155
+ Args:
156
+ before: Optional cursor for pagination before a specific link ID
157
+ after: Optional cursor for pagination after a specific link ID
158
+ limit: Optional limit on number of results (max 100)
159
+ order: Optional sort order ("asc" or "desc")
160
+ processor_id: Optional filter by processor ID
161
+ name: Optional filter by link name
162
+
163
+ Returns:
164
+ ListLinks: Paginated list of extraction link configurations with metadata
165
+ """
166
+ request = self.prepare_list(before=before, after=after, limit=limit, order=order, processor_id=processor_id, name=name)
167
+ response = self._client._prepared_request(request)
168
+ return ListLinks.model_validate(response)
169
+
170
+ def get(self, link_id: str) -> Link:
171
+ """Get a specific extraction link configuration.
172
+
173
+ Args:
174
+ link_id: ID of the extraction link
175
+
176
+ Returns:
177
+ Link: The extraction link configuration
178
+ """
179
+ request = self.prepare_get(link_id)
180
+ response = self._client._prepared_request(request)
181
+ return Link.model_validate(response)
182
+
183
+ def update(
184
+ self,
185
+ link_id: str,
186
+ name: str = FieldUnset,
187
+ webhook_url: str = FieldUnset,
188
+ webhook_headers: dict[str, str] = FieldUnset,
189
+ password: str | None = FieldUnset,
190
+ need_validation: bool = FieldUnset,
191
+ ) -> Link:
192
+ """Update an extraction link configuration.
193
+
194
+ Args:
195
+ link_id: ID of the extraction link to update
196
+ name: New name for the link
197
+ webhook_url: New webhook endpoint URL
198
+ webhook_headers: New webhook headers
199
+ password: New password for protected links
200
+ image_resolution_dpi: New image resolution DPI
201
+ browser_canvas: New browser canvas
202
+ modality: New processing modality
203
+ model: New AI model
204
+ temperature: New temperature setting
205
+ reasoning_effort: The effort level for the model to reason about the input data.
206
+ json_schema: New JSON schema
207
+
208
+ Returns:
209
+ Link: The updated extraction link configuration
210
+ """
211
+
212
+ request = self.prepare_update(
213
+ link_id=link_id,
214
+ name=name,
215
+ webhook_url=webhook_url,
216
+ webhook_headers=webhook_headers,
217
+ password=password,
218
+ need_validation=need_validation,
219
+ )
220
+ response = self._client._prepared_request(request)
221
+ return Link.model_validate(response)
222
+
223
+ def delete(self, link_id: str) -> None:
224
+ """Delete an extraction link configuration.
225
+
226
+ Args:
227
+ link_id: ID of the extraction link to delete
228
+
229
+ Returns:
230
+ Dict[str, str]: Response message confirming deletion
231
+ """
232
+ request = self.prepare_delete(link_id)
233
+ self._client._prepared_request(request)
234
+
235
+
236
+ class AsyncLinks(AsyncAPIResource, LinksMixin):
237
+ """Async Extraction Link API wrapper for managing extraction link configurations"""
238
+
239
+ def __init__(self, client: Any) -> None:
240
+ super().__init__(client=client)
241
+
242
+ async def create(
243
+ self,
244
+ processor_id: str,
245
+ name: str,
246
+ webhook_url: str,
247
+ webhook_headers: dict[str, str] = FieldUnset,
248
+ need_validation: bool = FieldUnset,
249
+ password: str | None = FieldUnset,
250
+ ) -> Link:
251
+ request = self.prepare_create(
252
+ processor_id=processor_id,
253
+ name=name,
254
+ webhook_url=webhook_url,
255
+ webhook_headers=webhook_headers,
256
+ need_validation=need_validation,
257
+ password=password,
258
+ )
259
+ response = await self._client._prepared_request(request)
260
+ print(f"Link Created. Url: https://www.retab.com/dashboard/processors/automations/{response['id']}")
261
+ return Link.model_validate(response)
262
+
263
+ async def list(
264
+ self,
265
+ before: Optional[str] = None,
266
+ after: Optional[str] = None,
267
+ limit: Optional[int] = 10,
268
+ order: Optional[Literal["asc", "desc"]] = "desc",
269
+ processor_id: Optional[str] = None,
270
+ name: Optional[str] = None,
271
+ ) -> ListLinks:
272
+ request = self.prepare_list(before=before, after=after, limit=limit, order=order, processor_id=processor_id, name=name)
273
+ response = await self._client._prepared_request(request)
274
+ return ListLinks.model_validate(response)
275
+
276
+ async def get(self, link_id: str) -> Link:
277
+ request = self.prepare_get(link_id)
278
+ response = await self._client._prepared_request(request)
279
+ return Link.model_validate(response)
280
+
281
+ async def update(
282
+ self,
283
+ link_id: str,
284
+ name: str = FieldUnset,
285
+ webhook_url: str = FieldUnset,
286
+ webhook_headers: dict[str, str] = FieldUnset,
287
+ password: str | None = FieldUnset,
288
+ need_validation: bool = FieldUnset,
289
+ ) -> Link:
290
+ request = self.prepare_update(
291
+ link_id=link_id,
292
+ name=name,
293
+ webhook_url=webhook_url,
294
+ webhook_headers=webhook_headers,
295
+ password=password,
296
+ need_validation=need_validation,
297
+ )
298
+ response = await self._client._prepared_request(request)
299
+ return Link.model_validate(response)
300
+
301
+ async def delete(self, link_id: str) -> None:
302
+ request = self.prepare_delete(link_id)
303
+ await self._client._prepared_request(request)