SDK
A typed client generated from the same OpenAPI document as the API reference.
Install
Not yet on npm. Until they are, the source is in this repository and the API is plain HTTP — every example in the documentation is shown as a request as well, so nothing a reader needs depends on a package they cannot install. Publishing is a decision with a credential behind it and is not made by a build.
git clone https://github.com/NotifHQ/app.git cd app/sdk && npm install && npm run build
Every example below is shown as an HTTP request too, so nothing here depends on a package you cannot install yet.
Send a notification
The contract decides the channel, the template and the preference policy. The request names what happened, not how to tell anyone about it.
import { NotifHQ } from "@notifhq/sdk";
const notifhq = new NotifHQ({ apiKey: process.env.NOTIFHQ_API_KEY });
await notifhq.notifications.create({
type: "commerce.order.shipped",
recipient: { external_id: "cus_1024", channels: [{ channel: "email", destination: "ada@example.com" }] },
params: { order_number: "A-1024", tracking_url: "https://..." },
}, { idempotencyKey: "order-A-1024-shipped" });
The same call over HTTP:
curl https://api.notifhq.com/v1/notifications \
-H "Authorization: Bearer $NOTIFHQ_API_KEY" \
-H "Idempotency-Key: order-A-1024-shipped" \
-H "Content-Type: application/json" \
-d '{"type":"commerce.order.shipped","recipient":{"external_id":"cus_1024","channels":[{"channel":"email","destination":"ada@example.com"}]},"params":{"order_number":"A-1024"}}'What comes back
A notification id and a state. requested means accepted and nothing more — the decision, the render and the delivery each have their own state, and none of them borrows another's. Follow them with GET /v1/notifications/{id} or subscribe to the webhooks below.
Widgets
9 embeddable widgets ship with the platform, each mounted with a short-lived recipient-scoped token. The workspace key never reaches a browser.
- Preferences Center — The recipient's own view of what they receive and how. The single most-requested surface, and the one that turns an opt-out into a downgrade.
- Passcode Verification — The screen where a recipient types the code NotifHQ just sent them. Customers were already sending auth.identity.otp through us and then writing the checking half themselves — the half with the timing-safe comparison, the attempt cap and the single-use guard, which is the half where a mistake is a breach rather than a bug. This widget is the client of the endpoint that does it properly.
- Notification Inbox — An in-app list of the recipient's notifications, with read state.
- Notification Bell — Unread count and a compact dropdown. Pairs with the inbox.
- Communication History — Everything sent to this recipient, with delivery state. Turns 'I never got it' into a self-service answer.
- Ticket Submit — A form that opens a ticket already bound to the recipient and their communication evidence.
- Ticket Status — The recipient's view of their own open conversations.
- Data Request Centre — The recipient asks for their data or its erasure, from inside your product. The request is recorded with its own evidence the moment it is made, so the clock starts on a row rather than on somebody noticing an email.
- Consent Capture — An opt-in with its lawful basis and its source recorded at the moment it is given. A consent with no evidence is an assertion, and an assertion is not a defence.