- Bumped
Version::API_SPEC_VERSIONto the Apify OpenAPI specv2-2026-08-14T072928Z. This version formally addsTask.isPublic/publicConfigand theTaskPublicConfigschema to the spec; this client already implemented them in0.4.0, ahead of the spec, for parity with the reference JS client. No client code or public interface change.
- Corrected the write-permission wording on
TaskClient::publish()/unpublish(): the OpenAPI spec states that bothisPublicandpublicConfigrequire write permission to the task's Actor, not (asunpublish()'s docblock previously claimed) permission to the task alone.publish()'s docblock now also states the Actor's fewer-than-50-published-tasks limit. docs/tasks.mdupdated to match.
Breaking: RequestQueueClient methods that previously returned a raw array<string,mixed> (or, for
batchDeleteRequests, accepted an untyped mixed argument) now use typed models, matching the
OpenAPI-documented response schemas and the reference client's typed result interfaces:
listAndLockHead()now returnsLockedRequestQueueHead(wasarray).prolongRequestLock()now returnsRequestLockInfo(wasarray).unlockRequests()now returnsUnlockRequestsResult(wasarray).listRequests()now returnsRequestQueueRequestsPage(wasarray).batchDeleteRequests()now takeslist<RequestQueueRequest>and returnsBatchDeleteResult(wasmixed $requests/array).RequestQueueHeadand the newLockedRequestQueueHeadgained the previously-missinggetQueueModifiedAt()getter (the field is present in the OpenAPI spec and the reference client, but was not yet exposed by this client).RequestQueueRequestgainedgetRetryCount()/getLockExpiresAt()getters, populated on requests returned bylistHead()/listAndLockHead()/listRequests().batchDeleteRequests()now throwsInvalidArgumentExceptionup front for an empty or over-25-request input, or for any entry missing a non-emptyid/uniqueKey, matchingbatchAddRequests()'s and the reference client's validation.- Integration tests: every "create a resource, then
iterate()the collection and assert it is present" test now retries the iterate-and-check pass with a bounded backoff (via a newIntegrationTestCase::assertEventuallyIterated()helper) instead of asserting after a single pass. Apify's list/pagination endpoints are eventually consistent, and this suite runs concurrently with other language clients against the same shared test account, so a resource created immediately before aniterate()call could occasionally not yet be reflected in the listing; this was causing intermittent CI failures unrelated to any client defect. No test's assertion was weakened - each still fails if the resource never appears within the timeout.
- Synced to Apify OpenAPI spec
v2-2026-08-05T133145Z(additive nullability/response/description changes only; no client code changes required beyond the version constant). - Added
TaskClient::publish()andTaskClient::unpublish()convenience methods (mirroring the reference JS client), plusTask::isPublic()andTask::getPublicConfig()getters. - Removed the duplicated "official, but experimental, AI-generated" disclaimer from
docs/README.mdand theApifyClientclass docblock; it is now stated only once, in the top-levelREADME.md.
- Synced to Apify OpenAPI spec
v2-2026-07-13T092445Z(adds402/408error responses to the synchronous run and run-resurrect endpoints; relaxes store/run/build/webhook stats counters to optional). No public interface or code changes.
- Added
failOnEmptyTestSuite="true"tophpunit.xml.distso a suite matching zero tests fails instead of passing green. - Replaced magic literals with named constants:
HttpClientCore::attemptTimeout()now scales the per-attempt timeout by a dedicatedTIMEOUT_BACKOFF_FACTORconstant, andJson::decode()uses a namedMAX_JSON_DEPTHconstant. - Corrected the
RunClient::get()andBuildClient::get()doc comments to explain that thewaitForFinishSecsvalue is clamped client-side to the request-timeout budget and additionally capped at 60s by the server. - Reworded the docs namespace table so the
Optionsrow no longer implies its example list is exhaustive.
- Fixed
RunClient::metamorph()to normalize a slash-formtargetActorId(e.g.username/actor-name) to the URL-safeusername~actor-nameform before sending it, matching the reference JS client. - Documented the expected
YYYY-MM-DDdate format forme()->monthlyUsage()in the docs. - Expanded the docs namespace table with the commonly-used option classes so their
usenamespace is discoverable.
- Fixed
KeyValueStoreClient::iterateKeys()so alimitof0(likenull) iterates the whole store instead of stopping after a single page; a positivelimitstill caps the total keys yielded across all pages. - Documented the
bool $forefrontparameter on the request-queueaddRequest/updateRequest/prolongRequestLock/deleteRequestLockmethods and the?bool $gracefullyparameter onrun()->abort(), and added behavior descriptions forrecordExists,setRecordJson,deleteRecord,getRecordPublicUrl,createKeysPublicUrl, andcreateItemsPublicUrl. - Corrected the README error-handling description so the "4xx are thrown" rule notes its exception:
a 404 on a single-resource fetch returns
nullfromget()and is a no-op fordelete(). - Added the optional
baseUrlargument to the README configuration snippet and documented thatpaginateRequests()yieldsRequestQueueRequestinstances. - Fixed
RequestQueueClient::paginateRequests()so alimitof0(likenull) iterates all requests instead of yielding a single page, matchingiterateKeysand the offset paginator. - Documented that combining item-dropping dataset filters (
skipEmpty, andcleanwhich implies it) with multi-pageiterateItems()can repeat or skip items, mirroring the reference JS client's offset advancement.
- Added lazy iteration helpers matching the reference client, which iterates every collection: an
iterate()generator on the Actor, Actor-version, Actor-env-var, build, run, dataset, key-value-store, request-queue, schedule, task, webhook (account-wide and nested) and webhook-dispatch collections;DatasetClient::iterateItems()for dataset items; andKeyValueStoreClient::iterateKeys()for store keys (cursor-based). Each fetches pages on demand. - Iteration
limitsemantics: for the offset/limit iterators, the options'limitnow caps the total number of items yielded across all pages (unset = all) and the per-page size is a separate$chunkSizeargument.StoreCollectionClient::iterate()follows the same rule (previously itslimitwas used as the page size);StoreListOptions::withOffset()is replaced bywithPagination(). KeyValueStoreClient::iterateKeys()follows the store's cursor pagination (exclusiveStartKey/nextExclusiveStartKey) and stops on the total-item cap or an untruncated page.- Documented every new iteration method with runnable examples and clarified the request-queue
method list, the key-value-store record snippet, and when
TransportExceptionsurfaces versusApifyApiException.
batchAddRequestsnow validates every request's individual payload size up front, before any HTTP call, so an oversized request anywhere in a large batch is rejected without POSTing earlier chunks (previously later chunks could partially mutate the queue before the error was raised).
- Synced to Apify OpenAPI spec
v2-2026-07-10T105921Z. No public interface changes.
- Synced to Apify OpenAPI spec
v2-2026-07-08T143931Z. No public interface changes. - Request bodies larger than 1024 bytes are now compressed before being sent, using brotli
(
Content-Encoding: br) when the PECLbrotliextension is available and gzip (Content-Encoding: gzip) as a fallback. Matches the reference client's request compression. - The
User-AgentOS token now reports the short lowercase platform identifier (e.g.linux,darwin,win32), matching the reference JS client'sos.platform()token, instead of the upper-casedPHP_OS_FAMILYvalue. - Both request-compression codecs are now covered by deterministic tests: the brotli path (its
preference over gzip and its output) and the gzip fallback are each exercised regardless of whether
the host PHP build has the PECL
brotliextension loaded. No behavior change.
- Synced to Apify OpenAPI spec
v2-2026-07-07T132551Z. No public interface changes. originis now a spec-declared query parameter on the last-run endpoints; corrected theLastRunOptionsdoc comment accordingly (behavior unchanged). Kept parity with the reference client, which does not exposewaitForFinishonlastRun.
- Initial PHP client for the Apify API (spec
v2-2026-07-02T131926Z). - Resource clients for Actors, Actor versions and environment variables, builds, runs, datasets, key-value stores, request queues, tasks, schedules, webhooks, webhook dispatches, the Apify Store, users, and logs.
- Convenience helpers consistent with the JS reference client:
actor()->call()/start(),validateInput(),defaultBuild(),lastRun(), runabort/metamorph/reboot/resurrect/charge/waitForFinish, datasetlistItems/downloadItems/pushItems/public URLs, key-value store records and public URLs, request queue batch add with retries, lazy request/store iteration, and log streaming.lastRun(status, origin)filters propagate to the run's nested dataset, key-value store, request queue, and log accessors, so they resolve the same run. batchAddRequestsrequires a non-emptyuniqueKeyper request, splits batches by both the 25-request count limit and the ~9 MiB payload-size limit, and retries only the requests the API reports unprocessed in a successful response (previously it hard-coded an empty unprocessed list and could mis-correlate requests). Consistent with the reference client, a failed batch call reports that chunk's not-yet-processed requests as unprocessed rather than throwing.datasets()->getOrCreate()andkeyValueStores()->getOrCreate()accept an optionalschema.requestQueue($id, RequestQueueClientOptions)acceptsclientKeyandtimeoutSecs;paginateRequests()acceptsPaginateRequestsOptions(limit,maxPageLimit,exclusiveStartId,cursor,filter).- Replaceable HTTP transport (
HttpClientInterface) with a default Guzzle implementation and a PSR-18 adapter; automatic retries with exponential backoff and jitter, growing per-attempt timeouts, and HMAC-SHA256 storage URL signing. - Public
Version::CLIENT_VERSIONandVersion::API_SPEC_VERSIONconstants. - Integration test suite, documentation with runnable examples, and CI workflows for integration tests and publishing.