Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
6aebd3b
refactor!: adapt to apify-client v3
vdusek May 27, 2026
ed4fcd0
refactor!: wrap client webhook models in a single `Webhook` class
vdusek May 28, 2026
8a743f0
refactor: accept `idempotency_key` as kwarg on `Actor.add_webhook`
vdusek May 28, 2026
a3f3fd3
refactor: deprecate `idempotency_key` kwarg on `Actor.add_webhook`
vdusek May 28, 2026
f1bc435
chore: drop `__all__` from internal `_apify/_models.py`
vdusek May 28, 2026
9cacc1b
docs: add v4 upgrading guide covering the new `Webhook` API
vdusek May 28, 2026
34391b7
refactor!: align `Actor.new_client` with apify-client v3 interface
vdusek May 28, 2026
a23a8b5
docs: keep webhook migration only in v4 guide
vdusek May 28, 2026
674b571
refactor: keep single `timeout` on `Actor.new_client`, scale client t…
vdusek May 28, 2026
fbfe22c
refactor: make `timeout_max` strictly greater than `timeout_long` in …
vdusek May 28, 2026
3b2a391
refactor: pass `ApifyClientAsync` kwargs directly in `Actor.new_client`
vdusek May 28, 2026
1e6a8be
refactor: replace `ActorExitCodes` enum with int constants
vdusek May 28, 2026
5a13075
refactor: convert SDK `Webhook` from pydantic model to dataclass
vdusek May 28, 2026
d2ee470
docs: drop misleading notes on `Webhook` field docstrings
vdusek May 28, 2026
1ce478e
refactor!: introduce SDK-side `ActorPricingInfo` data structures
vdusek May 28, 2026
8f328f9
refactor: fold `_pricing` module into `_charging`
vdusek May 28, 2026
383f28d
docs: round out v4 upgrading guide with remaining breaking changes
vdusek May 28, 2026
59d6405
refactor: re-introduce `ActorEventTypes` as a `Literal` alias
vdusek May 28, 2026
f51aebe
revert: drop SDK-side `ActorPricingInfo` rewrite
vdusek May 28, 2026
079215a
refactor: keep SDK-side pricing models, drop env-var workaround
vdusek May 28, 2026
102881c
refactor: fold pricing models into `_charging`
vdusek May 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/02_concepts/code/07_webhook.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import asyncio

from apify import Actor, Webhook, WebhookEventType
from apify import Actor, Webhook


async def main() -> None:
async with Actor:
# Create a webhook that will be triggered when the Actor run fails.
webhook = Webhook(
event_types=[WebhookEventType.ACTOR_RUN_FAILED],
event_types=['ACTOR.RUN.FAILED'],
request_url='https://example.com/run-failed',
)

Expand Down
9 changes: 5 additions & 4 deletions docs/02_concepts/code/07_webhook_preventing.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import asyncio

from apify import Actor, Webhook, WebhookEventType
from apify import Actor, Webhook


async def main() -> None:
async with Actor:
# Create a webhook that will be triggered when the Actor run fails.
# Create a webhook with an idempotency key to prevent duplicates on retries.
webhook = Webhook(
event_types=[WebhookEventType.ACTOR_RUN_FAILED],
event_types=['ACTOR.RUN.FAILED'],
request_url='https://example.com/run-failed',
idempotency_key=Actor.configuration.actor_run_id,
)

# Add the webhook to the Actor.
await Actor.add_webhook(webhook, idempotency_key=Actor.configuration.actor_run_id)
await Actor.add_webhook(webhook)

# Raise an error to simulate a failed run.
raise RuntimeError('I am an error and I know it!')
Expand Down
74 changes: 72 additions & 2 deletions docs/04_upgrading/upgrading_to_v4.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,78 @@ title: Upgrading to v4
description: Breaking changes and migration guide from Apify SDK v3.x to v4.0.
---

This guide lists the breaking changes between Apify Python SDK v3.x and v4.0.
This page summarizes the breaking changes between Apify Python SDK v3.x and v4.0.

## Python 3.11+ required

Support for Python 3.10 has been dropped. The Apify Python SDK v4.x now requires Python 3.11 or later — make sure your environment is on a compatible version before upgrading.
Support for Python 3.10 has been dropped. Apify Python SDK v4.x requires Python 3.11 or later.

## `apify-client` v3 required

The SDK is now built on `apify-client` v3 and no longer depends on `apify-shared`. Three changes are user-visible:

- `Actor.start`, `Actor.call`, `Actor.call_task`, and `Actor.metamorph` return `apify_client._models.Run` instead of the SDK-side `ActorRun`. The shape is equivalent — only the import path changes.
- `apify.WebhookEventType` is now a `Literal[...]` instead of a `StrEnum`. Use plain string values (`'ACTOR.RUN.FAILED'`) instead of enum members.
- `apify_shared.consts.ActorEventTypes` (a `StrEnum`) is replaced by `apify.ActorEventTypes`, now a `Literal['systemInfo', 'persistState', 'migrating', 'aborting']`. For runtime values, use `apify.Event` (re-exported from Crawlee) instead of enum members.

**Before (v3.x):**

```python
from apify import Actor
from apify_shared.consts import ActorEventTypes

Actor.on(ActorEventTypes.SYSTEM_INFO, callback)
```

**Now (v4.0):**

```python
from apify import Actor, Event

Actor.on(Event.SYSTEM_INFO, callback)
```

## `Webhook` API simplified

The `Webhook` model has been slimmed down to only the fields a user sets when defining a webhook. Server-populated response fields (`id`, `created_at`, `modified_at`, `user_id`, `is_ad_hoc`, `condition`, `last_dispatch`, `stats`) and the unused `WebhookCondition` helper class have been removed. `Webhook` is now a plain `@dataclass` instead of a Pydantic `BaseModel` — construct it with snake_case kwargs; `.model_dump()` / `.model_validate()` are gone.

The retry and idempotency kwargs that used to live on `Actor.add_webhook` have moved onto the `Webhook` instance itself.

**Before (v3.x):**

```python
from apify import Actor, Webhook

await Actor.add_webhook(
Webhook(event_types=['ACTOR.RUN.FAILED'], request_url='https://example.com'),
ignore_ssl_errors=False,
do_not_retry=False,
idempotency_key='my-key',
)
```

**Now (v4.0):**

```python
from apify import Actor, Webhook

await Actor.add_webhook(
Webhook(
event_types=['ACTOR.RUN.FAILED'],
request_url='https://example.com',
ignore_ssl_errors=False,
do_not_retry=False,
idempotency_key='my-key',
)
)
```

The `idempotency_key` kwarg form on `Actor.add_webhook` still works for one more release but emits a `DeprecationWarning` and will be removed in v5.0. The `ignore_ssl_errors` and `do_not_retry` kwargs have been removed outright — set them on the `Webhook` instance.

`apify.WebhookCondition` is no longer exported; the SDK now binds the webhook to the current Actor run internally.

The `webhooks` argument on `Actor.start`, `Actor.call`, and `Actor.call_task` still accepts `list[Webhook]` and the fields used at the call site (`event_types`, `request_url`, `payload_template`, `headers_template`) are unchanged.

## `Actor.new_client` — `timeout` scales all tiers

`apify-client` v3 split its single timeout into four tiers (short / medium / long / max). `Actor.new_client(timeout=...)` still takes a single `timedelta`; the SDK uses it as the medium-tier baseline and scales the other tiers proportionally (short = `timeout / 6`, long = `timeout * 12`, max = `timeout * 24`). The public signature is unchanged — no migration needed.
7 changes: 3 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,14 @@ keywords = [
"scraping",
]
dependencies = [
"apify-client>=2.3.0,<3.0.0",
"apify-shared>=2.0.0,<3.0.0",
"apify-client>=3.0.0,<4.0.0",
"crawlee>=1.0.4,<2.0.0",
"cachetools>=5.5.0",
"cryptography>=42.0.0",
"impit>=0.8.0",
"lazy-object-proxy>=1.11.0",
"more_itertools>=10.2.0",
"pydantic>=2.11.0",
"pydantic[email]>=2.11.0",
"typing-extensions>=4.1.0",
"websockets>=14.0",
"yarl>=1.18.0",
Expand Down Expand Up @@ -197,7 +196,7 @@ builtins-ignorelist = ["id"]

[tool.ruff.lint.isort]
known-local-folder = ["apify"]
known-first-party = ["apify_client", "apify_shared", "crawlee"]
known-first-party = ["apify_client", "crawlee"]

[tool.ruff.lint.pylint]
max-branches = 18
Expand Down
6 changes: 4 additions & 2 deletions src/apify/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from importlib import metadata

from apify_shared.consts import WebhookEventType
from apify_client._literals import WebhookEventType
from crawlee import Request
from crawlee.events import (
Event,
Expand All @@ -14,13 +14,15 @@

from apify._actor import Actor
from apify._configuration import Configuration
from apify._models import Webhook
from apify._proxy_configuration import ProxyConfiguration, ProxyInfo
from apify._webhook import Webhook
from apify.events._types import ActorEventTypes

__version__ = metadata.version('apify')

__all__ = [
'Actor',
'ActorEventTypes',
'Configuration',
'Event',
'EventAbortingData',
Expand Down
Loading
Loading