Skip to content
sarmakska edited this page Jun 1, 2026 · 1 revision

Crons

Every scheduled job in StaffPortal is an HTTP endpoint under /api/cron/*. The scheduler authenticates with Authorization: Bearer <CRON_SECRET>. Drive them with Vercel Cron (vercel.json), with GitHub Actions, or with any external scheduler such as Cloudflare Workers Cron.

Job Endpoint Schedule What it does
Year-end rollover /api/cron/year-end-rollover 5 0 1 1 * On 1 January at 00:05 UTC, caps unused leave at max_carry_forward and writes the new year's opening balance. Idempotent.
Leave accrual /api/cron/leave-accrual 10 0 1 * * On the 1st of each month, grants accrual_rate days to every balance with accrual enabled, capped at the entitlement. Idempotent.
Birthday reminders /api/cron/birthday-reminder Daily 08:00 UTC Emails colleagues two days ahead of a birthday and emails the birthday person on the day.
Absent reminders /api/cron/absent-reminder Weekdays 10:00 UTC Reminds users scheduled to work who have not clocked in, are not on leave, are not WFH, and have not pre-logged running late. Skips UK bank holidays.
Forgotten clock-out /api/cron/forgotten-clockout Daily 19:00 UTC Emails users who clocked in today but never clocked out, plus reception.
Missing attendance /api/cron/missing-attendance Daily 19:00 UTC Emails users with no attendance, leave, WFH, or running-late record for today, plus the accounts team.
Diary reminders /api/cron/diary-reminders Daily 07:00 UTC Emails diary entries to their author when remind_at == today.
Stretch reminder /api/cron/stretch-reminder Weekdays 14:00 UTC Sends a wellness stretch nudge to opted-in users.
IT ticket cleanup /api/cron/it-ticket-cleanup Weekly Archives resolved IT tickets older than 30 days.

Configuration

Set CRON_SECRET in the deployment environment. Set WFH_NOTIFY_EMAIL, LEAVE_APPROVAL_TIMEOUT_HOURS, and the admin and accounts notification addresses as needed. Every cron handler returns JSON with a count of rows touched and a list of warnings.

Local testing

Each handler can be invoked locally with curl:

curl -H "Authorization: Bearer $CRON_SECRET" http://localhost:3000/api/cron/birthday-reminder

If the handler returns 401, the secret is wrong or missing. If it returns 200 with an empty count, the date or schedule does not match any rows today.

Clone this wiki locally