airweave-sdk 0.8.64__py3-none-any.whl → 0.8.66__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.
- airweave/__init__.py +44 -38
- airweave/client.py +19 -16
- airweave/collections/__init__.py +3 -6
- airweave/collections/client.py +273 -113
- airweave/collections/raw_client.py +633 -94
- airweave/collections/types/__init__.py +2 -4
- airweave/core/client_wrapper.py +4 -30
- airweave/errors/__init__.py +10 -2
- airweave/errors/conflict_error.py +11 -0
- airweave/errors/not_found_error.py +11 -0
- airweave/errors/too_many_requests_error.py +11 -0
- airweave/errors/unprocessable_entity_error.py +1 -2
- airweave/{types/message_status.py → events/__init__.py} +2 -1
- airweave/events/client.py +919 -0
- airweave/events/raw_client.py +1435 -0
- airweave/source_connections/client.py +210 -162
- airweave/source_connections/raw_client.py +574 -137
- airweave/sources/client.py +42 -18
- airweave/sources/raw_client.py +118 -17
- airweave/types/__init__.py +33 -33
- airweave/types/{create_subscription_request.py → conflict_error_response.py} +9 -6
- airweave/types/delivery_attempt.py +61 -0
- airweave/types/event_message.py +55 -0
- airweave/types/event_message_with_attempts.py +59 -0
- airweave/types/{endpoint_secret_out.py → not_found_error_response.py} +9 -2
- airweave/types/{subscription_with_attempts_out.py → rate_limit_error_response.py} +9 -6
- airweave/types/recovery_task.py +35 -0
- airweave/types/search_request.py +13 -10
- airweave/types/search_response.py +6 -3
- airweave/types/source_connection.py +73 -18
- airweave/types/source_connection_job.py +65 -15
- airweave/types/source_connection_list_item.py +45 -10
- airweave/types/sync_event_payload.py +72 -0
- airweave/types/{patch_subscription_request.py → validation_error_detail.py} +16 -5
- airweave/types/validation_error_response.py +30 -0
- airweave/types/webhook_subscription.py +68 -0
- {airweave_sdk-0.8.64.dist-info → airweave_sdk-0.8.66.dist-info}/METADATA +1 -5
- {airweave_sdk-0.8.64.dist-info → airweave_sdk-0.8.66.dist-info}/RECORD +39 -34
- airweave/collections/types/search_collections_readable_id_search_post_response.py +0 -8
- airweave/types/collection_update.py +0 -35
- airweave/types/endpoint_out.py +0 -35
- airweave/types/message_attempt_out.py +0 -37
- airweave/types/message_attempt_trigger_type.py +0 -3
- airweave/types/message_out.py +0 -29
- airweave/types/message_status_text.py +0 -5
- {airweave_sdk-0.8.64.dist-info → airweave_sdk-0.8.66.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,1435 @@
|
|
|
1
|
+
# This file was auto-generated by Fern from our API Definition.
|
|
2
|
+
|
|
3
|
+
import datetime as dt
|
|
4
|
+
import typing
|
|
5
|
+
from json.decoder import JSONDecodeError
|
|
6
|
+
|
|
7
|
+
from ..core.api_error import ApiError
|
|
8
|
+
from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
|
|
9
|
+
from ..core.http_response import AsyncHttpResponse, HttpResponse
|
|
10
|
+
from ..core.jsonable_encoder import jsonable_encoder
|
|
11
|
+
from ..core.pydantic_utilities import parse_obj_as
|
|
12
|
+
from ..core.request_options import RequestOptions
|
|
13
|
+
from ..errors.not_found_error import NotFoundError
|
|
14
|
+
from ..errors.too_many_requests_error import TooManyRequestsError
|
|
15
|
+
from ..errors.unprocessable_entity_error import UnprocessableEntityError
|
|
16
|
+
from ..types.event_message import EventMessage
|
|
17
|
+
from ..types.event_message_with_attempts import EventMessageWithAttempts
|
|
18
|
+
from ..types.event_type import EventType
|
|
19
|
+
from ..types.not_found_error_response import NotFoundErrorResponse
|
|
20
|
+
from ..types.rate_limit_error_response import RateLimitErrorResponse
|
|
21
|
+
from ..types.recovery_task import RecoveryTask
|
|
22
|
+
from ..types.webhook_subscription import WebhookSubscription
|
|
23
|
+
|
|
24
|
+
# this is used as the default value for optional parameters
|
|
25
|
+
OMIT = typing.cast(typing.Any, ...)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class RawEventsClient:
|
|
29
|
+
def __init__(self, *, client_wrapper: SyncClientWrapper):
|
|
30
|
+
self._client_wrapper = client_wrapper
|
|
31
|
+
|
|
32
|
+
def get_messages(
|
|
33
|
+
self,
|
|
34
|
+
*,
|
|
35
|
+
event_types: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
|
|
36
|
+
request_options: typing.Optional[RequestOptions] = None,
|
|
37
|
+
) -> HttpResponse[typing.List[EventMessage]]:
|
|
38
|
+
"""
|
|
39
|
+
Retrieve all event messages for your organization.
|
|
40
|
+
|
|
41
|
+
Event messages represent webhook payloads that were sent (or attempted to be sent)
|
|
42
|
+
to your subscribed endpoints. Each message contains the event type, payload data,
|
|
43
|
+
and delivery status information.
|
|
44
|
+
|
|
45
|
+
Use the `event_types` query parameter to filter messages by specific event types,
|
|
46
|
+
such as `sync.completed` or `sync.failed`.
|
|
47
|
+
|
|
48
|
+
Parameters
|
|
49
|
+
----------
|
|
50
|
+
event_types : typing.Optional[typing.Union[str, typing.Sequence[str]]]
|
|
51
|
+
Filter messages by event type(s). Accepts multiple values, e.g., `?event_types=sync.completed&event_types=sync.failed`.
|
|
52
|
+
|
|
53
|
+
request_options : typing.Optional[RequestOptions]
|
|
54
|
+
Request-specific configuration.
|
|
55
|
+
|
|
56
|
+
Returns
|
|
57
|
+
-------
|
|
58
|
+
HttpResponse[typing.List[EventMessage]]
|
|
59
|
+
List of event messages
|
|
60
|
+
"""
|
|
61
|
+
_response = self._client_wrapper.httpx_client.request(
|
|
62
|
+
"events/messages",
|
|
63
|
+
method="GET",
|
|
64
|
+
params={
|
|
65
|
+
"event_types": event_types,
|
|
66
|
+
},
|
|
67
|
+
request_options=request_options,
|
|
68
|
+
)
|
|
69
|
+
try:
|
|
70
|
+
if 200 <= _response.status_code < 300:
|
|
71
|
+
_data = typing.cast(
|
|
72
|
+
typing.List[EventMessage],
|
|
73
|
+
parse_obj_as(
|
|
74
|
+
type_=typing.List[EventMessage], # type: ignore
|
|
75
|
+
object_=_response.json(),
|
|
76
|
+
),
|
|
77
|
+
)
|
|
78
|
+
return HttpResponse(response=_response, data=_data)
|
|
79
|
+
if _response.status_code == 422:
|
|
80
|
+
raise UnprocessableEntityError(
|
|
81
|
+
headers=dict(_response.headers),
|
|
82
|
+
body=typing.cast(
|
|
83
|
+
typing.Optional[typing.Any],
|
|
84
|
+
parse_obj_as(
|
|
85
|
+
type_=typing.Optional[typing.Any], # type: ignore
|
|
86
|
+
object_=_response.json(),
|
|
87
|
+
),
|
|
88
|
+
),
|
|
89
|
+
)
|
|
90
|
+
if _response.status_code == 429:
|
|
91
|
+
raise TooManyRequestsError(
|
|
92
|
+
headers=dict(_response.headers),
|
|
93
|
+
body=typing.cast(
|
|
94
|
+
RateLimitErrorResponse,
|
|
95
|
+
parse_obj_as(
|
|
96
|
+
type_=RateLimitErrorResponse, # type: ignore
|
|
97
|
+
object_=_response.json(),
|
|
98
|
+
),
|
|
99
|
+
),
|
|
100
|
+
)
|
|
101
|
+
_response_json = _response.json()
|
|
102
|
+
except JSONDecodeError:
|
|
103
|
+
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
|
|
104
|
+
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
|
|
105
|
+
|
|
106
|
+
def get_message(
|
|
107
|
+
self,
|
|
108
|
+
message_id: str,
|
|
109
|
+
*,
|
|
110
|
+
include_attempts: typing.Optional[bool] = None,
|
|
111
|
+
request_options: typing.Optional[RequestOptions] = None,
|
|
112
|
+
) -> HttpResponse[EventMessageWithAttempts]:
|
|
113
|
+
"""
|
|
114
|
+
Retrieve a specific event message by its ID.
|
|
115
|
+
|
|
116
|
+
Returns the full message details including the event type, payload data,
|
|
117
|
+
timestamp, and delivery channel information. Use this to inspect the
|
|
118
|
+
exact payload that was sent to your webhook endpoints.
|
|
119
|
+
|
|
120
|
+
Use `include_attempts=true` to also retrieve delivery attempts for this message,
|
|
121
|
+
which include HTTP response codes, response bodies, and timestamps for debugging
|
|
122
|
+
delivery failures.
|
|
123
|
+
|
|
124
|
+
Parameters
|
|
125
|
+
----------
|
|
126
|
+
message_id : str
|
|
127
|
+
The unique identifier of the message to retrieve (UUID).
|
|
128
|
+
|
|
129
|
+
include_attempts : typing.Optional[bool]
|
|
130
|
+
Include delivery attempts for this message. Each attempt includes the HTTP response code, response body, and timestamp.
|
|
131
|
+
|
|
132
|
+
request_options : typing.Optional[RequestOptions]
|
|
133
|
+
Request-specific configuration.
|
|
134
|
+
|
|
135
|
+
Returns
|
|
136
|
+
-------
|
|
137
|
+
HttpResponse[EventMessageWithAttempts]
|
|
138
|
+
Event message details
|
|
139
|
+
"""
|
|
140
|
+
_response = self._client_wrapper.httpx_client.request(
|
|
141
|
+
f"events/messages/{jsonable_encoder(message_id)}",
|
|
142
|
+
method="GET",
|
|
143
|
+
params={
|
|
144
|
+
"include_attempts": include_attempts,
|
|
145
|
+
},
|
|
146
|
+
request_options=request_options,
|
|
147
|
+
)
|
|
148
|
+
try:
|
|
149
|
+
if 200 <= _response.status_code < 300:
|
|
150
|
+
_data = typing.cast(
|
|
151
|
+
EventMessageWithAttempts,
|
|
152
|
+
parse_obj_as(
|
|
153
|
+
type_=EventMessageWithAttempts, # type: ignore
|
|
154
|
+
object_=_response.json(),
|
|
155
|
+
),
|
|
156
|
+
)
|
|
157
|
+
return HttpResponse(response=_response, data=_data)
|
|
158
|
+
if _response.status_code == 404:
|
|
159
|
+
raise NotFoundError(
|
|
160
|
+
headers=dict(_response.headers),
|
|
161
|
+
body=typing.cast(
|
|
162
|
+
NotFoundErrorResponse,
|
|
163
|
+
parse_obj_as(
|
|
164
|
+
type_=NotFoundErrorResponse, # type: ignore
|
|
165
|
+
object_=_response.json(),
|
|
166
|
+
),
|
|
167
|
+
),
|
|
168
|
+
)
|
|
169
|
+
if _response.status_code == 422:
|
|
170
|
+
raise UnprocessableEntityError(
|
|
171
|
+
headers=dict(_response.headers),
|
|
172
|
+
body=typing.cast(
|
|
173
|
+
typing.Optional[typing.Any],
|
|
174
|
+
parse_obj_as(
|
|
175
|
+
type_=typing.Optional[typing.Any], # type: ignore
|
|
176
|
+
object_=_response.json(),
|
|
177
|
+
),
|
|
178
|
+
),
|
|
179
|
+
)
|
|
180
|
+
if _response.status_code == 429:
|
|
181
|
+
raise TooManyRequestsError(
|
|
182
|
+
headers=dict(_response.headers),
|
|
183
|
+
body=typing.cast(
|
|
184
|
+
RateLimitErrorResponse,
|
|
185
|
+
parse_obj_as(
|
|
186
|
+
type_=RateLimitErrorResponse, # type: ignore
|
|
187
|
+
object_=_response.json(),
|
|
188
|
+
),
|
|
189
|
+
),
|
|
190
|
+
)
|
|
191
|
+
_response_json = _response.json()
|
|
192
|
+
except JSONDecodeError:
|
|
193
|
+
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
|
|
194
|
+
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
|
|
195
|
+
|
|
196
|
+
def get_subscriptions(
|
|
197
|
+
self, *, request_options: typing.Optional[RequestOptions] = None
|
|
198
|
+
) -> HttpResponse[typing.List[WebhookSubscription]]:
|
|
199
|
+
"""
|
|
200
|
+
List all webhook subscriptions for your organization.
|
|
201
|
+
|
|
202
|
+
Returns all configured webhook endpoints, including their URLs, subscribed
|
|
203
|
+
event types, and current status (enabled/disabled). Use this to audit
|
|
204
|
+
your webhook configuration or find a specific subscription.
|
|
205
|
+
|
|
206
|
+
Parameters
|
|
207
|
+
----------
|
|
208
|
+
request_options : typing.Optional[RequestOptions]
|
|
209
|
+
Request-specific configuration.
|
|
210
|
+
|
|
211
|
+
Returns
|
|
212
|
+
-------
|
|
213
|
+
HttpResponse[typing.List[WebhookSubscription]]
|
|
214
|
+
List of webhook subscriptions
|
|
215
|
+
"""
|
|
216
|
+
_response = self._client_wrapper.httpx_client.request(
|
|
217
|
+
"events/subscriptions",
|
|
218
|
+
method="GET",
|
|
219
|
+
request_options=request_options,
|
|
220
|
+
)
|
|
221
|
+
try:
|
|
222
|
+
if 200 <= _response.status_code < 300:
|
|
223
|
+
_data = typing.cast(
|
|
224
|
+
typing.List[WebhookSubscription],
|
|
225
|
+
parse_obj_as(
|
|
226
|
+
type_=typing.List[WebhookSubscription], # type: ignore
|
|
227
|
+
object_=_response.json(),
|
|
228
|
+
),
|
|
229
|
+
)
|
|
230
|
+
return HttpResponse(response=_response, data=_data)
|
|
231
|
+
if _response.status_code == 422:
|
|
232
|
+
raise UnprocessableEntityError(
|
|
233
|
+
headers=dict(_response.headers),
|
|
234
|
+
body=typing.cast(
|
|
235
|
+
typing.Optional[typing.Any],
|
|
236
|
+
parse_obj_as(
|
|
237
|
+
type_=typing.Optional[typing.Any], # type: ignore
|
|
238
|
+
object_=_response.json(),
|
|
239
|
+
),
|
|
240
|
+
),
|
|
241
|
+
)
|
|
242
|
+
if _response.status_code == 429:
|
|
243
|
+
raise TooManyRequestsError(
|
|
244
|
+
headers=dict(_response.headers),
|
|
245
|
+
body=typing.cast(
|
|
246
|
+
RateLimitErrorResponse,
|
|
247
|
+
parse_obj_as(
|
|
248
|
+
type_=RateLimitErrorResponse, # type: ignore
|
|
249
|
+
object_=_response.json(),
|
|
250
|
+
),
|
|
251
|
+
),
|
|
252
|
+
)
|
|
253
|
+
_response_json = _response.json()
|
|
254
|
+
except JSONDecodeError:
|
|
255
|
+
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
|
|
256
|
+
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
|
|
257
|
+
|
|
258
|
+
def create_subscription(
|
|
259
|
+
self,
|
|
260
|
+
*,
|
|
261
|
+
url: str,
|
|
262
|
+
event_types: typing.Sequence[EventType],
|
|
263
|
+
secret: typing.Optional[str] = OMIT,
|
|
264
|
+
request_options: typing.Optional[RequestOptions] = None,
|
|
265
|
+
) -> HttpResponse[WebhookSubscription]:
|
|
266
|
+
"""
|
|
267
|
+
Create a new webhook subscription.
|
|
268
|
+
|
|
269
|
+
Webhook subscriptions allow you to receive real-time notifications when events
|
|
270
|
+
occur in Airweave. When you create a subscription, you specify:
|
|
271
|
+
|
|
272
|
+
- **URL**: The HTTPS endpoint where events will be delivered
|
|
273
|
+
- **Event Types**: Which events you want to receive (e.g., `sync.completed`, `sync.failed`)
|
|
274
|
+
- **Secret** (optional): A custom signing secret for verifying webhook signatures
|
|
275
|
+
|
|
276
|
+
After creation, Airweave will send HTTP POST requests to your URL whenever
|
|
277
|
+
matching events occur. Each request includes a signature header for verification.
|
|
278
|
+
|
|
279
|
+
Parameters
|
|
280
|
+
----------
|
|
281
|
+
url : str
|
|
282
|
+
The HTTPS URL where webhook events will be delivered. Must be a publicly accessible endpoint that returns a 2xx status code.
|
|
283
|
+
|
|
284
|
+
event_types : typing.Sequence[EventType]
|
|
285
|
+
List of event types to subscribe to. Events not in this list will not be delivered to this subscription. Available types: `sync.pending`, `sync.running`, `sync.completed`, `sync.failed`, `sync.cancelled`.
|
|
286
|
+
|
|
287
|
+
secret : typing.Optional[str]
|
|
288
|
+
Optional custom signing secret for webhook signature verification. If not provided, a secure secret will be auto-generated. Must be at least 24 characters if specified.
|
|
289
|
+
|
|
290
|
+
request_options : typing.Optional[RequestOptions]
|
|
291
|
+
Request-specific configuration.
|
|
292
|
+
|
|
293
|
+
Returns
|
|
294
|
+
-------
|
|
295
|
+
HttpResponse[WebhookSubscription]
|
|
296
|
+
Created subscription
|
|
297
|
+
"""
|
|
298
|
+
_response = self._client_wrapper.httpx_client.request(
|
|
299
|
+
"events/subscriptions",
|
|
300
|
+
method="POST",
|
|
301
|
+
json={
|
|
302
|
+
"url": url,
|
|
303
|
+
"event_types": event_types,
|
|
304
|
+
"secret": secret,
|
|
305
|
+
},
|
|
306
|
+
headers={
|
|
307
|
+
"content-type": "application/json",
|
|
308
|
+
},
|
|
309
|
+
request_options=request_options,
|
|
310
|
+
omit=OMIT,
|
|
311
|
+
)
|
|
312
|
+
try:
|
|
313
|
+
if 200 <= _response.status_code < 300:
|
|
314
|
+
_data = typing.cast(
|
|
315
|
+
WebhookSubscription,
|
|
316
|
+
parse_obj_as(
|
|
317
|
+
type_=WebhookSubscription, # type: ignore
|
|
318
|
+
object_=_response.json(),
|
|
319
|
+
),
|
|
320
|
+
)
|
|
321
|
+
return HttpResponse(response=_response, data=_data)
|
|
322
|
+
if _response.status_code == 422:
|
|
323
|
+
raise UnprocessableEntityError(
|
|
324
|
+
headers=dict(_response.headers),
|
|
325
|
+
body=typing.cast(
|
|
326
|
+
typing.Optional[typing.Any],
|
|
327
|
+
parse_obj_as(
|
|
328
|
+
type_=typing.Optional[typing.Any], # type: ignore
|
|
329
|
+
object_=_response.json(),
|
|
330
|
+
),
|
|
331
|
+
),
|
|
332
|
+
)
|
|
333
|
+
if _response.status_code == 429:
|
|
334
|
+
raise TooManyRequestsError(
|
|
335
|
+
headers=dict(_response.headers),
|
|
336
|
+
body=typing.cast(
|
|
337
|
+
RateLimitErrorResponse,
|
|
338
|
+
parse_obj_as(
|
|
339
|
+
type_=RateLimitErrorResponse, # type: ignore
|
|
340
|
+
object_=_response.json(),
|
|
341
|
+
),
|
|
342
|
+
),
|
|
343
|
+
)
|
|
344
|
+
_response_json = _response.json()
|
|
345
|
+
except JSONDecodeError:
|
|
346
|
+
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
|
|
347
|
+
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
|
|
348
|
+
|
|
349
|
+
def get_subscription(
|
|
350
|
+
self,
|
|
351
|
+
subscription_id: str,
|
|
352
|
+
*,
|
|
353
|
+
include_secret: typing.Optional[bool] = None,
|
|
354
|
+
request_options: typing.Optional[RequestOptions] = None,
|
|
355
|
+
) -> HttpResponse[WebhookSubscription]:
|
|
356
|
+
"""
|
|
357
|
+
Retrieve a specific webhook subscription with its recent delivery attempts.
|
|
358
|
+
|
|
359
|
+
Returns the subscription configuration along with a history of message delivery
|
|
360
|
+
attempts. This is useful for debugging delivery issues or verifying that your
|
|
361
|
+
endpoint is correctly receiving events.
|
|
362
|
+
|
|
363
|
+
Use `include_secret=true` to also retrieve the signing secret for webhook
|
|
364
|
+
signature verification. Keep this secret secure.
|
|
365
|
+
|
|
366
|
+
Parameters
|
|
367
|
+
----------
|
|
368
|
+
subscription_id : str
|
|
369
|
+
The unique identifier of the subscription to retrieve (UUID).
|
|
370
|
+
|
|
371
|
+
include_secret : typing.Optional[bool]
|
|
372
|
+
Include the signing secret for webhook signature verification. Keep this secret secure and use it to verify the 'svix-signature' header.
|
|
373
|
+
|
|
374
|
+
request_options : typing.Optional[RequestOptions]
|
|
375
|
+
Request-specific configuration.
|
|
376
|
+
|
|
377
|
+
Returns
|
|
378
|
+
-------
|
|
379
|
+
HttpResponse[WebhookSubscription]
|
|
380
|
+
Subscription with delivery attempts
|
|
381
|
+
"""
|
|
382
|
+
_response = self._client_wrapper.httpx_client.request(
|
|
383
|
+
f"events/subscriptions/{jsonable_encoder(subscription_id)}",
|
|
384
|
+
method="GET",
|
|
385
|
+
params={
|
|
386
|
+
"include_secret": include_secret,
|
|
387
|
+
},
|
|
388
|
+
request_options=request_options,
|
|
389
|
+
)
|
|
390
|
+
try:
|
|
391
|
+
if 200 <= _response.status_code < 300:
|
|
392
|
+
_data = typing.cast(
|
|
393
|
+
WebhookSubscription,
|
|
394
|
+
parse_obj_as(
|
|
395
|
+
type_=WebhookSubscription, # type: ignore
|
|
396
|
+
object_=_response.json(),
|
|
397
|
+
),
|
|
398
|
+
)
|
|
399
|
+
return HttpResponse(response=_response, data=_data)
|
|
400
|
+
if _response.status_code == 404:
|
|
401
|
+
raise NotFoundError(
|
|
402
|
+
headers=dict(_response.headers),
|
|
403
|
+
body=typing.cast(
|
|
404
|
+
NotFoundErrorResponse,
|
|
405
|
+
parse_obj_as(
|
|
406
|
+
type_=NotFoundErrorResponse, # type: ignore
|
|
407
|
+
object_=_response.json(),
|
|
408
|
+
),
|
|
409
|
+
),
|
|
410
|
+
)
|
|
411
|
+
if _response.status_code == 422:
|
|
412
|
+
raise UnprocessableEntityError(
|
|
413
|
+
headers=dict(_response.headers),
|
|
414
|
+
body=typing.cast(
|
|
415
|
+
typing.Optional[typing.Any],
|
|
416
|
+
parse_obj_as(
|
|
417
|
+
type_=typing.Optional[typing.Any], # type: ignore
|
|
418
|
+
object_=_response.json(),
|
|
419
|
+
),
|
|
420
|
+
),
|
|
421
|
+
)
|
|
422
|
+
if _response.status_code == 429:
|
|
423
|
+
raise TooManyRequestsError(
|
|
424
|
+
headers=dict(_response.headers),
|
|
425
|
+
body=typing.cast(
|
|
426
|
+
RateLimitErrorResponse,
|
|
427
|
+
parse_obj_as(
|
|
428
|
+
type_=RateLimitErrorResponse, # type: ignore
|
|
429
|
+
object_=_response.json(),
|
|
430
|
+
),
|
|
431
|
+
),
|
|
432
|
+
)
|
|
433
|
+
_response_json = _response.json()
|
|
434
|
+
except JSONDecodeError:
|
|
435
|
+
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
|
|
436
|
+
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
|
|
437
|
+
|
|
438
|
+
def delete_subscription(
|
|
439
|
+
self, subscription_id: str, *, request_options: typing.Optional[RequestOptions] = None
|
|
440
|
+
) -> HttpResponse[WebhookSubscription]:
|
|
441
|
+
"""
|
|
442
|
+
Permanently delete a webhook subscription.
|
|
443
|
+
|
|
444
|
+
Once deleted, Airweave will stop sending events to this endpoint immediately.
|
|
445
|
+
This action cannot be undone. Any pending message deliveries will be cancelled.
|
|
446
|
+
|
|
447
|
+
If you want to temporarily stop receiving events, consider disabling the
|
|
448
|
+
subscription instead using the PATCH endpoint.
|
|
449
|
+
|
|
450
|
+
Parameters
|
|
451
|
+
----------
|
|
452
|
+
subscription_id : str
|
|
453
|
+
The unique identifier of the subscription to delete (UUID).
|
|
454
|
+
|
|
455
|
+
request_options : typing.Optional[RequestOptions]
|
|
456
|
+
Request-specific configuration.
|
|
457
|
+
|
|
458
|
+
Returns
|
|
459
|
+
-------
|
|
460
|
+
HttpResponse[WebhookSubscription]
|
|
461
|
+
Deleted subscription
|
|
462
|
+
"""
|
|
463
|
+
_response = self._client_wrapper.httpx_client.request(
|
|
464
|
+
f"events/subscriptions/{jsonable_encoder(subscription_id)}",
|
|
465
|
+
method="DELETE",
|
|
466
|
+
request_options=request_options,
|
|
467
|
+
)
|
|
468
|
+
try:
|
|
469
|
+
if 200 <= _response.status_code < 300:
|
|
470
|
+
_data = typing.cast(
|
|
471
|
+
WebhookSubscription,
|
|
472
|
+
parse_obj_as(
|
|
473
|
+
type_=WebhookSubscription, # type: ignore
|
|
474
|
+
object_=_response.json(),
|
|
475
|
+
),
|
|
476
|
+
)
|
|
477
|
+
return HttpResponse(response=_response, data=_data)
|
|
478
|
+
if _response.status_code == 404:
|
|
479
|
+
raise NotFoundError(
|
|
480
|
+
headers=dict(_response.headers),
|
|
481
|
+
body=typing.cast(
|
|
482
|
+
NotFoundErrorResponse,
|
|
483
|
+
parse_obj_as(
|
|
484
|
+
type_=NotFoundErrorResponse, # type: ignore
|
|
485
|
+
object_=_response.json(),
|
|
486
|
+
),
|
|
487
|
+
),
|
|
488
|
+
)
|
|
489
|
+
if _response.status_code == 422:
|
|
490
|
+
raise UnprocessableEntityError(
|
|
491
|
+
headers=dict(_response.headers),
|
|
492
|
+
body=typing.cast(
|
|
493
|
+
typing.Optional[typing.Any],
|
|
494
|
+
parse_obj_as(
|
|
495
|
+
type_=typing.Optional[typing.Any], # type: ignore
|
|
496
|
+
object_=_response.json(),
|
|
497
|
+
),
|
|
498
|
+
),
|
|
499
|
+
)
|
|
500
|
+
if _response.status_code == 429:
|
|
501
|
+
raise TooManyRequestsError(
|
|
502
|
+
headers=dict(_response.headers),
|
|
503
|
+
body=typing.cast(
|
|
504
|
+
RateLimitErrorResponse,
|
|
505
|
+
parse_obj_as(
|
|
506
|
+
type_=RateLimitErrorResponse, # type: ignore
|
|
507
|
+
object_=_response.json(),
|
|
508
|
+
),
|
|
509
|
+
),
|
|
510
|
+
)
|
|
511
|
+
_response_json = _response.json()
|
|
512
|
+
except JSONDecodeError:
|
|
513
|
+
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
|
|
514
|
+
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
|
|
515
|
+
|
|
516
|
+
def patch_subscription(
|
|
517
|
+
self,
|
|
518
|
+
subscription_id: str,
|
|
519
|
+
*,
|
|
520
|
+
url: typing.Optional[str] = OMIT,
|
|
521
|
+
event_types: typing.Optional[typing.Sequence[EventType]] = OMIT,
|
|
522
|
+
disabled: typing.Optional[bool] = OMIT,
|
|
523
|
+
recover_since: typing.Optional[dt.datetime] = OMIT,
|
|
524
|
+
request_options: typing.Optional[RequestOptions] = None,
|
|
525
|
+
) -> HttpResponse[WebhookSubscription]:
|
|
526
|
+
"""
|
|
527
|
+
Update an existing webhook subscription.
|
|
528
|
+
|
|
529
|
+
Use this endpoint to modify a subscription's configuration. You can:
|
|
530
|
+
|
|
531
|
+
- **Change the URL**: Update where events are delivered
|
|
532
|
+
- **Update event types**: Modify which events trigger notifications
|
|
533
|
+
- **Enable/disable**: Temporarily pause delivery without deleting the subscription
|
|
534
|
+
- **Recover messages**: When re-enabling, optionally recover missed messages
|
|
535
|
+
|
|
536
|
+
Only include the fields you want to change. Omitted fields will retain their
|
|
537
|
+
current values.
|
|
538
|
+
|
|
539
|
+
When re-enabling a subscription (`disabled: false`), you can optionally provide
|
|
540
|
+
`recover_since` to automatically retry all messages that were generated while
|
|
541
|
+
the subscription was disabled.
|
|
542
|
+
|
|
543
|
+
Parameters
|
|
544
|
+
----------
|
|
545
|
+
subscription_id : str
|
|
546
|
+
The unique identifier of the subscription to update (UUID).
|
|
547
|
+
|
|
548
|
+
url : typing.Optional[str]
|
|
549
|
+
New URL for webhook delivery. Must be a publicly accessible HTTPS endpoint.
|
|
550
|
+
|
|
551
|
+
event_types : typing.Optional[typing.Sequence[EventType]]
|
|
552
|
+
New list of event types to subscribe to. This replaces the existing list entirely.
|
|
553
|
+
|
|
554
|
+
disabled : typing.Optional[bool]
|
|
555
|
+
Set to `true` to pause delivery to this subscription, or `false` to resume. Disabled subscriptions will not receive events.
|
|
556
|
+
|
|
557
|
+
recover_since : typing.Optional[dt.datetime]
|
|
558
|
+
When re-enabling a subscription (`disabled: false`), optionally recover failed messages from this timestamp. Only applies when enabling.
|
|
559
|
+
|
|
560
|
+
request_options : typing.Optional[RequestOptions]
|
|
561
|
+
Request-specific configuration.
|
|
562
|
+
|
|
563
|
+
Returns
|
|
564
|
+
-------
|
|
565
|
+
HttpResponse[WebhookSubscription]
|
|
566
|
+
Updated subscription
|
|
567
|
+
"""
|
|
568
|
+
_response = self._client_wrapper.httpx_client.request(
|
|
569
|
+
f"events/subscriptions/{jsonable_encoder(subscription_id)}",
|
|
570
|
+
method="PATCH",
|
|
571
|
+
json={
|
|
572
|
+
"url": url,
|
|
573
|
+
"event_types": event_types,
|
|
574
|
+
"disabled": disabled,
|
|
575
|
+
"recover_since": recover_since,
|
|
576
|
+
},
|
|
577
|
+
headers={
|
|
578
|
+
"content-type": "application/json",
|
|
579
|
+
},
|
|
580
|
+
request_options=request_options,
|
|
581
|
+
omit=OMIT,
|
|
582
|
+
)
|
|
583
|
+
try:
|
|
584
|
+
if 200 <= _response.status_code < 300:
|
|
585
|
+
_data = typing.cast(
|
|
586
|
+
WebhookSubscription,
|
|
587
|
+
parse_obj_as(
|
|
588
|
+
type_=WebhookSubscription, # type: ignore
|
|
589
|
+
object_=_response.json(),
|
|
590
|
+
),
|
|
591
|
+
)
|
|
592
|
+
return HttpResponse(response=_response, data=_data)
|
|
593
|
+
if _response.status_code == 404:
|
|
594
|
+
raise NotFoundError(
|
|
595
|
+
headers=dict(_response.headers),
|
|
596
|
+
body=typing.cast(
|
|
597
|
+
NotFoundErrorResponse,
|
|
598
|
+
parse_obj_as(
|
|
599
|
+
type_=NotFoundErrorResponse, # type: ignore
|
|
600
|
+
object_=_response.json(),
|
|
601
|
+
),
|
|
602
|
+
),
|
|
603
|
+
)
|
|
604
|
+
if _response.status_code == 422:
|
|
605
|
+
raise UnprocessableEntityError(
|
|
606
|
+
headers=dict(_response.headers),
|
|
607
|
+
body=typing.cast(
|
|
608
|
+
typing.Optional[typing.Any],
|
|
609
|
+
parse_obj_as(
|
|
610
|
+
type_=typing.Optional[typing.Any], # type: ignore
|
|
611
|
+
object_=_response.json(),
|
|
612
|
+
),
|
|
613
|
+
),
|
|
614
|
+
)
|
|
615
|
+
if _response.status_code == 429:
|
|
616
|
+
raise TooManyRequestsError(
|
|
617
|
+
headers=dict(_response.headers),
|
|
618
|
+
body=typing.cast(
|
|
619
|
+
RateLimitErrorResponse,
|
|
620
|
+
parse_obj_as(
|
|
621
|
+
type_=RateLimitErrorResponse, # type: ignore
|
|
622
|
+
object_=_response.json(),
|
|
623
|
+
),
|
|
624
|
+
),
|
|
625
|
+
)
|
|
626
|
+
_response_json = _response.json()
|
|
627
|
+
except JSONDecodeError:
|
|
628
|
+
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
|
|
629
|
+
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
|
|
630
|
+
|
|
631
|
+
def recover_failed_messages(
|
|
632
|
+
self,
|
|
633
|
+
subscription_id: str,
|
|
634
|
+
*,
|
|
635
|
+
since: dt.datetime,
|
|
636
|
+
until: typing.Optional[dt.datetime] = OMIT,
|
|
637
|
+
request_options: typing.Optional[RequestOptions] = None,
|
|
638
|
+
) -> HttpResponse[RecoveryTask]:
|
|
639
|
+
"""
|
|
640
|
+
Retry failed message deliveries for a webhook subscription.
|
|
641
|
+
|
|
642
|
+
Triggers a recovery process that replays all failed messages within the
|
|
643
|
+
specified time window. This is useful when:
|
|
644
|
+
|
|
645
|
+
- Your endpoint was temporarily down and you want to catch up
|
|
646
|
+
- You've fixed a bug in your webhook handler
|
|
647
|
+
- You want to reprocess events after re-enabling a disabled subscription
|
|
648
|
+
|
|
649
|
+
Messages are retried in chronological order. Successfully delivered messages
|
|
650
|
+
are skipped; only failed or pending messages are retried.
|
|
651
|
+
|
|
652
|
+
Parameters
|
|
653
|
+
----------
|
|
654
|
+
subscription_id : str
|
|
655
|
+
The unique identifier of the subscription to recover messages for (UUID).
|
|
656
|
+
|
|
657
|
+
since : dt.datetime
|
|
658
|
+
Start of the recovery time window (inclusive). All failed messages from this time onward will be retried.
|
|
659
|
+
|
|
660
|
+
until : typing.Optional[dt.datetime]
|
|
661
|
+
End of the recovery time window (exclusive). If not specified, recovers all failed messages up to now.
|
|
662
|
+
|
|
663
|
+
request_options : typing.Optional[RequestOptions]
|
|
664
|
+
Request-specific configuration.
|
|
665
|
+
|
|
666
|
+
Returns
|
|
667
|
+
-------
|
|
668
|
+
HttpResponse[RecoveryTask]
|
|
669
|
+
Recovery task information
|
|
670
|
+
"""
|
|
671
|
+
_response = self._client_wrapper.httpx_client.request(
|
|
672
|
+
f"events/subscriptions/{jsonable_encoder(subscription_id)}/recover",
|
|
673
|
+
method="POST",
|
|
674
|
+
json={
|
|
675
|
+
"since": since,
|
|
676
|
+
"until": until,
|
|
677
|
+
},
|
|
678
|
+
headers={
|
|
679
|
+
"content-type": "application/json",
|
|
680
|
+
},
|
|
681
|
+
request_options=request_options,
|
|
682
|
+
omit=OMIT,
|
|
683
|
+
)
|
|
684
|
+
try:
|
|
685
|
+
if 200 <= _response.status_code < 300:
|
|
686
|
+
_data = typing.cast(
|
|
687
|
+
RecoveryTask,
|
|
688
|
+
parse_obj_as(
|
|
689
|
+
type_=RecoveryTask, # type: ignore
|
|
690
|
+
object_=_response.json(),
|
|
691
|
+
),
|
|
692
|
+
)
|
|
693
|
+
return HttpResponse(response=_response, data=_data)
|
|
694
|
+
if _response.status_code == 404:
|
|
695
|
+
raise NotFoundError(
|
|
696
|
+
headers=dict(_response.headers),
|
|
697
|
+
body=typing.cast(
|
|
698
|
+
NotFoundErrorResponse,
|
|
699
|
+
parse_obj_as(
|
|
700
|
+
type_=NotFoundErrorResponse, # type: ignore
|
|
701
|
+
object_=_response.json(),
|
|
702
|
+
),
|
|
703
|
+
),
|
|
704
|
+
)
|
|
705
|
+
if _response.status_code == 422:
|
|
706
|
+
raise UnprocessableEntityError(
|
|
707
|
+
headers=dict(_response.headers),
|
|
708
|
+
body=typing.cast(
|
|
709
|
+
typing.Optional[typing.Any],
|
|
710
|
+
parse_obj_as(
|
|
711
|
+
type_=typing.Optional[typing.Any], # type: ignore
|
|
712
|
+
object_=_response.json(),
|
|
713
|
+
),
|
|
714
|
+
),
|
|
715
|
+
)
|
|
716
|
+
if _response.status_code == 429:
|
|
717
|
+
raise TooManyRequestsError(
|
|
718
|
+
headers=dict(_response.headers),
|
|
719
|
+
body=typing.cast(
|
|
720
|
+
RateLimitErrorResponse,
|
|
721
|
+
parse_obj_as(
|
|
722
|
+
type_=RateLimitErrorResponse, # type: ignore
|
|
723
|
+
object_=_response.json(),
|
|
724
|
+
),
|
|
725
|
+
),
|
|
726
|
+
)
|
|
727
|
+
_response_json = _response.json()
|
|
728
|
+
except JSONDecodeError:
|
|
729
|
+
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
|
|
730
|
+
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
|
|
731
|
+
|
|
732
|
+
|
|
733
|
+
class AsyncRawEventsClient:
|
|
734
|
+
def __init__(self, *, client_wrapper: AsyncClientWrapper):
|
|
735
|
+
self._client_wrapper = client_wrapper
|
|
736
|
+
|
|
737
|
+
async def get_messages(
|
|
738
|
+
self,
|
|
739
|
+
*,
|
|
740
|
+
event_types: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
|
|
741
|
+
request_options: typing.Optional[RequestOptions] = None,
|
|
742
|
+
) -> AsyncHttpResponse[typing.List[EventMessage]]:
|
|
743
|
+
"""
|
|
744
|
+
Retrieve all event messages for your organization.
|
|
745
|
+
|
|
746
|
+
Event messages represent webhook payloads that were sent (or attempted to be sent)
|
|
747
|
+
to your subscribed endpoints. Each message contains the event type, payload data,
|
|
748
|
+
and delivery status information.
|
|
749
|
+
|
|
750
|
+
Use the `event_types` query parameter to filter messages by specific event types,
|
|
751
|
+
such as `sync.completed` or `sync.failed`.
|
|
752
|
+
|
|
753
|
+
Parameters
|
|
754
|
+
----------
|
|
755
|
+
event_types : typing.Optional[typing.Union[str, typing.Sequence[str]]]
|
|
756
|
+
Filter messages by event type(s). Accepts multiple values, e.g., `?event_types=sync.completed&event_types=sync.failed`.
|
|
757
|
+
|
|
758
|
+
request_options : typing.Optional[RequestOptions]
|
|
759
|
+
Request-specific configuration.
|
|
760
|
+
|
|
761
|
+
Returns
|
|
762
|
+
-------
|
|
763
|
+
AsyncHttpResponse[typing.List[EventMessage]]
|
|
764
|
+
List of event messages
|
|
765
|
+
"""
|
|
766
|
+
_response = await self._client_wrapper.httpx_client.request(
|
|
767
|
+
"events/messages",
|
|
768
|
+
method="GET",
|
|
769
|
+
params={
|
|
770
|
+
"event_types": event_types,
|
|
771
|
+
},
|
|
772
|
+
request_options=request_options,
|
|
773
|
+
)
|
|
774
|
+
try:
|
|
775
|
+
if 200 <= _response.status_code < 300:
|
|
776
|
+
_data = typing.cast(
|
|
777
|
+
typing.List[EventMessage],
|
|
778
|
+
parse_obj_as(
|
|
779
|
+
type_=typing.List[EventMessage], # type: ignore
|
|
780
|
+
object_=_response.json(),
|
|
781
|
+
),
|
|
782
|
+
)
|
|
783
|
+
return AsyncHttpResponse(response=_response, data=_data)
|
|
784
|
+
if _response.status_code == 422:
|
|
785
|
+
raise UnprocessableEntityError(
|
|
786
|
+
headers=dict(_response.headers),
|
|
787
|
+
body=typing.cast(
|
|
788
|
+
typing.Optional[typing.Any],
|
|
789
|
+
parse_obj_as(
|
|
790
|
+
type_=typing.Optional[typing.Any], # type: ignore
|
|
791
|
+
object_=_response.json(),
|
|
792
|
+
),
|
|
793
|
+
),
|
|
794
|
+
)
|
|
795
|
+
if _response.status_code == 429:
|
|
796
|
+
raise TooManyRequestsError(
|
|
797
|
+
headers=dict(_response.headers),
|
|
798
|
+
body=typing.cast(
|
|
799
|
+
RateLimitErrorResponse,
|
|
800
|
+
parse_obj_as(
|
|
801
|
+
type_=RateLimitErrorResponse, # type: ignore
|
|
802
|
+
object_=_response.json(),
|
|
803
|
+
),
|
|
804
|
+
),
|
|
805
|
+
)
|
|
806
|
+
_response_json = _response.json()
|
|
807
|
+
except JSONDecodeError:
|
|
808
|
+
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
|
|
809
|
+
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
|
|
810
|
+
|
|
811
|
+
async def get_message(
|
|
812
|
+
self,
|
|
813
|
+
message_id: str,
|
|
814
|
+
*,
|
|
815
|
+
include_attempts: typing.Optional[bool] = None,
|
|
816
|
+
request_options: typing.Optional[RequestOptions] = None,
|
|
817
|
+
) -> AsyncHttpResponse[EventMessageWithAttempts]:
|
|
818
|
+
"""
|
|
819
|
+
Retrieve a specific event message by its ID.
|
|
820
|
+
|
|
821
|
+
Returns the full message details including the event type, payload data,
|
|
822
|
+
timestamp, and delivery channel information. Use this to inspect the
|
|
823
|
+
exact payload that was sent to your webhook endpoints.
|
|
824
|
+
|
|
825
|
+
Use `include_attempts=true` to also retrieve delivery attempts for this message,
|
|
826
|
+
which include HTTP response codes, response bodies, and timestamps for debugging
|
|
827
|
+
delivery failures.
|
|
828
|
+
|
|
829
|
+
Parameters
|
|
830
|
+
----------
|
|
831
|
+
message_id : str
|
|
832
|
+
The unique identifier of the message to retrieve (UUID).
|
|
833
|
+
|
|
834
|
+
include_attempts : typing.Optional[bool]
|
|
835
|
+
Include delivery attempts for this message. Each attempt includes the HTTP response code, response body, and timestamp.
|
|
836
|
+
|
|
837
|
+
request_options : typing.Optional[RequestOptions]
|
|
838
|
+
Request-specific configuration.
|
|
839
|
+
|
|
840
|
+
Returns
|
|
841
|
+
-------
|
|
842
|
+
AsyncHttpResponse[EventMessageWithAttempts]
|
|
843
|
+
Event message details
|
|
844
|
+
"""
|
|
845
|
+
_response = await self._client_wrapper.httpx_client.request(
|
|
846
|
+
f"events/messages/{jsonable_encoder(message_id)}",
|
|
847
|
+
method="GET",
|
|
848
|
+
params={
|
|
849
|
+
"include_attempts": include_attempts,
|
|
850
|
+
},
|
|
851
|
+
request_options=request_options,
|
|
852
|
+
)
|
|
853
|
+
try:
|
|
854
|
+
if 200 <= _response.status_code < 300:
|
|
855
|
+
_data = typing.cast(
|
|
856
|
+
EventMessageWithAttempts,
|
|
857
|
+
parse_obj_as(
|
|
858
|
+
type_=EventMessageWithAttempts, # type: ignore
|
|
859
|
+
object_=_response.json(),
|
|
860
|
+
),
|
|
861
|
+
)
|
|
862
|
+
return AsyncHttpResponse(response=_response, data=_data)
|
|
863
|
+
if _response.status_code == 404:
|
|
864
|
+
raise NotFoundError(
|
|
865
|
+
headers=dict(_response.headers),
|
|
866
|
+
body=typing.cast(
|
|
867
|
+
NotFoundErrorResponse,
|
|
868
|
+
parse_obj_as(
|
|
869
|
+
type_=NotFoundErrorResponse, # type: ignore
|
|
870
|
+
object_=_response.json(),
|
|
871
|
+
),
|
|
872
|
+
),
|
|
873
|
+
)
|
|
874
|
+
if _response.status_code == 422:
|
|
875
|
+
raise UnprocessableEntityError(
|
|
876
|
+
headers=dict(_response.headers),
|
|
877
|
+
body=typing.cast(
|
|
878
|
+
typing.Optional[typing.Any],
|
|
879
|
+
parse_obj_as(
|
|
880
|
+
type_=typing.Optional[typing.Any], # type: ignore
|
|
881
|
+
object_=_response.json(),
|
|
882
|
+
),
|
|
883
|
+
),
|
|
884
|
+
)
|
|
885
|
+
if _response.status_code == 429:
|
|
886
|
+
raise TooManyRequestsError(
|
|
887
|
+
headers=dict(_response.headers),
|
|
888
|
+
body=typing.cast(
|
|
889
|
+
RateLimitErrorResponse,
|
|
890
|
+
parse_obj_as(
|
|
891
|
+
type_=RateLimitErrorResponse, # type: ignore
|
|
892
|
+
object_=_response.json(),
|
|
893
|
+
),
|
|
894
|
+
),
|
|
895
|
+
)
|
|
896
|
+
_response_json = _response.json()
|
|
897
|
+
except JSONDecodeError:
|
|
898
|
+
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
|
|
899
|
+
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
|
|
900
|
+
|
|
901
|
+
async def get_subscriptions(
|
|
902
|
+
self, *, request_options: typing.Optional[RequestOptions] = None
|
|
903
|
+
) -> AsyncHttpResponse[typing.List[WebhookSubscription]]:
|
|
904
|
+
"""
|
|
905
|
+
List all webhook subscriptions for your organization.
|
|
906
|
+
|
|
907
|
+
Returns all configured webhook endpoints, including their URLs, subscribed
|
|
908
|
+
event types, and current status (enabled/disabled). Use this to audit
|
|
909
|
+
your webhook configuration or find a specific subscription.
|
|
910
|
+
|
|
911
|
+
Parameters
|
|
912
|
+
----------
|
|
913
|
+
request_options : typing.Optional[RequestOptions]
|
|
914
|
+
Request-specific configuration.
|
|
915
|
+
|
|
916
|
+
Returns
|
|
917
|
+
-------
|
|
918
|
+
AsyncHttpResponse[typing.List[WebhookSubscription]]
|
|
919
|
+
List of webhook subscriptions
|
|
920
|
+
"""
|
|
921
|
+
_response = await self._client_wrapper.httpx_client.request(
|
|
922
|
+
"events/subscriptions",
|
|
923
|
+
method="GET",
|
|
924
|
+
request_options=request_options,
|
|
925
|
+
)
|
|
926
|
+
try:
|
|
927
|
+
if 200 <= _response.status_code < 300:
|
|
928
|
+
_data = typing.cast(
|
|
929
|
+
typing.List[WebhookSubscription],
|
|
930
|
+
parse_obj_as(
|
|
931
|
+
type_=typing.List[WebhookSubscription], # type: ignore
|
|
932
|
+
object_=_response.json(),
|
|
933
|
+
),
|
|
934
|
+
)
|
|
935
|
+
return AsyncHttpResponse(response=_response, data=_data)
|
|
936
|
+
if _response.status_code == 422:
|
|
937
|
+
raise UnprocessableEntityError(
|
|
938
|
+
headers=dict(_response.headers),
|
|
939
|
+
body=typing.cast(
|
|
940
|
+
typing.Optional[typing.Any],
|
|
941
|
+
parse_obj_as(
|
|
942
|
+
type_=typing.Optional[typing.Any], # type: ignore
|
|
943
|
+
object_=_response.json(),
|
|
944
|
+
),
|
|
945
|
+
),
|
|
946
|
+
)
|
|
947
|
+
if _response.status_code == 429:
|
|
948
|
+
raise TooManyRequestsError(
|
|
949
|
+
headers=dict(_response.headers),
|
|
950
|
+
body=typing.cast(
|
|
951
|
+
RateLimitErrorResponse,
|
|
952
|
+
parse_obj_as(
|
|
953
|
+
type_=RateLimitErrorResponse, # type: ignore
|
|
954
|
+
object_=_response.json(),
|
|
955
|
+
),
|
|
956
|
+
),
|
|
957
|
+
)
|
|
958
|
+
_response_json = _response.json()
|
|
959
|
+
except JSONDecodeError:
|
|
960
|
+
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
|
|
961
|
+
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
|
|
962
|
+
|
|
963
|
+
async def create_subscription(
|
|
964
|
+
self,
|
|
965
|
+
*,
|
|
966
|
+
url: str,
|
|
967
|
+
event_types: typing.Sequence[EventType],
|
|
968
|
+
secret: typing.Optional[str] = OMIT,
|
|
969
|
+
request_options: typing.Optional[RequestOptions] = None,
|
|
970
|
+
) -> AsyncHttpResponse[WebhookSubscription]:
|
|
971
|
+
"""
|
|
972
|
+
Create a new webhook subscription.
|
|
973
|
+
|
|
974
|
+
Webhook subscriptions allow you to receive real-time notifications when events
|
|
975
|
+
occur in Airweave. When you create a subscription, you specify:
|
|
976
|
+
|
|
977
|
+
- **URL**: The HTTPS endpoint where events will be delivered
|
|
978
|
+
- **Event Types**: Which events you want to receive (e.g., `sync.completed`, `sync.failed`)
|
|
979
|
+
- **Secret** (optional): A custom signing secret for verifying webhook signatures
|
|
980
|
+
|
|
981
|
+
After creation, Airweave will send HTTP POST requests to your URL whenever
|
|
982
|
+
matching events occur. Each request includes a signature header for verification.
|
|
983
|
+
|
|
984
|
+
Parameters
|
|
985
|
+
----------
|
|
986
|
+
url : str
|
|
987
|
+
The HTTPS URL where webhook events will be delivered. Must be a publicly accessible endpoint that returns a 2xx status code.
|
|
988
|
+
|
|
989
|
+
event_types : typing.Sequence[EventType]
|
|
990
|
+
List of event types to subscribe to. Events not in this list will not be delivered to this subscription. Available types: `sync.pending`, `sync.running`, `sync.completed`, `sync.failed`, `sync.cancelled`.
|
|
991
|
+
|
|
992
|
+
secret : typing.Optional[str]
|
|
993
|
+
Optional custom signing secret for webhook signature verification. If not provided, a secure secret will be auto-generated. Must be at least 24 characters if specified.
|
|
994
|
+
|
|
995
|
+
request_options : typing.Optional[RequestOptions]
|
|
996
|
+
Request-specific configuration.
|
|
997
|
+
|
|
998
|
+
Returns
|
|
999
|
+
-------
|
|
1000
|
+
AsyncHttpResponse[WebhookSubscription]
|
|
1001
|
+
Created subscription
|
|
1002
|
+
"""
|
|
1003
|
+
_response = await self._client_wrapper.httpx_client.request(
|
|
1004
|
+
"events/subscriptions",
|
|
1005
|
+
method="POST",
|
|
1006
|
+
json={
|
|
1007
|
+
"url": url,
|
|
1008
|
+
"event_types": event_types,
|
|
1009
|
+
"secret": secret,
|
|
1010
|
+
},
|
|
1011
|
+
headers={
|
|
1012
|
+
"content-type": "application/json",
|
|
1013
|
+
},
|
|
1014
|
+
request_options=request_options,
|
|
1015
|
+
omit=OMIT,
|
|
1016
|
+
)
|
|
1017
|
+
try:
|
|
1018
|
+
if 200 <= _response.status_code < 300:
|
|
1019
|
+
_data = typing.cast(
|
|
1020
|
+
WebhookSubscription,
|
|
1021
|
+
parse_obj_as(
|
|
1022
|
+
type_=WebhookSubscription, # type: ignore
|
|
1023
|
+
object_=_response.json(),
|
|
1024
|
+
),
|
|
1025
|
+
)
|
|
1026
|
+
return AsyncHttpResponse(response=_response, data=_data)
|
|
1027
|
+
if _response.status_code == 422:
|
|
1028
|
+
raise UnprocessableEntityError(
|
|
1029
|
+
headers=dict(_response.headers),
|
|
1030
|
+
body=typing.cast(
|
|
1031
|
+
typing.Optional[typing.Any],
|
|
1032
|
+
parse_obj_as(
|
|
1033
|
+
type_=typing.Optional[typing.Any], # type: ignore
|
|
1034
|
+
object_=_response.json(),
|
|
1035
|
+
),
|
|
1036
|
+
),
|
|
1037
|
+
)
|
|
1038
|
+
if _response.status_code == 429:
|
|
1039
|
+
raise TooManyRequestsError(
|
|
1040
|
+
headers=dict(_response.headers),
|
|
1041
|
+
body=typing.cast(
|
|
1042
|
+
RateLimitErrorResponse,
|
|
1043
|
+
parse_obj_as(
|
|
1044
|
+
type_=RateLimitErrorResponse, # type: ignore
|
|
1045
|
+
object_=_response.json(),
|
|
1046
|
+
),
|
|
1047
|
+
),
|
|
1048
|
+
)
|
|
1049
|
+
_response_json = _response.json()
|
|
1050
|
+
except JSONDecodeError:
|
|
1051
|
+
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
|
|
1052
|
+
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
|
|
1053
|
+
|
|
1054
|
+
async def get_subscription(
|
|
1055
|
+
self,
|
|
1056
|
+
subscription_id: str,
|
|
1057
|
+
*,
|
|
1058
|
+
include_secret: typing.Optional[bool] = None,
|
|
1059
|
+
request_options: typing.Optional[RequestOptions] = None,
|
|
1060
|
+
) -> AsyncHttpResponse[WebhookSubscription]:
|
|
1061
|
+
"""
|
|
1062
|
+
Retrieve a specific webhook subscription with its recent delivery attempts.
|
|
1063
|
+
|
|
1064
|
+
Returns the subscription configuration along with a history of message delivery
|
|
1065
|
+
attempts. This is useful for debugging delivery issues or verifying that your
|
|
1066
|
+
endpoint is correctly receiving events.
|
|
1067
|
+
|
|
1068
|
+
Use `include_secret=true` to also retrieve the signing secret for webhook
|
|
1069
|
+
signature verification. Keep this secret secure.
|
|
1070
|
+
|
|
1071
|
+
Parameters
|
|
1072
|
+
----------
|
|
1073
|
+
subscription_id : str
|
|
1074
|
+
The unique identifier of the subscription to retrieve (UUID).
|
|
1075
|
+
|
|
1076
|
+
include_secret : typing.Optional[bool]
|
|
1077
|
+
Include the signing secret for webhook signature verification. Keep this secret secure and use it to verify the 'svix-signature' header.
|
|
1078
|
+
|
|
1079
|
+
request_options : typing.Optional[RequestOptions]
|
|
1080
|
+
Request-specific configuration.
|
|
1081
|
+
|
|
1082
|
+
Returns
|
|
1083
|
+
-------
|
|
1084
|
+
AsyncHttpResponse[WebhookSubscription]
|
|
1085
|
+
Subscription with delivery attempts
|
|
1086
|
+
"""
|
|
1087
|
+
_response = await self._client_wrapper.httpx_client.request(
|
|
1088
|
+
f"events/subscriptions/{jsonable_encoder(subscription_id)}",
|
|
1089
|
+
method="GET",
|
|
1090
|
+
params={
|
|
1091
|
+
"include_secret": include_secret,
|
|
1092
|
+
},
|
|
1093
|
+
request_options=request_options,
|
|
1094
|
+
)
|
|
1095
|
+
try:
|
|
1096
|
+
if 200 <= _response.status_code < 300:
|
|
1097
|
+
_data = typing.cast(
|
|
1098
|
+
WebhookSubscription,
|
|
1099
|
+
parse_obj_as(
|
|
1100
|
+
type_=WebhookSubscription, # type: ignore
|
|
1101
|
+
object_=_response.json(),
|
|
1102
|
+
),
|
|
1103
|
+
)
|
|
1104
|
+
return AsyncHttpResponse(response=_response, data=_data)
|
|
1105
|
+
if _response.status_code == 404:
|
|
1106
|
+
raise NotFoundError(
|
|
1107
|
+
headers=dict(_response.headers),
|
|
1108
|
+
body=typing.cast(
|
|
1109
|
+
NotFoundErrorResponse,
|
|
1110
|
+
parse_obj_as(
|
|
1111
|
+
type_=NotFoundErrorResponse, # type: ignore
|
|
1112
|
+
object_=_response.json(),
|
|
1113
|
+
),
|
|
1114
|
+
),
|
|
1115
|
+
)
|
|
1116
|
+
if _response.status_code == 422:
|
|
1117
|
+
raise UnprocessableEntityError(
|
|
1118
|
+
headers=dict(_response.headers),
|
|
1119
|
+
body=typing.cast(
|
|
1120
|
+
typing.Optional[typing.Any],
|
|
1121
|
+
parse_obj_as(
|
|
1122
|
+
type_=typing.Optional[typing.Any], # type: ignore
|
|
1123
|
+
object_=_response.json(),
|
|
1124
|
+
),
|
|
1125
|
+
),
|
|
1126
|
+
)
|
|
1127
|
+
if _response.status_code == 429:
|
|
1128
|
+
raise TooManyRequestsError(
|
|
1129
|
+
headers=dict(_response.headers),
|
|
1130
|
+
body=typing.cast(
|
|
1131
|
+
RateLimitErrorResponse,
|
|
1132
|
+
parse_obj_as(
|
|
1133
|
+
type_=RateLimitErrorResponse, # type: ignore
|
|
1134
|
+
object_=_response.json(),
|
|
1135
|
+
),
|
|
1136
|
+
),
|
|
1137
|
+
)
|
|
1138
|
+
_response_json = _response.json()
|
|
1139
|
+
except JSONDecodeError:
|
|
1140
|
+
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
|
|
1141
|
+
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
|
|
1142
|
+
|
|
1143
|
+
async def delete_subscription(
|
|
1144
|
+
self, subscription_id: str, *, request_options: typing.Optional[RequestOptions] = None
|
|
1145
|
+
) -> AsyncHttpResponse[WebhookSubscription]:
|
|
1146
|
+
"""
|
|
1147
|
+
Permanently delete a webhook subscription.
|
|
1148
|
+
|
|
1149
|
+
Once deleted, Airweave will stop sending events to this endpoint immediately.
|
|
1150
|
+
This action cannot be undone. Any pending message deliveries will be cancelled.
|
|
1151
|
+
|
|
1152
|
+
If you want to temporarily stop receiving events, consider disabling the
|
|
1153
|
+
subscription instead using the PATCH endpoint.
|
|
1154
|
+
|
|
1155
|
+
Parameters
|
|
1156
|
+
----------
|
|
1157
|
+
subscription_id : str
|
|
1158
|
+
The unique identifier of the subscription to delete (UUID).
|
|
1159
|
+
|
|
1160
|
+
request_options : typing.Optional[RequestOptions]
|
|
1161
|
+
Request-specific configuration.
|
|
1162
|
+
|
|
1163
|
+
Returns
|
|
1164
|
+
-------
|
|
1165
|
+
AsyncHttpResponse[WebhookSubscription]
|
|
1166
|
+
Deleted subscription
|
|
1167
|
+
"""
|
|
1168
|
+
_response = await self._client_wrapper.httpx_client.request(
|
|
1169
|
+
f"events/subscriptions/{jsonable_encoder(subscription_id)}",
|
|
1170
|
+
method="DELETE",
|
|
1171
|
+
request_options=request_options,
|
|
1172
|
+
)
|
|
1173
|
+
try:
|
|
1174
|
+
if 200 <= _response.status_code < 300:
|
|
1175
|
+
_data = typing.cast(
|
|
1176
|
+
WebhookSubscription,
|
|
1177
|
+
parse_obj_as(
|
|
1178
|
+
type_=WebhookSubscription, # type: ignore
|
|
1179
|
+
object_=_response.json(),
|
|
1180
|
+
),
|
|
1181
|
+
)
|
|
1182
|
+
return AsyncHttpResponse(response=_response, data=_data)
|
|
1183
|
+
if _response.status_code == 404:
|
|
1184
|
+
raise NotFoundError(
|
|
1185
|
+
headers=dict(_response.headers),
|
|
1186
|
+
body=typing.cast(
|
|
1187
|
+
NotFoundErrorResponse,
|
|
1188
|
+
parse_obj_as(
|
|
1189
|
+
type_=NotFoundErrorResponse, # type: ignore
|
|
1190
|
+
object_=_response.json(),
|
|
1191
|
+
),
|
|
1192
|
+
),
|
|
1193
|
+
)
|
|
1194
|
+
if _response.status_code == 422:
|
|
1195
|
+
raise UnprocessableEntityError(
|
|
1196
|
+
headers=dict(_response.headers),
|
|
1197
|
+
body=typing.cast(
|
|
1198
|
+
typing.Optional[typing.Any],
|
|
1199
|
+
parse_obj_as(
|
|
1200
|
+
type_=typing.Optional[typing.Any], # type: ignore
|
|
1201
|
+
object_=_response.json(),
|
|
1202
|
+
),
|
|
1203
|
+
),
|
|
1204
|
+
)
|
|
1205
|
+
if _response.status_code == 429:
|
|
1206
|
+
raise TooManyRequestsError(
|
|
1207
|
+
headers=dict(_response.headers),
|
|
1208
|
+
body=typing.cast(
|
|
1209
|
+
RateLimitErrorResponse,
|
|
1210
|
+
parse_obj_as(
|
|
1211
|
+
type_=RateLimitErrorResponse, # type: ignore
|
|
1212
|
+
object_=_response.json(),
|
|
1213
|
+
),
|
|
1214
|
+
),
|
|
1215
|
+
)
|
|
1216
|
+
_response_json = _response.json()
|
|
1217
|
+
except JSONDecodeError:
|
|
1218
|
+
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
|
|
1219
|
+
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
|
|
1220
|
+
|
|
1221
|
+
async def patch_subscription(
|
|
1222
|
+
self,
|
|
1223
|
+
subscription_id: str,
|
|
1224
|
+
*,
|
|
1225
|
+
url: typing.Optional[str] = OMIT,
|
|
1226
|
+
event_types: typing.Optional[typing.Sequence[EventType]] = OMIT,
|
|
1227
|
+
disabled: typing.Optional[bool] = OMIT,
|
|
1228
|
+
recover_since: typing.Optional[dt.datetime] = OMIT,
|
|
1229
|
+
request_options: typing.Optional[RequestOptions] = None,
|
|
1230
|
+
) -> AsyncHttpResponse[WebhookSubscription]:
|
|
1231
|
+
"""
|
|
1232
|
+
Update an existing webhook subscription.
|
|
1233
|
+
|
|
1234
|
+
Use this endpoint to modify a subscription's configuration. You can:
|
|
1235
|
+
|
|
1236
|
+
- **Change the URL**: Update where events are delivered
|
|
1237
|
+
- **Update event types**: Modify which events trigger notifications
|
|
1238
|
+
- **Enable/disable**: Temporarily pause delivery without deleting the subscription
|
|
1239
|
+
- **Recover messages**: When re-enabling, optionally recover missed messages
|
|
1240
|
+
|
|
1241
|
+
Only include the fields you want to change. Omitted fields will retain their
|
|
1242
|
+
current values.
|
|
1243
|
+
|
|
1244
|
+
When re-enabling a subscription (`disabled: false`), you can optionally provide
|
|
1245
|
+
`recover_since` to automatically retry all messages that were generated while
|
|
1246
|
+
the subscription was disabled.
|
|
1247
|
+
|
|
1248
|
+
Parameters
|
|
1249
|
+
----------
|
|
1250
|
+
subscription_id : str
|
|
1251
|
+
The unique identifier of the subscription to update (UUID).
|
|
1252
|
+
|
|
1253
|
+
url : typing.Optional[str]
|
|
1254
|
+
New URL for webhook delivery. Must be a publicly accessible HTTPS endpoint.
|
|
1255
|
+
|
|
1256
|
+
event_types : typing.Optional[typing.Sequence[EventType]]
|
|
1257
|
+
New list of event types to subscribe to. This replaces the existing list entirely.
|
|
1258
|
+
|
|
1259
|
+
disabled : typing.Optional[bool]
|
|
1260
|
+
Set to `true` to pause delivery to this subscription, or `false` to resume. Disabled subscriptions will not receive events.
|
|
1261
|
+
|
|
1262
|
+
recover_since : typing.Optional[dt.datetime]
|
|
1263
|
+
When re-enabling a subscription (`disabled: false`), optionally recover failed messages from this timestamp. Only applies when enabling.
|
|
1264
|
+
|
|
1265
|
+
request_options : typing.Optional[RequestOptions]
|
|
1266
|
+
Request-specific configuration.
|
|
1267
|
+
|
|
1268
|
+
Returns
|
|
1269
|
+
-------
|
|
1270
|
+
AsyncHttpResponse[WebhookSubscription]
|
|
1271
|
+
Updated subscription
|
|
1272
|
+
"""
|
|
1273
|
+
_response = await self._client_wrapper.httpx_client.request(
|
|
1274
|
+
f"events/subscriptions/{jsonable_encoder(subscription_id)}",
|
|
1275
|
+
method="PATCH",
|
|
1276
|
+
json={
|
|
1277
|
+
"url": url,
|
|
1278
|
+
"event_types": event_types,
|
|
1279
|
+
"disabled": disabled,
|
|
1280
|
+
"recover_since": recover_since,
|
|
1281
|
+
},
|
|
1282
|
+
headers={
|
|
1283
|
+
"content-type": "application/json",
|
|
1284
|
+
},
|
|
1285
|
+
request_options=request_options,
|
|
1286
|
+
omit=OMIT,
|
|
1287
|
+
)
|
|
1288
|
+
try:
|
|
1289
|
+
if 200 <= _response.status_code < 300:
|
|
1290
|
+
_data = typing.cast(
|
|
1291
|
+
WebhookSubscription,
|
|
1292
|
+
parse_obj_as(
|
|
1293
|
+
type_=WebhookSubscription, # type: ignore
|
|
1294
|
+
object_=_response.json(),
|
|
1295
|
+
),
|
|
1296
|
+
)
|
|
1297
|
+
return AsyncHttpResponse(response=_response, data=_data)
|
|
1298
|
+
if _response.status_code == 404:
|
|
1299
|
+
raise NotFoundError(
|
|
1300
|
+
headers=dict(_response.headers),
|
|
1301
|
+
body=typing.cast(
|
|
1302
|
+
NotFoundErrorResponse,
|
|
1303
|
+
parse_obj_as(
|
|
1304
|
+
type_=NotFoundErrorResponse, # type: ignore
|
|
1305
|
+
object_=_response.json(),
|
|
1306
|
+
),
|
|
1307
|
+
),
|
|
1308
|
+
)
|
|
1309
|
+
if _response.status_code == 422:
|
|
1310
|
+
raise UnprocessableEntityError(
|
|
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 == 429:
|
|
1321
|
+
raise TooManyRequestsError(
|
|
1322
|
+
headers=dict(_response.headers),
|
|
1323
|
+
body=typing.cast(
|
|
1324
|
+
RateLimitErrorResponse,
|
|
1325
|
+
parse_obj_as(
|
|
1326
|
+
type_=RateLimitErrorResponse, # type: ignore
|
|
1327
|
+
object_=_response.json(),
|
|
1328
|
+
),
|
|
1329
|
+
),
|
|
1330
|
+
)
|
|
1331
|
+
_response_json = _response.json()
|
|
1332
|
+
except JSONDecodeError:
|
|
1333
|
+
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
|
|
1334
|
+
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
|
|
1335
|
+
|
|
1336
|
+
async def recover_failed_messages(
|
|
1337
|
+
self,
|
|
1338
|
+
subscription_id: str,
|
|
1339
|
+
*,
|
|
1340
|
+
since: dt.datetime,
|
|
1341
|
+
until: typing.Optional[dt.datetime] = OMIT,
|
|
1342
|
+
request_options: typing.Optional[RequestOptions] = None,
|
|
1343
|
+
) -> AsyncHttpResponse[RecoveryTask]:
|
|
1344
|
+
"""
|
|
1345
|
+
Retry failed message deliveries for a webhook subscription.
|
|
1346
|
+
|
|
1347
|
+
Triggers a recovery process that replays all failed messages within the
|
|
1348
|
+
specified time window. This is useful when:
|
|
1349
|
+
|
|
1350
|
+
- Your endpoint was temporarily down and you want to catch up
|
|
1351
|
+
- You've fixed a bug in your webhook handler
|
|
1352
|
+
- You want to reprocess events after re-enabling a disabled subscription
|
|
1353
|
+
|
|
1354
|
+
Messages are retried in chronological order. Successfully delivered messages
|
|
1355
|
+
are skipped; only failed or pending messages are retried.
|
|
1356
|
+
|
|
1357
|
+
Parameters
|
|
1358
|
+
----------
|
|
1359
|
+
subscription_id : str
|
|
1360
|
+
The unique identifier of the subscription to recover messages for (UUID).
|
|
1361
|
+
|
|
1362
|
+
since : dt.datetime
|
|
1363
|
+
Start of the recovery time window (inclusive). All failed messages from this time onward will be retried.
|
|
1364
|
+
|
|
1365
|
+
until : typing.Optional[dt.datetime]
|
|
1366
|
+
End of the recovery time window (exclusive). If not specified, recovers all failed messages up to now.
|
|
1367
|
+
|
|
1368
|
+
request_options : typing.Optional[RequestOptions]
|
|
1369
|
+
Request-specific configuration.
|
|
1370
|
+
|
|
1371
|
+
Returns
|
|
1372
|
+
-------
|
|
1373
|
+
AsyncHttpResponse[RecoveryTask]
|
|
1374
|
+
Recovery task information
|
|
1375
|
+
"""
|
|
1376
|
+
_response = await self._client_wrapper.httpx_client.request(
|
|
1377
|
+
f"events/subscriptions/{jsonable_encoder(subscription_id)}/recover",
|
|
1378
|
+
method="POST",
|
|
1379
|
+
json={
|
|
1380
|
+
"since": since,
|
|
1381
|
+
"until": until,
|
|
1382
|
+
},
|
|
1383
|
+
headers={
|
|
1384
|
+
"content-type": "application/json",
|
|
1385
|
+
},
|
|
1386
|
+
request_options=request_options,
|
|
1387
|
+
omit=OMIT,
|
|
1388
|
+
)
|
|
1389
|
+
try:
|
|
1390
|
+
if 200 <= _response.status_code < 300:
|
|
1391
|
+
_data = typing.cast(
|
|
1392
|
+
RecoveryTask,
|
|
1393
|
+
parse_obj_as(
|
|
1394
|
+
type_=RecoveryTask, # type: ignore
|
|
1395
|
+
object_=_response.json(),
|
|
1396
|
+
),
|
|
1397
|
+
)
|
|
1398
|
+
return AsyncHttpResponse(response=_response, data=_data)
|
|
1399
|
+
if _response.status_code == 404:
|
|
1400
|
+
raise NotFoundError(
|
|
1401
|
+
headers=dict(_response.headers),
|
|
1402
|
+
body=typing.cast(
|
|
1403
|
+
NotFoundErrorResponse,
|
|
1404
|
+
parse_obj_as(
|
|
1405
|
+
type_=NotFoundErrorResponse, # type: ignore
|
|
1406
|
+
object_=_response.json(),
|
|
1407
|
+
),
|
|
1408
|
+
),
|
|
1409
|
+
)
|
|
1410
|
+
if _response.status_code == 422:
|
|
1411
|
+
raise UnprocessableEntityError(
|
|
1412
|
+
headers=dict(_response.headers),
|
|
1413
|
+
body=typing.cast(
|
|
1414
|
+
typing.Optional[typing.Any],
|
|
1415
|
+
parse_obj_as(
|
|
1416
|
+
type_=typing.Optional[typing.Any], # type: ignore
|
|
1417
|
+
object_=_response.json(),
|
|
1418
|
+
),
|
|
1419
|
+
),
|
|
1420
|
+
)
|
|
1421
|
+
if _response.status_code == 429:
|
|
1422
|
+
raise TooManyRequestsError(
|
|
1423
|
+
headers=dict(_response.headers),
|
|
1424
|
+
body=typing.cast(
|
|
1425
|
+
RateLimitErrorResponse,
|
|
1426
|
+
parse_obj_as(
|
|
1427
|
+
type_=RateLimitErrorResponse, # type: ignore
|
|
1428
|
+
object_=_response.json(),
|
|
1429
|
+
),
|
|
1430
|
+
),
|
|
1431
|
+
)
|
|
1432
|
+
_response_json = _response.json()
|
|
1433
|
+
except JSONDecodeError:
|
|
1434
|
+
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
|
|
1435
|
+
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
|