Skip to content

Commit 139a426

Browse files
feat: add Actor task publication endpoints (#985)
- Add publish() / unpublish() methods to TaskClient and TaskClientAsync — convenience wrappers over update() that toggle the task's publication on its public landing page. - Add is_public and public_config_* arguments (SEO title/description, input schema fields, dataset name/view) to TaskClient.update() and TaskCollectionClient.create(), sync and async. - Regenerate models from the updated OpenAPI spec (apify-docs #2840): new TaskPublicConfig model, plus is_public and public_config fields on Task, CreateTaskRequest, and UpdateTaskRequest. - Add unit tests for task publication (tests/unit/test_task_publication.py) and move the shared sync_client / async_client fixtures into tests/unit/conftest.py. --------- Co-authored-by: Jan (Honza) Jiráň <jan.jiran@apify.com>
1 parent 3caaa2b commit 139a426

6 files changed

Lines changed: 530 additions & 11 deletions

File tree

‎src/apify_client/_models.py‎

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -883,6 +883,13 @@ class CreateTaskRequest(BaseModel):
883883
input: TaskInput | None = None
884884
title: str | None = None
885885
actor_standby: ActorStandby | None = None
886+
public_config: TaskPublicConfig | None = None
887+
"""
888+
Public-facing display configuration of the task's public landing page. The task is not
889+
published by setting it — set `isPublic` via the [Update task](https://docs.apify.com/api/v2/actor-task-put)
890+
endpoint for that. Setting `publicConfig` requires write permission to the task's Actor.
891+
892+
"""
886893

887894

888895
@docs_group('Models')
@@ -3496,6 +3503,14 @@ class Task(BaseModel):
34963503
title: str | None = None
34973504
actor_standby: ActorStandby | None = None
34983505
standby_url: AnyUrl | None = None
3506+
is_public: Annotated[bool | None, Field(examples=[False])] = None
3507+
"""
3508+
Whether the task is published on its public landing page. Derived from
3509+
`publicConfig.publishedAt`. Set it via the [Update task](https://docs.apify.com/api/v2/actor-task-put)
3510+
endpoint to publish or unpublish the task.
3511+
3512+
"""
3513+
public_config: TaskPublicConfig | None = None
34993514

35003515

35013516
@docs_group('Models')
@@ -3527,6 +3542,52 @@ class TaskOptions(BaseModel):
35273542
restart_on_error: Annotated[bool | None, Field(examples=[False])] = None
35283543

35293544

3545+
@docs_group('Models')
3546+
class TaskPublicConfig(BaseModel):
3547+
"""Public-facing configuration of a published task, used by the task's public landing page.
3548+
The task's publication state is determined by `publishedAt` - a task is published when
3549+
`publishedAt` is set and unpublished when it is `null`.
3550+
3551+
"""
3552+
3553+
model_config = ConfigDict(
3554+
extra='allow',
3555+
populate_by_name=True,
3556+
alias_generator=to_camel,
3557+
)
3558+
published_at: Annotated[AwareDatetime | None, Field(examples=['2025-06-16T09:20:45.777Z'])] = None
3559+
"""
3560+
Time when the task was published, or `null` if the task is not published.
3561+
This field is server-controlled - to publish or unpublish a task, set `isPublic`
3562+
via the [Update task](https://docs.apify.com/api/v2/actor-task-put) endpoint.
3563+
3564+
"""
3565+
seo_title: Annotated[str | None, Field(examples=['Scrape data from a website'])] = None
3566+
"""
3567+
SEO title of the public task page. Defaults to the task title when not set.
3568+
"""
3569+
seo_description: str | None = None
3570+
"""
3571+
SEO description of the public task page. Defaults to the task description when not set.
3572+
"""
3573+
categorization: str | None = None
3574+
"""
3575+
Use-case category of the public task.
3576+
"""
3577+
input_schema_fields: list[str] | None = None
3578+
"""
3579+
Names of the task input fields displayed on the public task page.
3580+
"""
3581+
dataset_name: str | None = None
3582+
"""
3583+
Name of the dataset from the Actor's dataset schema whose results are displayed.
3584+
"""
3585+
dataset_view: str | None = None
3586+
"""
3587+
Key of the dataset view from the Actor's dataset schema used to display results.
3588+
"""
3589+
3590+
35303591
@docs_group('Models')
35313592
class TaskResponse(BaseModel):
35323593
"""Response containing Actor task data."""
@@ -3802,6 +3863,22 @@ class UpdateTaskRequest(BaseModel):
38023863
input: TaskInput | None = None
38033864
title: str | None = None
38043865
actor_standby: ActorStandby | None = None
3866+
public_config: TaskPublicConfig | None = None
3867+
"""
3868+
Public-facing display configuration of the task's public landing page. The provided
3869+
fields are merged into the stored configuration and validated. The stored configuration
3870+
cannot be cleared this way. Set `isPublic` to change the publication state.
3871+
Updating `publicConfig` requires write permission to the task's Actor.
3872+
3873+
"""
3874+
is_public: Annotated[bool | None, Field(examples=[True])] = None
3875+
"""
3876+
Set to `true` to publish the task on its public landing page, or `false` to unpublish it.
3877+
Sending the value the task already has does nothing. Publishing requires the task's
3878+
`publicConfig` to be filled in and write permission to the task's Actor; it fails if the
3879+
task is not ready to be published, leaving the rest of the update unapplied.
3880+
3881+
"""
38053882

38063883

38073884
@docs_group('Models')

‎src/apify_client/_resource_clients/task.py‎

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
Task,
1111
TaskInput,
1212
TaskOptions,
13+
TaskPublicConfig,
1314
TaskResponse,
1415
UpdateTaskRequest,
1516
)
@@ -83,6 +84,12 @@ def update(
8384
actor_standby_idle_timeout: timedelta | None = None,
8485
actor_standby_build: str | None = None,
8586
actor_standby_memory_mbytes: int | None = None,
87+
is_public: bool | None = None,
88+
public_config_seo_title: str | None = None,
89+
public_config_seo_description: str | None = None,
90+
public_config_input_schema_fields: list[str] | None = None,
91+
public_config_dataset_name: str | None = None,
92+
public_config_dataset_view: str | None = None,
8693
timeout: Timeout = 'short',
8794
) -> Task:
8895
"""Update the task with specified fields.
@@ -111,6 +118,16 @@ def update(
111118
it will be shut down.
112119
actor_standby_build: The build tag or number to run when the Actor is in Standby mode.
113120
actor_standby_memory_mbytes: The memory in megabytes to use when the Actor is in Standby mode.
121+
is_public: Set to `True` to publish the task on its public landing page, or `False` to unpublish it.
122+
Passing the value the task already has does nothing. Publishing requires the public display
123+
configuration to be filled in, and write access to the task's Actor.
124+
public_config_seo_title: SEO title of the public task page. Defaults to the task title when not set.
125+
public_config_seo_description: SEO description of the public task page. Defaults to the task description
126+
when not set.
127+
public_config_input_schema_fields: Names of the task input fields displayed on the public task page.
128+
public_config_dataset_name: Name of the dataset from the Actor's dataset schema whose results are
129+
displayed on the public task page.
130+
public_config_dataset_view: View key from the Actor's dataset schema shown on the public task page.
114131
timeout: Timeout for the API HTTP request.
115132
116133
Returns:
@@ -123,6 +140,14 @@ def update(
123140
name=name,
124141
title=title,
125142
input=task_input,
143+
is_public=is_public,
144+
public_config=TaskPublicConfig(
145+
seo_title=public_config_seo_title,
146+
seo_description=public_config_seo_description,
147+
input_schema_fields=public_config_input_schema_fields,
148+
dataset_name=public_config_dataset_name,
149+
dataset_view=public_config_dataset_view,
150+
),
126151
options=TaskOptions(
127152
build=build,
128153
max_items=max_items,
@@ -141,6 +166,40 @@ def update(
141166
result = self._update(timeout=timeout, **task_fields.model_dump(by_alias=True, exclude_none=True))
142167
return TaskResponse.model_validate(result).data
143168

169+
def publish(self, *, timeout: Timeout = 'short') -> Task:
170+
"""Publish the task on its public landing page.
171+
172+
Convenience wrapper over `update` with `is_public` set to `True`. The task's Actor must be public and
173+
the task must have its public display configuration set up. Requires write access to the task and to its
174+
Actor. Publishing an already published task does nothing.
175+
176+
https://docs.apify.com/api/v2#/reference/actor-tasks/task-object/update-task
177+
178+
Args:
179+
timeout: Timeout for the API HTTP request.
180+
181+
Returns:
182+
The published task.
183+
"""
184+
return self.update(is_public=True, timeout=timeout)
185+
186+
def unpublish(self, *, timeout: Timeout = 'short') -> Task:
187+
"""Unpublish the task from its public landing page.
188+
189+
Convenience wrapper over `update` with `is_public` set to `False`. The public display configuration is
190+
preserved, so the task can be published again without re-entering it. Requires write access to the task
191+
and to its Actor. Unpublishing a task that is not published does nothing.
192+
193+
https://docs.apify.com/api/v2#/reference/actor-tasks/task-object/update-task
194+
195+
Args:
196+
timeout: Timeout for the API HTTP request.
197+
198+
Returns:
199+
The unpublished task.
200+
"""
201+
return self.update(is_public=False, timeout=timeout)
202+
144203
def delete(self, *, timeout: Timeout = 'short') -> None:
145204
"""Delete the task.
146205
@@ -406,6 +465,12 @@ async def update(
406465
actor_standby_idle_timeout: timedelta | None = None,
407466
actor_standby_build: str | None = None,
408467
actor_standby_memory_mbytes: int | None = None,
468+
is_public: bool | None = None,
469+
public_config_seo_title: str | None = None,
470+
public_config_seo_description: str | None = None,
471+
public_config_input_schema_fields: list[str] | None = None,
472+
public_config_dataset_name: str | None = None,
473+
public_config_dataset_view: str | None = None,
409474
timeout: Timeout = 'short',
410475
) -> Task:
411476
"""Update the task with specified fields.
@@ -434,6 +499,16 @@ async def update(
434499
it will be shut down.
435500
actor_standby_build: The build tag or number to run when the Actor is in Standby mode.
436501
actor_standby_memory_mbytes: The memory in megabytes to use when the Actor is in Standby mode.
502+
is_public: Set to `True` to publish the task on its public landing page, or `False` to unpublish it.
503+
Passing the value the task already has does nothing. Publishing requires the public display
504+
configuration to be filled in, and write access to the task's Actor.
505+
public_config_seo_title: SEO title of the public task page. Defaults to the task title when not set.
506+
public_config_seo_description: SEO description of the public task page. Defaults to the task description
507+
when not set.
508+
public_config_input_schema_fields: Names of the task input fields displayed on the public task page.
509+
public_config_dataset_name: Name of the dataset from the Actor's dataset schema whose results are
510+
displayed on the public task page.
511+
public_config_dataset_view: View key from the Actor's dataset schema shown on the public task page.
437512
timeout: Timeout for the API HTTP request.
438513
439514
Returns:
@@ -446,6 +521,14 @@ async def update(
446521
name=name,
447522
title=title,
448523
input=task_input,
524+
is_public=is_public,
525+
public_config=TaskPublicConfig(
526+
seo_title=public_config_seo_title,
527+
seo_description=public_config_seo_description,
528+
input_schema_fields=public_config_input_schema_fields,
529+
dataset_name=public_config_dataset_name,
530+
dataset_view=public_config_dataset_view,
531+
),
449532
options=TaskOptions(
450533
build=build,
451534
max_items=max_items,
@@ -464,6 +547,40 @@ async def update(
464547
result = await self._update(timeout=timeout, **task_fields.model_dump(by_alias=True, exclude_none=True))
465548
return TaskResponse.model_validate(result).data
466549

550+
async def publish(self, *, timeout: Timeout = 'short') -> Task:
551+
"""Publish the task on its public landing page.
552+
553+
Convenience wrapper over `update` with `is_public` set to `True`. The task's Actor must be public and
554+
the task must have its public display configuration set up. Requires write access to the task and to its
555+
Actor. Publishing an already published task does nothing.
556+
557+
https://docs.apify.com/api/v2#/reference/actor-tasks/task-object/update-task
558+
559+
Args:
560+
timeout: Timeout for the API HTTP request.
561+
562+
Returns:
563+
The published task.
564+
"""
565+
return await self.update(is_public=True, timeout=timeout)
566+
567+
async def unpublish(self, *, timeout: Timeout = 'short') -> Task:
568+
"""Unpublish the task from its public landing page.
569+
570+
Convenience wrapper over `update` with `is_public` set to `False`. The public display configuration is
571+
preserved, so the task can be published again without re-entering it. Requires write access to the task
572+
and to its Actor. Unpublishing a task that is not published does nothing.
573+
574+
https://docs.apify.com/api/v2#/reference/actor-tasks/task-object/update-task
575+
576+
Args:
577+
timeout: Timeout for the API HTTP request.
578+
579+
Returns:
580+
The unpublished task.
581+
"""
582+
return await self.update(is_public=False, timeout=timeout)
583+
467584
async def delete(self, *, timeout: Timeout = 'short') -> None:
468585
"""Delete the task.
469586

‎src/apify_client/_resource_clients/task_collection.py‎

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
Task,
1212
TaskInput,
1313
TaskOptions,
14+
TaskPublicConfig,
1415
TaskResponse,
1516
)
1617
from apify_client._pagination import get_items_iterator, get_items_iterator_async
@@ -116,10 +117,18 @@ def create(
116117
actor_standby_idle_timeout: timedelta | None = None,
117118
actor_standby_build: str | None = None,
118119
actor_standby_memory_mbytes: int | None = None,
120+
public_config_seo_title: str | None = None,
121+
public_config_seo_description: str | None = None,
122+
public_config_input_schema_fields: list[str] | None = None, # ty: ignore[invalid-type-form]
123+
public_config_dataset_name: str | None = None,
124+
public_config_dataset_view: str | None = None,
119125
timeout: Timeout = 'medium',
120126
) -> Task:
121127
"""Create a new task.
122128
129+
The `public_config_*` arguments set the public display configuration of the task's landing page, which
130+
requires write access to the task's Actor and the task itself. Use `TaskClient.publish` for publishing.
131+
123132
https://docs.apify.com/api/v2#/reference/actor-tasks/task-collection/create-task
124133
125134
Args:
@@ -145,6 +154,13 @@ def create(
145154
it will be shut down.
146155
actor_standby_build: The build tag or number to run when the Actor is in Standby mode.
147156
actor_standby_memory_mbytes: The memory in megabytes to use when the Actor is in Standby mode.
157+
public_config_seo_title: SEO title of the public task page. Defaults to the task title when not set.
158+
public_config_seo_description: SEO description of the public task page. Defaults to the task description
159+
when not set.
160+
public_config_input_schema_fields: Names of the task input fields displayed on the public task page.
161+
public_config_dataset_name: Name of the dataset from the Actor's dataset schema whose results are
162+
displayed on the public task page.
163+
public_config_dataset_view: View key from the Actor's dataset schema shown on the public task page.
148164
timeout: Timeout for the API HTTP request.
149165
150166
Returns:
@@ -158,6 +174,13 @@ def create(
158174
name=name,
159175
title=title,
160176
input=task_input,
177+
public_config=TaskPublicConfig(
178+
seo_title=public_config_seo_title,
179+
seo_description=public_config_seo_description,
180+
input_schema_fields=public_config_input_schema_fields,
181+
dataset_name=public_config_dataset_name,
182+
dataset_view=public_config_dataset_view,
183+
),
161184
options=TaskOptions(
162185
build=build,
163186
max_items=max_items,
@@ -267,10 +290,18 @@ async def create(
267290
actor_standby_idle_timeout: timedelta | None = None,
268291
actor_standby_build: str | None = None,
269292
actor_standby_memory_mbytes: int | None = None,
293+
public_config_seo_title: str | None = None,
294+
public_config_seo_description: str | None = None,
295+
public_config_input_schema_fields: list[str] | None = None, # ty: ignore[invalid-type-form]
296+
public_config_dataset_name: str | None = None,
297+
public_config_dataset_view: str | None = None,
270298
timeout: Timeout = 'medium',
271299
) -> Task:
272300
"""Create a new task.
273301
302+
The `public_config_*` arguments set the public display configuration of the task's landing page, which
303+
requires write access to the task's Actor and the task itself. Use `TaskClientAsync.publish` for publishing.
304+
274305
https://docs.apify.com/api/v2#/reference/actor-tasks/task-collection/create-task
275306
276307
Args:
@@ -296,6 +327,13 @@ async def create(
296327
it will be shut down.
297328
actor_standby_build: The build tag or number to run when the Actor is in Standby mode.
298329
actor_standby_memory_mbytes: The memory in megabytes to use when the Actor is in Standby mode.
330+
public_config_seo_title: SEO title of the public task page. Defaults to the task title when not set.
331+
public_config_seo_description: SEO description of the public task page. Defaults to the task description
332+
when not set.
333+
public_config_input_schema_fields: Names of the task input fields displayed on the public task page.
334+
public_config_dataset_name: Name of the dataset from the Actor's dataset schema whose results are
335+
displayed on the public task page.
336+
public_config_dataset_view: View key from the Actor's dataset schema shown on the public task page.
299337
timeout: Timeout for the API HTTP request.
300338
301339
Returns:
@@ -309,6 +347,13 @@ async def create(
309347
name=name,
310348
title=title,
311349
input=task_input,
350+
public_config=TaskPublicConfig(
351+
seo_title=public_config_seo_title,
352+
seo_description=public_config_seo_description,
353+
input_schema_fields=public_config_input_schema_fields,
354+
dataset_name=public_config_dataset_name,
355+
dataset_view=public_config_dataset_view,
356+
),
312357
options=TaskOptions(
313358
build=build,
314359
max_items=max_items,

0 commit comments

Comments
 (0)