Examples
Five example projects ship in the repository, each a single file you can read in a couple of minutes. Each answers a different question — how do I call this without an SDK, how do I plug in my own provider, what does a workflow look like end to end, and how fast is it. Every section below links straight to the source on GitHub.
All five talk to a running NotifKit server, so you will want one before any of them do
anything — the quickstart gets you there in a few minutes, and
custom-server below is a working server in a single
file.
fetch. No SDK, no build step.basic-usage
The one to read first. Three HTTP calls — sync a template, register a user,
send — using nothing but fetch. It exists to make the point that NotifKit has no
required SDK: anything that can POST JSON is a client, so the same three calls work from Go,
Python, PHP, or a shell script.
The third call comes back 202 Accepted, which is NotifKit saying queued,
not delivered — the distinction the rest of the docs keep coming back to. The task id
it returns is what GET /v1/notifications/{taskId} reports against.
| Shows you | Read next |
|---|---|
| Template sync, user creation, a first send | Quickstart |
Bearer auth on every /v1 route | Reference |
custom-server
Bootstraps NotifkitServer in your own process with services: ["all"],
registers a hand-written email transport, sets worker concurrency, and installs graceful
shutdown handlers. The transport is the interesting part: a class with a
channel and a send() that returns
{ success, providerMessageId }. That is the entire contract — Resend and FCM
implement the same one.
| Shows you | Read next |
|---|---|
Writing a Transport | Channels & fallback |
| Running every service in one process | Architecture |
| Graceful shutdown | Operations |
workflows
Defines a two-step onboarding drip — welcome, wait an hour, follow up — as a JSON workflow, registers the recipient, then triggers one instance for them. Worth reading closely for one detail: no step names a recipient. Each inherits the user the instance was triggered with, which is why the same definition serves every subscriber.
The JSON form needs no deploy — the sequence is data, editable by someone who is not shipping a release. Code-defined workflows can do the same thing with conditionals and arbitrary side effects.
◆ examples/workflows on GitHub →| Shows you | Read next |
|---|---|
| Declarative workflows, and who a step sends to | Workflows |
| Waiting between steps | The step API |
scheduled-notifications
Sends with sendAt set ten minutes out, for a user in
America/New_York with a 22:00–08:00 quiet window. Two mechanisms overlap here,
and the example is the shortest way to see the difference:
sendAt is absolute UTC and is not shifted into the user's timezone,
while quiet hours are timezone-aware — so a scheduled send that lands inside a quiet
window gets deferred again to the far edge of it.
The message is parked in Postgres with a pointer in a Redis sorted set, where
GET /v1/notifications/scheduled can see it and where it stays cancellable right
up until the scheduler releases it.
| Shows you | Read next |
|---|---|
sendAt, listing and cancelling scheduled sends | Scheduling |
| Quiet-hours deferral | Preferences & quiet hours |
load-test
Fires a configurable number of notifications through a pool of concurrent workers and reports throughput and elapsed time. Defaults to 500 notifications at concurrency 50, across 100 distinct users.
This measures ingestion, not delivery. Every call returns as soon as the
request is queued, so a high number here says the API accepted the work quickly — it says
nothing about how fast messages reached anyone. For that, watch stream depth in
GET /v1/system/metrics, which shows whether the queue drains afterwards or
grows without bound.
| Shows you | Read next |
|---|---|
| Ingestion throughput, batching behaviour | Architecture |
| What to watch while it runs | Operations |