Webhook Scheduler
Log inStart free

Trial reminders

Schedule trial-ending reminders you can cancel the moment a user upgrades.

The hard part of a trial reminder is not sending it - it is not sending it after the user already paid. Webhook Scheduler schedules the reminder for later and lets you cancel it with one API call the instant the user converts, so nobody gets a "your trial is ending" email an hour after they upgraded.

API request
curl https://webhookscheduler.com/api/v1/schedule \
  -H "Authorization: Bearer wh_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://api.example.com/hooks/trial-reminder",
    "runAt": "2026-07-12T09:00:00.000Z",
    "body": { "userId": "usr_4821" },
    "idempotencyKey": "trial-reminder-usr_4821"
  }'
01

Schedule when the trial starts

One POST when the trial begins schedules the reminder for 3 days before it ends. Store the returned job id next to the user.

02

Cancel when the user converts

One call cancels the pending reminder the moment the user upgrades. No cron to clean up, no stale reminder to apologize for.

03

Proof it was delivered

Every attempt is logged with HTTP status, response body, latency, and retries, so a missed reminder is a record you can read, not a mystery.

Why cron makes this painful

The usual build is a cron job that runs every few minutes, scans a reminders table, and sends whatever is due. It works until you need to not send one. Now you are also writing the code to delete the row on upgrade, handle the race where the cron fires between upgrade and cleanup, and explain to a customer why they got a trial-ending email after paying.

Scheduling the HTTP call itself removes the table, the polling, and the cleanup. You schedule one job and cancel one job. That is the whole lifecycle.

The two-call pattern

Schedule the reminder when the trial starts (the code block above), keep the returned job id on the user, then cancel it if they upgrade first:

# When the user upgrades before the reminder fires:
curl -X POST https://webhookscheduler.com/api/v1/jobs/job_xxx/cancel \
  -H "Authorization: Bearer wh_live_xxx"

The idempotencyKey makes the schedule call safe to run twice - a retried request or a double-fired signup will not create a duplicate reminder. Both schedule and cancel are in the public API.

Verify the reminder really came from us

Every delivery is signed with a Webhook-Signature header (HMAC-SHA256, timestamped) using your workspace secret, so your receiver can confirm the reminder is authentic before it sends an email. Verification examples are in the API docs and the SDK ships a verifySignature helper.

Beyond trial reminders

The same schedule-then-cancel pattern covers most lifecycle webhooks: dunning and failed-payment follow-ups, delayed onboarding nudges, and win-back sequences. If you are weighing a queue instead, see how this compares with Upstash QStash and with cron-based scheduling.

Try it before you wire it up

You can fire a real scheduled delivery from the playground in about ten seconds without an account, then watch the delivery result come back live. The free plan schedules real reminders up to 7 days ahead; longer trials need a paid plan.

FAQ

Can I cancel a scheduled reminder after it is created?

Yes. A single POST to /api/v1/jobs/{id}/cancel drops any pending reminder before it fires. This is the core reason to schedule the webhook instead of running a cron.

What happens if the reminder endpoint is down when it fires?

The delivery retries automatically with exponential backoff, and every attempt is logged with its HTTP status, response body, and latency so you can see exactly what happened.

How do I avoid sending duplicate reminders?

Pass an idempotencyKey (for example trial-reminder-<userId>) on the schedule call. Repeat calls with the same key return the same job instead of creating a new one.

Can I schedule a reminder more than a week in advance?

The free plan schedules up to 7 days ahead, which covers short trials. Longer horizons (up to 365 days) are available on paid plans.

Ship delayed webhooks without maintaining scheduling infrastructure.

Start with the free plan, test a real delivery, then upgrade when the workflow becomes production critical.

Test a reminder webhook