DocsCron Jobs
Scheduled jobs and CRON_SECRET enforcement
Cron Jobs
Scheduled jobs are configured in vercel.json and implemented under src/app/api/cron/.
Schedule
| Path | Cron | When (UTC) | Purpose |
|---|---|---|---|
/api/cron/wsl-sync | 0 6 * * * | daily 06:00 | Refresh WSL circuit results |
/api/cron/wsl-athletes-sync | 0 5 * * * | daily 05:00 | Refresh the WSL athlete search index (CT/CS/QS) for search + Discover |
/api/cron/wsl-avatars | 30 */6 * * * | every 6h | Backfill missing WSL athlete headshots, a bounded batch per run |
/api/cron/liveheats-sync | 0 7 * * * | daily 07:00 | Refresh linked LiveHeats athletes |
/api/cron/liveheats-orgs-sync | 0 8 * * 2 | Tue 08:00 | Re-cache athletes for every Liveheats series referenced by a circuit |
/api/cron/backfill-spots | 0 4 * * * | daily 04:00 | Resolve home breaks to Surfline spots |
/api/cron/prune-activity | 0 3 * * * | daily 03:00 | Delete activity events older than the retention window |
/api/cron/training-session-reminders | 0 * * * * | hourly | Remind athletes and coaches ~24h before confirmed training sessions |
Authorization
Every cron route calls isAuthorizedCron(request) first and returns 401 if it fails. The helper (src/lib/cronAuth.js):
- Reads
CRON_SECRET. - Fails closed when the secret is unset.
- Compares the
Authorization: Bearer <secret>header in constant time.
Cron routes use the service-role Supabase client. On Vercel, cron invocations include the secret automatically when CRON_SECRET is set.
Running a cron manually
curl -X GET https://your-app.com/api/cron/wsl-sync \
-H "Authorization: Bearer $CRON_SECRET"