diff --git a/src/apify/_actor.py b/src/apify/_actor.py index e00e4663..20242a9a 100644 --- a/src/apify/_actor.py +++ b/src/apify/_actor.py @@ -4,6 +4,7 @@ import sys import warnings from contextlib import suppress +from dataclasses import asdict from datetime import UTC, datetime, timedelta from functools import cached_property from typing import TYPE_CHECKING, Any, Literal, TypeVar, cast, overload @@ -1283,15 +1284,16 @@ async def add_webhook(self, webhook: Webhook, *, idempotency_key: str | None = N if not self.configuration.actor_run_id: raise RuntimeError('actor_run_id cannot be None when running on the Apify platform.') + # `Webhook`'s field names match `webhooks().create()`'s parameters, so we forward them by name rather + # than listing each one. + webhook_fields = asdict(webhook) + + if idempotency_key is not None: + webhook_fields['idempotency_key'] = idempotency_key + await self.apify_client.webhooks().create( + **webhook_fields, actor_run_id=self.configuration.actor_run_id, - event_types=webhook.event_types, - request_url=webhook.request_url, - payload_template=webhook.payload_template, - headers_template=webhook.headers_template, - ignore_ssl_errors=webhook.ignore_ssl_errors, - do_not_retry=webhook.do_not_retry, - idempotency_key=idempotency_key if idempotency_key is not None else webhook.idempotency_key, is_ad_hoc=True, ) diff --git a/src/apify/_webhook.py b/src/apify/_webhook.py index 129385c9..ff084f6a 100644 --- a/src/apify/_webhook.py +++ b/src/apify/_webhook.py @@ -48,15 +48,13 @@ def __post_init__(self) -> None: def to_client_representations(webhooks: list[Webhook] | None) -> list[WebhookRepresentation] | None: - """Project SDK webhooks to the minimal ad-hoc representation accepted by the client's `start()` / `call()`.""" + """Convert SDK webhooks to the ad-hoc representation accepted by the client's `start()` / `call()`. + + `Webhook`'s field names match `WebhookRepresentation`'s, so we let pydantic read them straight off the + instance rather than listing each one. This forwards any field the representation declares without changes + here, and never emits an undeclared field as a malformed snake_case extra. + """ if not webhooks: return None - return [ - WebhookRepresentation( - event_types=w.event_types, - request_url=w.request_url, - payload_template=w.payload_template, - headers_template=w.headers_template, - ) - for w in webhooks - ] + + return [WebhookRepresentation.model_validate(webhook, from_attributes=True) for webhook in webhooks]