Schedule a Stripe webhook in three lines
Stripe sends webhook events the moment they happen — checkout.session.completed fires at checkout, customer.subscription.created at signup. But a lot of product logic is about the future: remind a user three days before a trial ends, run a deferred charge, or send a re-engagement nudge a week later. Stripe doesn't schedule arbitrary future calls to your own endpoints — so you reach for a cron job, a queue, or a delayed task you have to babysit.
With SendItWhenever you schedule a delayed webhook right from inside your existing Stripe handler, in three lines.
1. Install the SDK
npm install @sendithq/sdk
2. Schedule a follow-up from your Stripe handler
When a checkout completes, schedule the reminder for three days before the trial ends. The payload is encrypted at rest the moment it's stored.
import { SendIt } from "@sendithq/sdk";
const sendit = new SendIt(process.env.SENDIT_API_KEY!);
// inside your Stripe webhook route
if (event.type === "checkout.session.completed") {
const session = event.data.object;
const trialEnd = session.subscription_details?.trial_end; // unix seconds
const fireAt = new Date((trialEnd - 3 * 24 * 60 * 60) * 1000);
await sendit.schedule({
url: "https://api.myapp.com/reminders/trial-ending",
fireAt: fireAt.toISOString(),
payload: { customerId: session.customer, email: session.customer_email },
});
}
3. Receive and verify the call
At the scheduled second, SendItWhenever POSTs your payload with an HMAC signature in the X-SendIt-Signature header. verifySignature() reads that header for you — pass the raw request body (parsed JSON breaks the signature) and verify before trusting the request:
import express from "express";
const sendit = new SendIt(process.env.SENDIT_API_KEY!, {
signingSecret: process.env.SENDIT_SIGNING_SECRET!,
});
// raw body is required — HMAC is computed over the exact bytes
app.post(
"/reminders/trial-ending",
express.raw({ type: "application/json" }),
(req, res) => {
const ok = sendit.verifySignature({ headers: req.headers, rawBody: req.body });
if (!ok) return res.status(401).end();
// …send the "your trial ends soon" email
res.status(200).end();
},
);
What you get for free
No broker, no cron server, no IAM. The delivery is signed, the payload is encrypted at rest with AES-256-GCM, and failures retry up to five times with exponential backoff before landing in a Dead Letter Queue — all visible in the dashboard. Firing is second-level precise with Early Firing to offset round-trip latency.
This same pattern covers deferred charges, dunning sequences, delayed onboarding emails, and any "do X later" flow that starts from a Stripe event.