Cron webhooks: call any URL on a schedule
cronservices calls any HTTP endpoint on a cron schedule: a webhook, an internal route like /api/cron/cleanup, or a third-party API. Use it in place of a crontab line on a server you have to keep alive, a scheduled serverless function, or a "cron job" add-on that can't send headers.
- Any method, headers, and a JSON or text body, with
{{ }}placeholders for dates and data. - Schedules in any time zone, from every minute to "the last weekday of the month", or once at an exact time.
- Secrets in encrypted credentials, sent as
Authorization: Bearer, Basic auth, or an API key header. - Every run recorded with its status code, duration, and the start of the response when it fails.
Example: a nightly cleanup route
Call your cleanup endpoint at 02:00 New York time, with a shared secret the endpoint checks:
{
"name": "Nightly cleanup",
"cron": { "expression": "0 2 * * *", "time_zone": "America/New_York" },
"nodes": [
{ "id": "cleanup", "request": {
"method": "POST",
"endpoint": "https://app.example.com/api/cron/cleanup",
"credential_id": "YOUR_SHARED_SECRET_ID",
"body": "{ \"older_than\": \"{{ now() - days(30) }}\" }" } }
]
}The body renders as { "older_than": "2026-09-30T06:00:00Z" } and is sent as application/json.
Example: chain two APIs
Each step receives the previous step's response, so you can read from one API and write to another in one job:
{
"name": "Sync open orders",
"cron": { "expression": "*/10 * * * *" },
"nodes": [
{ "id": "orders", "request": { "method": "GET", "endpoint": "https://shop.example.com/api/orders?status=open", "credential_id": "YOUR_SHOP_TOKEN_ID" } },
{ "id": "push", "request": {
"method": "POST",
"endpoint": "https://warehouse.example.com/v1/picklists",
"credential_id": "YOUR_WAREHOUSE_TOKEN_ID",
"headers": [{ "name": "Idempotency-Key", "value": "orders-{{ format(now(), \"YYYYMMDDHHmm\") }}" }],
"body": "{ \"orders\": { \"{{#each $.orders}}\": { \"id\": \"{{ $.id }}\", \"sku\": \"{{ $.sku }}\", \"qty\": \"{{ $.quantity }}\" } } }" } }
]
}Securing the endpoint
Store a long random secret as a bearer_token credential, reference it with credential_id, and have the endpoint reject requests without Authorization: Bearer <secret>. If the work takes more than 10 seconds, return 202 and finish in the background.
More ideas
- Warm a cache every 5 minutes:
*/5 * * * *. - Rotate logs or expire sessions nightly:
0 3 * * *. - Kick off a month-end export:
0 6 1 * *, or on the last day:0 18 L * *. - End a trial in 14 days with a one-time
run_atinstead of a delayed-job queue.
See the docs for every request field, and Use cases for complete jobs.