Getting Started
SendItWhenever is a precision HTTP webhook launcher. You tell it what request to send, where, and when — it holds the request and fires it at the scheduled time, signed and encrypted at rest.
Think of it as setTimeout for HTTP, but durable: it survives your process restarting, runs on second-level precision with Early Firing correction, and never loses a scheduled call.
Common uses:
- Trial-ending and dunning emails fired at an exact future moment
- Delayed billing charges (
charge in 14 days) - Reminders, follow-ups, and drip sequences
- Any "do this thing later" that you don't want to build a queue and worker for
How a schedule flows
Every scheduled webhook moves through a small set of states:
| State | Meaning |
|---|---|
scheduled |
Accepted and waiting for its fire time. |
firing |
The fire time arrived; delivery is in progress (including retries). |
succeeded |
Your endpoint returned a 2xx response. |
failed |
Delivery failed but may still retry. |
dead |
All retries were exhausted, or the target was permanently rejected. The request is moved to a dead-letter queue. |
cancelled |
You cancelled it before it fired. |
Internally there are two layers, and the split matters for understanding behavior:
- Execution layer (Redis): holds the encrypted job and fires it. This is the hot path; nothing slow is added to it.
- Record layer (Postgres): holds metadata you query — status, timestamps, attempt counts. When you call
list()orget(), you read this layer.
The payload itself is encrypted at rest and only decrypted in memory at the exact moment of firing. It is never written to logs.
Install
npm install @sendithq/sdk
# or: pnpm add @sendithq/sdk
The Node SDK (Node 18+) has zero runtime dependencies — it uses the built-in fetch.
There is also a Python SDK with the same surface (sync + async):
pip install sendithq
Your first scheduled webhook
Get an API key from your dashboard (it starts with sw_live_), then:
import { SendIt } from "@sendithq/sdk";
const sendit = new SendIt("sw_live_xxx");
await sendit.schedule({
url: "https://api.myapp.com/billing/charge",
in: "14d", // or fireAt: "2026-06-29T09:00:00Z"
payload: { userId: 42, amount: 9900 },
});
In Python it's the same call (note in_ — in is a reserved word):
from sendithq import SendIt
sendit = SendIt("sw_live_xxx")
sendit.schedule(
url="https://api.myapp.com/billing/charge",
in_="14d", # or fire_at="2026-06-29T09:00:00Z"
payload={"user_id": 42, "amount": 9900},
)
That's it. At the scheduled time, SendItWhenever sends a signed POST to your URL with that JSON body. If your endpoint is slow or down, it retries with backoff. You can later look the schedule up, reschedule it, or cancel it.
Without the SDK
Everything the SDK does is a thin wrapper over a REST API, so you can use plain HTTP from any language:
curl -X POST https://api.sendit-whenever.com/v1/schedules \
-H "Authorization: Bearer sw_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"targetUrl": "https://api.myapp.com/billing/charge",
"fireAt": "2026-06-29T09:00:00Z",
"payload": "{\"userId\":42,\"amount\":9900}"
}'
See the REST API Reference for the full surface.
Where to go next
- Authentication — API keys vs. session login
- Scheduling — fire times, payloads, idempotency, Early Firing
- Verifying Webhooks — confirm a request really came from us
- SDK Reference — every method