Set a schedule
An app has two schedules. Set either or both with Update app:
Both take a five-field cron expression, read in UTC, of at most 64 characters. The expression has to fire at least once.
schedule has no minimum interval. Send null or an empty string to clear a schedule. An invalid expression returns a 400. The key needs developer:update_app on the account that owns the app.
Handle the run
Exportscheduled() next to fetch() in your build’s server entry:
src/server.ts
ctx.props says which run this is:
controller.cron is the expression that scheduled the run, and controller.scheduledTime is the slot in milliseconds since the epoch.
A run uses the same isolate as your request handlers, so secrets and the injected API key work the same way. A run can last up to 15 minutes, where a request handler gets 30 seconds.
Retries and repeated runs
If a run fails, Whop retries it one time, a minute later, then drops it. To skip the retry, callcontroller.noRetry() before you throw. On the retry, attempt is 2 and scheduled_at is still the original slot.
The same slot can reach your app more than once, and a retry can start while the next slot’s run is already going. If your work must not happen twice, record each run you finish under run_id plus app_installation.id, and skip a run you’ve already recorded.
Skipped slots
No run happens while the app has no production web build with a server entry. Whop doesn’t queue a slot it skipped or make it up later, so build each run to carry on from whatever the last one saved.Logs
A run’sconsole output and uncaught errors appear in your app’s logs, next to its requests.
Next steps
App installations
The installation each per-install run carries, and where to keep a sync cursor.
Hosting
Builds, secrets, the injected API key, and logs.

