Apify
Run Apify actors and tasks through one gateway route — inline, or as tracked async runs
Fronts actor and task execution for Apify on https://api.apify.com, in both of Apify’s execution styles. Run an actor and get its result in the same response, or start a run, poll it, and read the dataset it produced. Whatever follows /apify/ is relayed to Apify, provided it names one of the admitted actions:
Admission is default-deny against a fixed allowlist: only the actions listed below get through, and every other path draws a 404. Mounted methods: GET, POST.
Supported scope
Synchronous — the actor runs and the result comes back inline:
Asynchronous — the run starts, and you poll it on your own schedule:
Give {actorId} / {actorTaskId} in tilde form as one path segment (e.g. apify~web-scraper); the slash-separated username/name form is not accepted.
Reach for the synchronous form when the job finishes inside one HTTP request. Reach for the asynchronous form for long crawls, for anything you want to abort partway, and whenever you’d rather hold a run id than an open connection.
Credential handling
Apify will take its token through two channels — a token query parameter or an Authorization: Bearer header — and the gateway closes off both:
Authorizationis overwritten with Apify’s secret token (Apify reads the very header that carries your gateway token). The gateway consumes your token itself; Apify never receives it.- A
tokensupplied by the client in the query is discarded (any encoding), so nothing can displace the injected token.
Ownership
A run you start asynchronously — and the default dataset it writes to — is registered to your account before the create response reaches you. That registration is what makes the run id and dataset id usable: polling, aborting, and reading dataset items all check it first.
An id belonging to another account answers exactly what an id that never existed answers: a 404, with no upstream call made on its behalf. There’s no separate “forbidden” status, so nothing about anyone else’s runs is disclosed — including whether they exist.
A run of your own that Apify has since expired also ends in a 404, but by a different route: the read is authorized, so it reaches Apify, and what comes back is Apify’s own 404. Handle it the same way — the run is gone — without expecting it to look identical to the ownership refusal above.
The account-wide GET /v2/actor-runs and GET /v2/datasets listings carry no id to check, so they aren’t mounted. Enumerate from your own side: keep the id and defaultDatasetId each create hands back.
If a create succeeds upstream but the gateway can’t record the run as yours, it answers 500 and discards the run rather than returning an id nothing tracks — nothing is charged for it. Retry the request.
Billing
The two styles meter differently, because they report cost differently.
Synchronous run-sync calls carry no per-request cost signal, so they bill a flat $0.01 per accepted run-sync call, settled on a 2xx. All four run-sync endpoints bill at that one rate, whatever the actor does or how long it takes.
Asynchronous runs report their own exact cost, so they’re billed from it:
- Starting a run carries no flat charge of its own, and polling costs nothing.
- Once a run reaches a terminal state —
SUCCEEDED,FAILED,TIMED-OUT, orABORTED— its ownusageTotalUsdis charged, exactly as Apify reports it, with no per-request markup. That figure already sums the run’s compute, proxy traffic, storage operations, and dataset writes. - The charge is taken once per run, no matter how many times you poll it, and an abort followed by a poll still charges once.
- A terminal run that genuinely cost nothing is charged nothing.
- The charge lands on the account that created the run — never on whoever happens to poll it.
usageTotalUsd is a running total while a run is live, which is why nothing is billed until the run is finished: charging mid-run would bill for compute the run hasn’t spent yet.
NativePort adds nothing per request: an asynchronous run’s charge is Apify’s own metered cost, unmarked up. The gateway’s only fee is applied when you add credits; see pricing.
Examples
Run an actor (sync)
Run a saved task (sync)
Start a run (async)
Poll, read, abort
A create answers with the run object. Keep both ids from it:
data.id is what you poll and abort; data.defaultDatasetId is where the run’s items land. Polling returns the same shape with an updated status, finishedAt, and usageTotalUsd.
Responses arrive as Apify’s JSON, untouched. Field-level request and response detail lives in Apify’s API reference; the gateway modifies neither.