Skip to main content

How Notifizz works

Notifizz is event-driven end to end. Your backend emits one event with a flat track(eventName, properties) call — even an incomplete one. The platform resolves campaigns, the AI orchestrator enriches the event with your live business data and builds the recipient list, and notifications dispatch through every channel — all server-side, with no workflow or recipient targeting at the call site.

TL;DR

  • One call, one event. client.track(eventName, properties) posts to POST /v1/events/track.
  • Server-side routing. Campaigns matching the event name are looked up; one workflow instance is created per match.
  • AI orchestrator builds recipients. The campaign’s orchestrator runs against the event properties, calls enrichers to fetch live data, and produces the recipient list. The AI surfaces dev tasks for any gap (missing event property, undefined enricher) — one-click executable from your IDE via MCP.
  • Channels dispatch. A queue processor delivers the resolved content per channel — Notification Center widget today, email next (roadmap).
  • Real-time front-end. The widget receives new messages instantly — no polling.

End-to-end pipeline

Each stage

1

Track the event

Your backend calls client.track(eventName, properties, { idempotencyKey }). The SDK posts to POST /v1/events/track with the SDK secret key as Bearer + X-Idempotency-Key. The backend acks acceptance within milliseconds — everything below runs asynchronously.
2

Match campaigns

The event handler looks up campaigns wired to this eventName in the caller’s environment. Idempotency is enforced here: a duplicate idempotencyKey returns { duplicate: true } and skips re-enqueue.
3

Create workflow instances

One workflow instance is created per matching campaign. Each instance carries the event properties, a correlation id, and the campaign version it ran against — so in-flight notifications run against the campaign version they started on, even if a newer version has shipped since.
4

Run the AI orchestrator

The orchestrator runs the campaign’s code: enrichment (calling registered enrichers via HMAC-signed webhooks to fetch live data your event didn’t carry), recipient resolution, branching. The AI generates this code from the campaign description; you review, edit, ship.
5

Enqueue per-recipient sends

Once the orchestrator produces a recipient list, the system enqueues one job per (recipient, channel) pair.
6

Dispatch through channels

The notifications processor calls each channel: for the Notification Center, the message is delivered to the user’s inbox + the unread index is bumped; email lands next.
7

Real-time client delivery

The widget receives new messages in real time — the bell badge updates the moment the notification commits, with no polling and no SSE plumbing on your side.

What you control

SurfaceWhat you decide
BackendWhat events fire, when, with which properties + idempotency keys.
DashboardWhich campaigns exist, what they listen on, their orchestrator (AI-generated, you review), channel configs, recipient logic.
FrontendWhere the bell renders, custom bell UI, headless mode, optional in-app reactions to state changes.
The SDK call site never picks a campaign, channel, or recipient list. That separation is what makes the marketing/dev split workable: marketing edits campaigns without redeploying code, and the same event drives multiple campaigns over time.

Idempotency, retries, traceability

  • Idempotency — every track() carries a key (auto-UUID or caller-supplied). Duplicate keys short-circuit at the backend with { duplicate: true }.
  • Retries — the SDK retries transient failures twice (1s, 2s) before bubbling. Once the backend accepts the event, the internal queue owns retries downstream — failed steps land in the dead-letter queue with a correlation id you can trace.
  • Correlation ID — stamped at message creation time, propagates through every queue hop and every delivery write. Use it to follow a single delivery end-to-end.

FAQ

The chained shape forced the developer to know the campaign slug and the recipient list at the call site — two things that almost always change before the campaign ships. With server-side routing, marketing edits the campaign without a deploy, and the same event drives multiple campaigns over time.
The event is accepted (200) and recorded, but no workflow instance is created and no notification fires. This is intentional — you can register events ahead of building campaigns. The dashboard’s “missing properties” / “unrouted events” view surfaces these so you can wire up a campaign later.
Common causes in order: (1) campaign status is Editing (only Live runs on prod; Dev runs on dev environments); (2) event-name mismatch (whitespace, case, source vs target); (3) campaign listening on the wrong environment. Check the dashboard delivery history — campaigns that didn’t match show a no-route entry.
The orchestrator is code (generated by the AI from the campaign description, editable). It reads the event properties, calls registered enrichers if needed (e.g. fetchUser({ userId })), and returns a recipient list. Each recipient must have at minimum id + email. See recipients for the patterns.
Acceptance is millisecond-fast. End-to-end latency depends on orchestrator complexity (especially enricher round trips) and queue depth. In normal operation, simple campaigns deliver in under a second; campaigns with cold enrichers can take a few seconds.
The widget subscribes to the user’s inbox over a real-time stream — new writes propagate instantly to the dropdown and badge, with no SSE plumbing or polling on your side. Reconnection and offline queueing are handled for you.

See also

Events and workflows

Events, properties, campaigns, recipients — the building blocks.

Channels

In-app, email, and what’s on the roadmap.

Authentication

Widget auth modes — Firebase, backend token, publicly-signed JWT, none.

Backend quickstart

Send your first event in under five minutes.