Scheduled webhooks
A scheduled webhook fires on a CRON timer instead of on a Jira event. JQL on the schedule is the source of the issue list; the whole list ships in one delivery. Times are always UTC; real fire is 0–5 minutes after the planned minute.
When to use it
Reach for a scheduled webhook when:
You need a periodic snapshot of Jira state — daily / hourly / weekly.
Your receiver expects batched input rather than one event at a time.
You want a heartbeat from Webhooks Pro at a known cadence.
The trigger is time — not a Jira event.
If you're trying to react to something happening in Jira, a scheduled webhook is the wrong tool. Use an event-driven webhook (see Webhooks).
Scheduled vs. event-driven — at a glance
| Event-driven | Scheduled |
|---|---|---|
Trigger | Jira event matching the subscription | A wall-clock minute matching the CRON |
Frequency | Whenever the event happens | Fixed cadence you define |
JQL | Optional — narrows which events qualify | Required — defines the issue list to send |
Payload shape |
|
|
|
|
|
Timezone | n/a | Always UTC |
Timing precision | Within the debounce window | 0–5 minutes after the planned minute |
Schedules are designed for periodic reports, reminders, daily digests — not for time-critical workflows.
How it works
Forge runs the underlying scheduled trigger every 5 minutes on a fixed (per-tenant) cadence. On each tick the scheduler asks: which CRON expressions matched a minute in the last 5-minute window? For each match, it fetches matching issues by JQL (paged, 50 per page server-side), renders the payload, and sends one HTTP request.
Configure
The Schedule card on the webhook form has one toggle — Enable scheduled delivery — and two input modes:
Builder (default): tabs for Minutes / Hours / Day / Month with Every, Every N, Specific values. The Day tab combines Day-of-Month and Day-of-Week; selecting one clears the other (Quartz forbids both being specific).
Custom cron: paste a Quartz 7-field expression directly.
A live preview under the inputs shows the composed expression, a human-readable label (e.g. "At 12:00, Mon–Fri"), and a UTC marker.
Required: JQL on the Events tab
A scheduled webhook must have a JQL filter set on the Events tab — the JQL is the source of the issue list. Without JQL, there's nothing to send.
If you want a recurring webhook that doesn't carry issue data (e.g. a heartbeat), use a JQL that you know returns nothing (key = INVALID-0 works) plus the Send request even if JQL returns no issues toggle.
Optional: Send empty deliveries
By default, if JQL returns 0 issues at fire time, the delivery is skipped — no HTTP request, no log row. Enable Send request even if JQL returns no issues to deliver an empty issues: [] anyway.
Sub-pages
Examples
CRON | Means |
|---|---|
| Every 5 minutes |
| Every hour at :00 |
| At 09:00 UTC, Monday–Friday |
| 14:30 UTC on the 1st of every month |
| New Year — 00:00 UTC on Jan 1 |
Full reference and a UTC ↔ local cheat sheet: Schedule examples.
Limits and gotchas
Always UTC. The form does not convert from your timezone.
0 0 9 ? * MON-FRI *fires at 09:00 UTC, which is 11:00 in Berlin (summer). See UTC semantics and the fire-window.5-minute grid for minutes. The minute field must be
*/5or specific values from0,5,10,…,55. Anything else (e.g. minute3) is silently dropped — the next tick evaluates only the 5-minute boundaries. The form's validator catches most of these on save; pasted custom-cron can slip through.0–5 minute lag. A scheduled webhook will never fire earlier than the CRON time, but can be up to 5 minutes late depending on where the per-tenant Forge tick lands.
Whole list per delivery, not per issue. A schedule that matches 200 issues sends one HTTP request with all 200 in
issues: []. If the receiver requires one-issue-per-call, post-process on the receiver side or use an event-driven webhook with similar JQL.No catch-up. If a tick is missed (Forge maintenance, disabled app), the missed fire is not replayed. The next tick evaluates only the next CRON match.
Schedules don't fire while the app is uninstalled. Reinstalling resets the per-tenant tick offset.
Auto-disable applies. A scheduled webhook can be auto-disabled after N consecutive failures, just like an event-driven one.
Related
Webhooks — the parent. Most form sections are shared.
JQL filtering — the JQL on a schedule's Events tab. Semantics differ slightly from event-driven (it's the source list, not a filter).
Payload templates — schedules render the same templates, just with
issues: [ … ]instead ofissue: { … }.Webhook logs — every fired schedule produces one log row (or none, if empty + heartbeat disabled).
CRON didn't fire when expected (UTC pitfalls) — diagnostic playbook.