Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 5 additions & 0 deletions .github/workflows/java-integration-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ concurrency:
group: java-integration-${{ github.ref }}
cancel-in-progress: true

# Least-privilege default: this workflow only checks out code and runs tests, it never writes to
# the repository or opens PRs/issues, so the GITHUB_TOKEN needs no more than read access.
permissions:
contents: read

jobs:
test:
runs-on: ubuntu-latest
Expand Down
230 changes: 212 additions & 18 deletions CHANGELOG.md

Large diffs are not rendered by default.

246 changes: 151 additions & 95 deletions README.md

Large diffs are not rendered by default.

108 changes: 82 additions & 26 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
# Apify Java client documentation

> **Official, but experimental — AI-generated and AI-maintained.** This is an official Apify client,
> but it is experimental: it is generated and maintained by AI. Review the code before relying on it
> in production and report issues on the repository.

This directory documents the public API of the Apify Java client, organized by resource. Each page
lists the available methods with their parameters and short snippets. The snippets are code
fragments that assume a configured `client` and the imports listed below, not standalone `main`
programs; for complete, runnable programs see [examples.md](examples.md) and
programs; [examples.md](examples.md) has more fragments in the same style, and the complete,
runnable programs live under
[`src/test/java/com/apify/client/examples/`](https://github.com/apify/apify-client-java/tree/master/src/test/java/com/apify/client/examples). For an
overview, configuration, error handling and the full resource table, see the
[top-level README](../README.md).
Expand All @@ -31,10 +28,39 @@ empty `Optional` rather than an exception. API failures are thrown as `ApifyApiE

## Imports and dependencies

Snippets in these docs assume the client types are imported from `com.apify.client` (e.g.
`import com.apify.client.*;`) plus standard-library types (`java.util.List`, `java.util.ArrayList`,
`java.util.Map`, `java.util.Optional`, `java.util.Iterator`, `java.util.function.Consumer`,
`java.time.Duration`, `java.io.InputStream`).
Client types are **not** all in one package: `import com.apify.client.*;` only resolves
`ApifyClient`, its builder, and the shared kernel types below — a wildcard import does not reach
into sub-packages in Java. Every resource has its own sub-package for its client(s), model(s) and
option types, so import each resource you use from its own package:

| Package | Contains |
|---|---|
| `com.apify.client` (root) | `ApifyClient`, `ApifyClientBuilder`, `Version`, `PaginationList<T>`, `ListOptions`, `StorageListOptions`, `ApifyResource` |
| `com.apify.client.http` | `ApifyClientException`, `ApifyApiException`, `ApifyTransportException`, `HttpTransport`, `DefaultHttpTransport`, `HttpTimeoutException` |
| `com.apify.client.actor` | `Actor`, `ActorClient`, `ActorCollectionClient`, `ActorListOptions`, `ActorStartOptions`, `ActorCallOptions`, `ActorBuildOptions`, `ActorStandby`, `ActorVersion`, `ActorVersionClient`, `ActorVersionCollectionClient`, `ActorEnvVar`, `ActorEnvVarClient`, `ActorEnvVarCollectionClient`, `ValidateInputOptions` |
| `com.apify.client.build` | `Build`, `BuildClient`, `BuildCollectionClient` |
| `com.apify.client.run` | `ActorRun`, `ActorRunStats`, `ActorRunOptions`, `ActorRunMeta`, `ActorRunUsage`, `RunClient`, `RunCollectionClient`, `RunListOptions`, `LastRunOptions`, `MetamorphOptions`, `RunChargeOptions`, `RunResurrectOptions`, `SetStatusMessageOptions` |
| `com.apify.client.dataset` | `Dataset`, `DatasetClient`, `DatasetCollectionClient`, `DatasetListItemsOptions`, `DatasetDownloadOptions`, `DownloadItemsFormat` |
| `com.apify.client.keyvalue` | `KeyValueStore`, `KeyValueStoreClient`, `KeyValueStoreCollectionClient`, `KeyValueStoreRecord`, `KeyValueStoreKeysPage`, `KeyValueStoreKey`, `GetRecordOptions`, `SetRecordOptions`, `ListKeysOptions` |
| `com.apify.client.requestqueue` | `RequestQueue`, `RequestQueueClient`, `RequestQueueCollectionClient`, `RequestQueueRequest`, `RequestQueueHead`, `LockedRequestQueueHead`, `RequestQueueOperationInfo`, `RequestLockInfo`, `UnlockRequestsResult`, `RequestsList`, `BatchAddResult`, `BatchDeleteResult`, `DeletedRequestInfo`, `ListRequestsOptions`, `BatchAddRequestsOptions` |
| `com.apify.client.task` | `Task`, `TaskStats`, `TaskOptions`, `TaskClient`, `TaskCollectionClient`, `TaskStartOptions`, `TaskCallOptions` |
| `com.apify.client.schedule` | `Schedule`, `ScheduleNotifications`, `ScheduleClient`, `ScheduleCollectionClient` |
| `com.apify.client.webhook` | `Webhook`, `WebhookStats`, `WebhookLastDispatch`, `WebhookClient`, `WebhookCollectionClient`, `WebhookDispatchCollectionClient`, `NestedWebhookCollectionClient`, `WebhookDispatch`, `WebhookDispatchClient` |
| `com.apify.client.user` | `User`, `UserClient` |
| `com.apify.client.store` | `ActorStoreListItem`, `StoreCollectionClient`, `StoreListOptions` |
| `com.apify.client.log` | `LogClient`, `LogOptions`, `StreamedLog`, `StreamedLogOptions` |

For example, the [top-level README's dataset snippet](../README.md#quick-start) needs
`com.apify.client.ApifyClient`, `com.apify.client.PaginationList`,
`com.apify.client.dataset.DatasetListItemsOptions`, `com.apify.client.run.ActorRun`,
`com.apify.client.actor.ActorStartOptions` and `com.fasterxml.jackson.databind.JsonNode` — five
different packages for one four-line snippet.

Snippets in these docs also assume the standard-library types they use are imported
(`java.util.List`, `java.util.ArrayList`, `java.util.Map`, `java.util.Optional`,
`java.util.Iterator`, `java.util.UUID`, `java.util.function.Consumer`, `java.time.Duration`,
`java.time.Instant`, `java.io.InputStream`). `java.time.Instant` is returned by many model getters
(e.g. `createdAt`, `modifiedAt`, `nextRunAt`, `lockExpiresAt`).

Raw-JSON return values use Jackson's `com.fasterxml.jackson.databind.JsonNode`. Jackson is a
transitive dependency of this client, so it is already on your classpath.
Expand All @@ -44,34 +70,64 @@ transitive dependency of this client, so it is already on your classpath.
A few methods return data whose shape is not modelled by this client and is instead exposed as a
Jackson `JsonNode` (or accept an arbitrary `Object` serialized to JSON):

- Read: `me().monthlyUsage(...)`, `me().limits()`, `task(id).getInput()`,
`build(id).getOpenApiDefinition()`, `dataset(id).getStatistics()` (returned as
`Optional<JsonNode>`), and the raw request-queue operations (`listRequests`, `listAndLockHead`,
`prolongRequestLock`, `unlockRequests`, `batchDeleteRequests`).
- Write: `task(id).updateInput(...)` and `me().updateLimits(...)` accept an arbitrary
JSON-serializable value, as do definition/`update`/`create` arguments generally — a `Map`, a
`JsonNode`, or your own POJO.
- Read, returning a required `JsonNode` (never absent): `me().monthlyUsage(...)`, `me().limits()`.
- Read, returning `Optional<JsonNode>` (empty when the underlying resource has none): `dataset(id).getStatistics()`,
`task(id).getInput()`, `build(id).getOpenApiDefinition()`.
- Write: `task(id).updateInput(...)` (itself returning a required `JsonNode`, the updated input)
and `me().updateLimits(...)` accept an arbitrary JSON-serializable value, as do
definition/`update`/`create` arguments generally — a `Map`, a `JsonNode`, or your own POJO.
- A few typed models still carry one or more raw-JSON fields where the shape is a discriminated
union (or otherwise not worth fully modelling): `RequestQueueRequest.getUserData()`,
`Webhook.getCondition()`, `Schedule.getActions()` (a `List<JsonNode>`), `Task.getInput()` (the
task's stored input, on the `Task` model itself — distinct from the live-fetching
`task(id).getInput()` client call listed above), and `ActorRun`, which carries two:
`getPricingInfo()` and `getStorageIds()`.

Navigate a `JsonNode` with `node.get("field")`, `node.path("a").asText()`, etc.

The request-queue lock/list operations (`listRequests`, `listAndLockHead`, `prolongRequestLock`,
`unlockRequests`, `batchDeleteRequests`) return typed models (`RequestsList`,
`LockedRequestQueueHead`, `RequestLockInfo`, `UnlockRequestsResult`, `BatchDeleteResult`) rather
than raw `JsonNode` — see [Storages](storages.md#request-queues).

## What `ApifyResource` is

`ApifyResource` (root package) is the base class every response model extends (`Actor`, `Dataset`,
`Schedule`, `ActorRun`, and so on). It has no fields of its own beyond the `extra` map described
below; it exists purely so every model shares one place to capture unmodelled API fields, and so
code that only needs the common capability (rare — most call sites use a concrete model type
directly) can accept `ApifyResource` rather than a specific model.

## Model fields and unmodeled data (`getExtra`)

Response models expose the commonly-used fields as typed getters. The API returns more fields than
are modelled; every model also carries a `getExtra()` map (`Map<String, Object>`) holding any field
not mapped to a typed getter, so nothing the API returns is lost. For example a `Schedule`'s
`actions`/`isExclusive`, or a `me()` `User`'s private account details (email, plan, proxy settings,
…), are available via `getExtra()`.
are modelled; every model also carries a `getExtra()` map (`Map<String, Object>`, inherited from
`ApifyResource` above) holding any field not mapped to a typed getter, so nothing the API returns is
lost. For example a `me()` `User`'s private account details (email, plan, proxy settings, …) are
available via `getExtra()`, since `User` models only its most commonly used fields.

```java
Schedule schedule = client.schedule("SCHEDULE_ID").get().orElseThrow();
Object actions = schedule.getExtra().get("actions");
User me = client.me().get().orElseThrow();
Object plan = me.getExtra().get("plan");
```

## Setting single-resource status
## Setting the current run's status message

`client.setStatusMessage(String message, boolean isTerminal)` updates the status message of the
current Actor run (identified by the `ACTOR_RUN_ID` environment variable); it only works from inside
a run and throws `IllegalStateException` otherwise. Returns the updated `ActorRun`.
`client.setStatusMessage(String message, SetStatusMessageOptions)` (import from
`com.apify.client.run`) updates the status message of the current Actor run (identified by the
`ACTOR_RUN_ID` environment variable); it only works from inside a run and throws
`IllegalStateException` otherwise. `SetStatusMessageOptions.isStatusMessageTerminal(boolean)` marks
the message as final so it won't be overwritten. Returns the updated `ActorRun`.

Note: `isStatusMessageTerminal(boolean)` takes a primitive `boolean`, not a boxed `Boolean` — an
intentional exception to the "optional fields are boxed so they can stay unset" convention used
elsewhere in this client's options classes, since this field always has a concrete on/off meaning
with no useful "unset" state (the field is simply omitted from the request body when the setter is
never called).

```java
client.setStatusMessage("half way there", new SetStatusMessageOptions().isStatusMessageTerminal(false));
```

## Optional option fields

Expand Down
32 changes: 23 additions & 9 deletions docs/actors.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
# Actors, versions & environment variables

> **Official, but experimental — AI-generated and AI-maintained.** This is an official Apify client,
> but it is experimental: it is generated and maintained by AI. Review the code before relying on it
> in production and report issues on the repository.

Access the Actor collection with `client.actors()` and a single Actor with `client.actor(id)`,
where `id` is an Actor ID or `username~name` (a `/` in the id is accepted and normalized).

Expand Down Expand Up @@ -51,8 +47,9 @@ Actor created = client.actors().create(Map.of(
| `update(Object)` | Update the Actor with the given fields. Returns `Actor`. |
| `delete()` | Delete the Actor. |
| `start(Object input, ActorStartOptions)` | Start a run, returning immediately. Returns `ActorRun`. |
| `call(Object input, ActorStartOptions, Long waitSecs)` | Start a run and poll until it finishes (`null` waits indefinitely). Returns `ActorRun`. |
| `validateInput(Object input)` / `validateInput(Object input, ValidateInputOptions)` | Validate an input against the Actor's input schema. Returns `boolean`. `ValidateInputOptions` fields (optional): `build`, `contentType`. |
| `call(Object input, ActorStartOptions, Long waitSecs)` | Start a run and poll until it finishes (`null` waits indefinitely); does **not** stream the run's log. Returns `ActorRun`. |
| `call(Object input, ActorCallOptions, Long waitSecs)` | As above, additionally streaming the run's log for the duration of the wait by default (matching the reference client's `call` defaulting `options.log` to `'default'`). Use `ActorCallOptions.disableLogStreaming()` to opt out, or `logOptions(StreamedLogOptions)` for a custom destination. |
| `validateInput(Object input)` / `validateInput(Object input, ValidateInputOptions)` | Validate an input against the Actor's input schema. Returns `boolean`. `ValidateInputOptions` fields (optional): `build` (`String`), `contentType` (`String`). |
| `build(String versionNumber, ActorBuildOptions)` | Build a version. Returns `Build`. |
| `defaultBuild(Long waitForFinish)` | Resolve the default build. Returns `BuildClient`. |
| `lastRun(String status)` / `lastRun(LastRunOptions)` | A `RunClient` for the last run. |
Expand All @@ -71,6 +68,13 @@ of the input body, defaults to `application/json`), `restartOnError` (restart th
(each a JSON-serializable `Map`, as in [Webhooks](webhooks.md)) that the client base64-encodes on the
wire.

`ActorCallOptions` (for the log-streaming `call` overload) mirrors `ActorStartOptions` field for
field, but omits `waitForFinish`: that field asks the API to hold the HTTP response open
server-side while the run finishes, which is redundant with (and wastes a request slot next to)
`call`'s own client-side `waitSecs` polling. It adds `disableLogStreaming()` (matching the
reference client's `log: null`) and `logOptions(StreamedLogOptions)` (a custom destination/prefix,
matching a custom `Log` instance) — see [Streamed log redirection](runs.md#streamed-log-redirection).

`lastRun(String status)` filters only by status; `lastRun(LastRunOptions)` also accepts an origin
filter. `LastRunOptions` has fluent setters `status(String)` (e.g. `SUCCEEDED`, `RUNNING`) and
`origin(String)` (e.g. `API`, `WEB`, `SCHEDULER`); leave a setter uncalled to omit that filter.
Expand All @@ -87,7 +91,17 @@ System.out.println(run.getStatus());
```

`Actor` fields: `getId()`, `getUserId()`, `getName()`, `getUsername()`, `getTitle()`,
`getDescription()`, `isPublic()`, `getCreatedAt()`, `getModifiedAt()`, plus `getExtra()` for any
`getDescription()`, `isPublic()`, `getCreatedAt()`, `getModifiedAt()`, `getStats()` (`ActorStats` —
`getTotalBuilds()`/`getTotalRuns()`/`getTotalUsers()`/`getTotalUsers7Days()`/
`getTotalUsers30Days()`/`getTotalUsers90Days()`/`getTotalMetamorphs()` as `Long`,
`getLastRunStartedAt()` as `Instant`), `getVersions()` (`List<ActorVersion>`),
`getPricingInfos()` (`List<JsonNode>`; shape depends on pricing model), `getDefaultRunOptions()`
(`ActorDefaultRunOptions` — `getBuild()`, `getTimeoutSecs()`/`getMemoryMbytes()` as `Long`,
`getRestartOnError()` as `Boolean`), `getTaggedBuilds()` (`JsonNode`; dynamic tag-name keys),
`getIsDeprecated()` (`Boolean`), `getDeploymentKey()`, `getSeoTitle()`, `getSeoDescription()`,
`getCategories()` (`List<String>`), `getActorStandby()` (`ActorStandby`, nullable — see
[Tasks](tasks.md) for its field list; only on `Actor` does it additionally expose
`getIsEnabled()`), `getActorPermissionLevel()` (e.g. `"OWNER"`), plus `getExtra()` for any
unmodelled fields.

## `ActorVersionClient` and `ActorVersionCollectionClient`
Expand All @@ -99,8 +113,8 @@ and deletes a single version and exposes its environment variables.

| Method | Description |
|---|---|
| `list(ListOptions)` | List the Actor's versions. Returns `PaginationList<ActorVersion>`. |
| `iterate(ListOptions)` | Lazy `Iterator<ActorVersion>` over all versions; `limit` caps the total (`null`/unset or non-positive = all). The versions endpoint is not paginated (one fetch returns every version), so `offset` has no effect and there is no page size to tune. |
| `list(ListOptions)` | List the Actor's versions. Returns `PaginationList<ActorVersion>`. The endpoint takes no query parameters; `options` (`offset`/`limit`/`desc`) is accepted only for signature consistency with every other `list(ListOptions)` and has no effect — pass `null`. |
| `iterate(ListOptions)` | Lazy `Iterator<ActorVersion>` over all versions; `limit` caps the total (`null`/unset or non-positive = all), applied client-side after the single fetch. `offset` has no effect and there is no page size to tune. |
| `create(Object version)` | Create a version. Returns `ActorVersion`. |

### `ActorVersionClient` — `client.actor(id).version(v)`
Expand Down
Loading
Loading