Docs LATEST

WebCron Endpoint

Trigger the scheduler via HTTP when system cron isn't available.

Scheduling

Some hosting environments do not provide cron access. WebCron gives you an HTTP endpoint that runs the scheduler when a request hits it.

Enabling WebCron #

Set cron_enabled in config/app.php or user/config/app.php:

return [
    'cron_enabled' => true,
];

The Endpoint #

Once enabled, the scheduler runs when you hit:

GET /system/cron

The endpoint returns a plain text response:

Ran 2 scheduled tasks.

Triggering from External Services #

Use an uptime monitoring service or external cron service to hit the endpoint every minute:

  • UptimeRobot - Set up a monitor with 1-minute checks
  • cron-job.org - Free external cron service
  • Pingdom - Use as a scheduled job
  • Your own server - Cron on a different machine

Example token-based request:

curl -s "https://yoursite.com/system/cron?token=your-secret-token"

Security Considerations #

The WebCron endpoint should not be exposed without some kind of protection. Core supports three built-in controls:

  • shared token authorization
  • optional signed URLs
  • optional IP allowlisting

You can also enable a dedicated rate limit for the endpoint.

IP Allowlisting #

Restrict requests to known IPs directly in application config:

return [
    'cron_allowed_ips' => [
        '203.0.113.10',
        '10.0.0.0/8',
    ],
];

Exact IPs, CIDR ranges, and * are supported.

You can still enforce the same rule in your web server if you want defense in depth:

Nginx:

location = /system/cron {
    allow 123.45.67.89;    # Your cron service IP
    allow 10.0.0.0/8;      # Internal network
    deny all;
    try_files $uri /index.php$is_args$args;
}

Apache (.htaccess):

<Location /system/cron>
    Require ip 123.45.67.89
    Require ip 10.0.0.0/8
</Location>

Shared Token #

Set a shared token in config, then send it as the token query parameter:

return [
    'cron_token' => env('CRON_TOKEN', 'your-secret-token'),
];
curl "https://yoursite.com/system/cron?token=your-secret-token"

If cron_token is empty, the endpoint refuses all requests.

Signed URLs #

If you do not want to expose the raw token in the request URL, enable signed URLs:

return [
    'cron_token' => env('CRON_TOKEN', ''),
    'cron_signed_urls' => true,
];

Core validates two query parameters:

  • expires - a future Unix timestamp
  • signature - hash_hmac('sha256', (string) $expires, $cronToken)

Example:

/system/cron?expires=1767225600&signature=...

Rate Limiting #

WebCron has its own rate limit config. It does not depend on route middleware:

return [
    'cron_rate_limit' => [
        'enabled' => true,
        'attempts' => 10,
        'decay' => 60,
    ],
];

When the limit is exceeded, the endpoint returns HTTP 429 Too Many Requests.

When to Use WebCron #

Use WebCron when:

  • Shared hosting without cron access
  • Serverless environments
  • Quick testing during development

Prefer system cron when:

  • You have server access
  • Tasks are time-sensitive
  • High reliability is needed

System cron is more reliable because it runs independently of HTTP traffic and external uptime services. WebCron is a fallback, not the first choice.

Alternatives #

If your host supports scheduled tasks but not traditional cron:

  • Laravel Forge - Has a scheduler UI
  • Heroku - Use Heroku Scheduler add-on
  • Platform.sh - Built-in cron support

These run php velvet schedule:run directly, which is preferable to WebCron.