TypeScript native
Full types for send(), ZinduaError, and ZinduaSendResult. Works in JavaScript too (Node 18+).

TypeScript-first Node backends with @zindua/sdk v1.4.1. send(), templates, logs, and webhooks. Same API as Next.js, built for Fastify route handlers and plugins.
npm i @zindua/sdknpm i fastifyFastify is your HTTP framework (npm i fastify). Zindua ships only @zindua/sdk on npm.
Full types for send(), ZinduaError, and ZinduaSendResult. Works in JavaScript too (Node 18+).

Fastify JSON schema on routes + SDK checks channel/to before the HTTP call.

One send() for both channels. cc, bcc, replyTo on email.

@zindua/sdk uses Node fetch. Server-side only (throws in the browser).
Register Zindua once with fastify.decorate() and reuse in all routes.

Smoke test with @zindua/cli. Trace delivery with logId, Logs, and webhooks.

Install SDK, email OTP, or WhatsApp OTP. The TypeScript snippet updates.
Install SDK
CLIAdd @zindua/sdk and fastify. Set ZINDUA_API_KEY in .env.
terminal
1# Zindua SDK (official npm package)2npm i @zindua/sdk3 4# Fastify: your HTTP framework (not published by Zindua)5npm i fastify6 7# .env8ZINDUA_API_KEY=znd_test_your_key_hereFrom project key to dashboard logs.
From project key to first OTP in four steps.
Create a Zindua project
Sign up at zindua.run, create a project, copy the API key. Connect email (Gmail/SMTP Service) and/or WhatsApp in the dashboard. Create templates (e.g. otp-verification).
JSON schema, plugins, OTP + Redis, errors, and response shape.
JSON schema
Validate request bodies in Fastify before send(). SDK validates channel and to again.
import type { FastifyInstance } from "fastify";import type { ZinduaSendResult } from "@zindua/sdk"; const sendOtpSchema = { body: { type: "object", required: ["to", "code"], properties: { to: { type: "string", format: "email" }, code: { type: "string", minLength: 4, maxLength: 8 }, lang: { type: "string", enum: ["fr", "en"] }, }, },} as const; fastify.post<{ Body: { to: string; code: string; lang?: string } }>( "/otp/email", { schema: sendOtpSchema }, async (request, reply): Promise<ZinduaSendResult> => { const { to, code, lang } = request.body; return zindua.send({ to, template: "otp-verification", ...(lang ? { lang } : {}), variables: { code }, }); });send() fields, channels, methods, errors, security, and environment.
All fields accepted by @zindua/sdk. Plain JavaScript works the same without types.
to
Email if channel is email (default). E.164 phone with + for WhatsApp (e.g. +243812345678).
Persist logId from send() and correlate with the dashboard.
There is no public SDK method for logs or analytics. Delivery history and send volume live in the Zindua dashboard (session auth). From Fastify, persist result.logId in your database and correlate with dashboard Logs or inbound webhooks.
doctor checks the key. send smoke-tests a template. Use znd_test_ keys with isTestMode() in staging.
npx @zindua/cli@latest doctorUse httpx with FastAPI for async OTP routes on Python 3.10+.