diff --git a/CHANGELOG.md b/CHANGELOG.md index 903a180..c97f21c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## 0.3.1 + +- Bumped `ApifyClientVersion.ApiSpecVersion` to the Apify OpenAPI spec `v2-2026-08-14T072928Z`. +- Corrected the publish/unpublish permission wording in `TaskClient.PublishAsync`/`UnpublishAsync`, + `docs/tasks.md`, and the `TaskPublishUnpublish` integration test comment: publishing/unpublishing + requires write permission to the task's Actor only, not to the task itself. +- `TaskClient.PublishAsync`'s doc comment and `docs/tasks.md` now state the concrete publish + preconditions from the spec (Actor public, `publicConfig.inputSchemaFields` and + `publicConfig.datasetView` set, Actor has fewer than 50 published tasks). +- Noted in `TaskPublicConfig.Categorization`'s doc comment and `docs/models.md` that the field is + not part of the documented schema and is kept only for parity with the reference JS client. + ## 0.3.0 Breaking: `RequestQueueClient` methods that previously returned a raw `JsonObject`/took an untyped diff --git a/docs/models.md b/docs/models.md index 4c757b7..ef26a51 100644 --- a/docs/models.md +++ b/docs/models.md @@ -124,7 +124,7 @@ An entry returned when browsing the Apify Store. | `PublishedAt` | `string?` | ISO 8601 timestamp the task was published, or `null` if unpublished. Read-only. | | `SeoTitle` | `string?` | Name to display for search engines. | | `SeoDescription` | `string?` | Description to display for search engines. | -| `Categorization` | `string?` | The task's category on its public landing page. | +| `Categorization` | `string?` | The task's category on its public landing page. Not part of the documented `TaskPublicConfig` schema; kept for parity with the reference JS client. | | `InputSchemaFields` | `IReadOnlyList?` | Input schema fields shown on the public landing page. | | `DatasetName` | `string?` | Name of the dataset shown on the public landing page. | | `DatasetView` | `string?` | View of the dataset shown on the public landing page. | diff --git a/docs/tasks.md b/docs/tasks.md index 871a8f1..2884cd9 100644 --- a/docs/tasks.md +++ b/docs/tasks.md @@ -13,12 +13,13 @@ a specific task with `client.Task(id)`. - `GetAsync()` → `ActorTask?`; `UpdateAsync(object newFields)` → `ActorTask`; `DeleteAsync()`. - `PublishAsync()` → `ActorTask` — publishes the task on its public landing page in Apify Store - (sets `isPublic: true`). The task's Actor must be public and the task must already have - `PublicConfig` set up. Requires write permission to both the task and its Actor. Publishing an - already published task does nothing. + (sets `isPublic: true`). The task's Actor must be public, `PublicConfig.InputSchemaFields` and + `PublicConfig.DatasetView` must already be set, and the Actor must have fewer than 50 published + tasks. Requires write permission to the task's Actor. Publishing an already published task does + nothing. - `UnpublishAsync()` → `ActorTask` — unpublishes the task (sets `isPublic: false`); `PublicConfig` is preserved so the task can be published again without re-entering it. Requires write permission to - both the task and its Actor. Unpublishing a task that is not published does nothing. + the task's Actor. Unpublishing a task that is not published does nothing. - `StartAsync(object? input = null, TaskStartOptions? options = null)` → `ActorRun`. - `CallAsync(object? input = null, TaskStartOptions? options = null, int? waitSecs = null, Action? log = null)` → `ActorRun` (`log`, if set, redirects the run's live log to that sink for the duration of the wait). @@ -50,11 +51,15 @@ var run = await client.Task(task.Id!).CallAsync(null, null, 120); Console.WriteLine(run.Status); ``` -Publishing a task requires its Actor to be public and the task to have `PublicConfig` set up first: +Publishing a task requires its Actor to be public and `publicConfig.inputSchemaFields` / +`publicConfig.datasetView` to already be set: ```csharp var taskClient = client.Task(task.Id!); -await taskClient.UpdateAsync(new { publicConfig = new { seoTitle = "My task" } }); +await taskClient.UpdateAsync(new +{ + publicConfig = new { seoTitle = "My task", inputSchemaFields = new[] { "url" }, datasetView = "overview" }, +}); var published = await taskClient.PublishAsync(); Console.WriteLine(published.IsPublic == true); diff --git a/src/Apify.Client/Apify.Client.csproj b/src/Apify.Client/Apify.Client.csproj index 979d0c2..73b45f7 100644 --- a/src/Apify.Client/Apify.Client.csproj +++ b/src/Apify.Client/Apify.Client.csproj @@ -6,7 +6,7 @@ Apify.Client - 0.3.0 + 0.3.1 Apify Apify Apify API client for .NET diff --git a/src/Apify.Client/ApifyClientVersion.cs b/src/Apify.Client/ApifyClientVersion.cs index 6fff84f..5319191 100644 --- a/src/Apify.Client/ApifyClientVersion.cs +++ b/src/Apify.Client/ApifyClientVersion.cs @@ -14,11 +14,11 @@ public static class ApifyClientVersion /// The semantic version of this client library (see https://semver.org/). Changes to the public /// interface other than additive ones are considered breaking changes. /// - public const string ClientVersion = "0.3.0"; + public const string ClientVersion = "0.3.1"; /// /// The version of the Apify OpenAPI specification this client was generated and verified against. /// Corresponds to the info.version field of the Apify OpenAPI document. /// - public const string ApiSpecVersion = "v2-2026-08-05T133145Z"; + public const string ApiSpecVersion = "v2-2026-08-14T072928Z"; } diff --git a/src/Apify.Client/Models/TaskPublicConfig.cs b/src/Apify.Client/Models/TaskPublicConfig.cs index 4694738..4776e7e 100644 --- a/src/Apify.Client/Models/TaskPublicConfig.cs +++ b/src/Apify.Client/Models/TaskPublicConfig.cs @@ -29,7 +29,11 @@ public TaskPublicConfig(JsonObject data) /// Description to display for search engines such as Google. public string? SeoDescription => GetString("seoDescription"); - /// The task's category on its public landing page. + /// + /// The task's category on its public landing page. Not part of the documented OpenAPI schema for + /// this resource; kept for parity with the reference JS client, which exposes the same + /// undocumented field. + /// public string? Categorization => GetString("categorization"); /// The input schema fields shown on the public landing page. diff --git a/src/Apify.Client/Resources/TaskClient.cs b/src/Apify.Client/Resources/TaskClient.cs index 957b1cf..7cfdc7c 100644 --- a/src/Apify.Client/Resources/TaskClient.cs +++ b/src/Apify.Client/Resources/TaskClient.cs @@ -54,9 +54,10 @@ public async Task UpdateAsync(object newFields, CancellationToken can /// through . /// /// - /// The task's Actor must be public and the task must already have its public display - /// configuration () set up. Requires write permission to both - /// the task and its Actor. Publishing an already published task does nothing. + /// The task's Actor must be public, 's InputSchemaFields + /// and DatasetView must already be set, and the Actor must have fewer than 50 published + /// tasks. Requires write permission to the task's Actor. Publishing an already published task + /// does nothing. /// /// A token to cancel the request. public Task PublishAsync(CancellationToken cancellationToken = default) => @@ -68,8 +69,8 @@ public Task PublishAsync(CancellationToken cancellationToken = defaul /// /// /// The public display configuration () is preserved, so the - /// task can be published again without re-entering it. Requires write permission to both the task - /// and its Actor. Unpublishing a task that is not published does nothing. + /// task can be published again without re-entering it. Requires write permission to the task's + /// Actor. Unpublishing a task that is not published does nothing. /// /// A token to cancel the request. public Task UnpublishAsync(CancellationToken cancellationToken = default) => diff --git a/tests/Apify.Client.Tests/Integration/TaskIntegrationTests.cs b/tests/Apify.Client.Tests/Integration/TaskIntegrationTests.cs index d45f32d..bbbb86c 100644 --- a/tests/Apify.Client.Tests/Integration/TaskIntegrationTests.cs +++ b/tests/Apify.Client.Tests/Integration/TaskIntegrationTests.cs @@ -78,8 +78,8 @@ public async Task TaskPublishUnpublish() Assert.Equal(task.Id, unpublished.Id); Assert.True(unpublished.IsPublic != true); - // Publishing requires write permission to both the task and its Actor (apify/hello-world), - // which the test account does not have, so this is expected to fail rather than succeed. + // Publishing requires write permission to the task's Actor (apify/hello-world), which the + // test account does not have, so this is expected to fail rather than succeed. var ex = await Assert.ThrowsAsync(() => tc.PublishAsync()); Assert.True(ex.StatusCode is 400 or 403); }