Webhooks allow you to schedule API calls to your PocketBase instance at specific times, replacing the need for external cron job schedulers. This feature enables automated tasks like data cleanup, backups, notifications, and integrations with external services.
Important: Webhooks replace PocketBase’s built-in cron job scheduling (
cronAdd
) on PocketHost. WhilecronAdd
works in standard PocketBase deployments, it becomes unreliable on PocketHost due to instance hibernation. Scheduled webhooks will always execute reliably, even when your instance is hibernated.
Webhooks are configured through the PocketHost dashboard and automatically execute HTTP requests to your specified endpoints at scheduled intervals. Each webhook consists of:
All webhooks execute in UTC time. Make sure to adjust your cron schedules accordingly.
cronAdd
?On PocketHost, webhooks provide several advantages over PocketBase’s built-in cronAdd
:
The API endpoint must be a valid path within your PocketBase instance:
/
(e.g., /api/webhooks/backup
)/api/cron?token=abc123
)http://
or https://
)Examples:
/api/webhooks/daily-cleanup
/api/backup?type=full&compress=true
/webhook/slack/notifications
/api/maintenance/cleanup-old-records
Webhooks use standard cron expressions to define execution schedules. You can use either:
Macro | Description | Equivalent Expression |
---|---|---|
@yearly | Once a year at midnight, January 1st | 0 0 1 1 * |
@annually | Same as @yearly | 0 0 1 1 * |
@monthly | Once a month at midnight, first day | 0 0 1 * * |
@weekly | Once a week at midnight on Sunday | 0 0 * * 0 |
@daily | Once a day at midnight | 0 0 * * * |
@midnight | Same as @daily | 0 0 * * * |
@hourly | Once an hour at the beginning | 0 * * * * |
@minutely | Once a minute | * * * * * |
@secondly | Once a second | * * * * * * |
@weekdays | Every weekday at midnight | 0 0 * * 1-5 |
@weekends | Every weekend at midnight | 0 0 * * 0,6 |
Standard cron expressions use 5 fields: minute hour day month weekday
Field | Values | Special Characters | Description |
---|---|---|---|
Minute | 0-59 | * , - / ? | Minute of the hour |
Hour | 0-23 | * , - / ? | Hour of the day |
Day of Month | 1-31 | * , - / ? L W | Day of the month |
Month | 1-12 | * , - / ? | Month of the year |
Day of Week | 0-6 | * , - / ? L # | Day of the week (0=Sunday) |
Special Characters:
*
- Any value,
- Value list separator-
- Range of values/
- Step values?
- Any value (alias for *
)L
- Last day of month/weekW
- Weekday (nearest to given day)#
- Nth day of monthAll webhooks execute in UTC time. When scheduling webhooks, convert your local time to UTC:
Use online UTC converters to help calculate the correct schedule times.
# Weekdays at 9 AM UTC
0 9 * * 1-5
# Every Monday at noon UTC
0 12 * * 1
# Every Friday at 6 PM UTC
0 18 * * 5
# First day of every month at midnight UTC
0 0 1 * *
# 15th of every month at 8 AM UTC
0 8 15 * *
# Daily backup at 2 AM UTC
0 2 * * *
# Cleanup old records every 6 hours
0 */6 * * *
# Weekly data export on Sundays at midnight UTC
0 0 * * 0
# Monthly maintenance on the 1st at midnight UTC
0 0 1 * *
# Daily operations
@daily
# Weekly reports
@weekly
# Monthly cleanup
@monthly
# Business hours only
@weekdays
Create API endpoints in your PocketBase instance to handle webhook requests using PocketBase’s routing system:
// pb_hooks/onRequest.pb.js
routerAdd('POST', '/api/webhooks/backup', (e) => {
// Your backup logic here
console.log('Backup webhook triggered')
// Example: Create a backup record
const backup = new Record($app.dao().findCollectionByNameOrId('backups'), {
timestamp: new Date().toISOString(),
status: 'completed',
size: '1.2GB',
})
$app.dao().saveRecord(backup)
return e.json(200, { status: 'success' })
})
Webhooks should return appropriate HTTP status codes:
200
- Success400
- Bad request500
- Internal server errorrouterAdd('POST', '/api/webhooks/cleanup', (e) => {
try {
// Your cleanup logic
return e.json(200, { status: 'success' })
} catch (error) {
console.error('Webhook error:', error)
return e.json(500, { error: 'Internal server error' })
}
})
For secure webhooks, include authentication in your endpoints:
routerAdd('POST', '/api/webhooks/secure', (e) => {
const token = e.request.url.query().get('token')
if (token !== process.env.WEBHOOK_SECRET) {
return e.json(401, { error: 'Unauthorized' })
}
// Your secure webhook logic
return e.json(200, { status: 'success' })
})
Make your webhooks idempotent so they can be safely retried:
routerAdd('POST', '/api/webhooks/process', (e) => {
const jobId = e.request.url.query().get('jobId')
// Check if already processed
const existing = $app.dao().findFirstRecordByData('jobs', 'jobId', jobId)
if (existing && existing.get('status') === 'completed') {
return e.json(200, { status: 'already_processed' })
}
// Process the job
// ...
})
Always log webhook executions for debugging:
routerAdd('POST', '/api/webhooks/backup', (e) => {
console.log(`Backup webhook triggered at ${new Date().toISOString()}`)
// Your backup logic
console.log('Backup webhook completed successfully')
return e.json(200, { status: 'success' })
})
cronAdd
instead of webhooks: Replace cronAdd
calls with scheduled webhooks for reliable execution on PocketHost