CLIENT SDK·@passyn/node
Node.js SDK
@passyn/node is the official, typed, zero-dependency client for Node 18+ and edge runtimes (Cloudflare Workers, Vercel Edge Functions, AWS Lambda).
Installation
pnpm add @passyn/node# or npm i @passyn/node / yarn add @passyn/node
Quickstart usage
Import the default client, instantiate it with your API key, and call strongly-typed methods.
passyn-tour.ts
import Passyn, { PassynError } from "@passyn/node";const passyn = new Passyn(process.env.PASSYN_API_KEY!, {baseUrl: "https://sub.blansyn.com/api/v1", // or "http://localhost:3000/api/v1" for local devtimeoutMs: 10_000,});// ── 1. Create a Pass Definition ──────────────────────────const pass = await passyn.passes.create({name: "Exam Cram 72h",type: "EXAM",durationHours: 72,price: 19,isActive: true,});const { passes, total } = await passyn.passes.list({ type: "EXAM", active: true });await passyn.passes.update(pass.id, { price: 24 });// ── 2. Users & Access Credential ─────────────────────────const access = await passyn.access.activate({ userId: user.id, passId: pass.id });// ── 3. Edge Turnstile Verification ───────────────────────const check = await passyn.access.verify({accessId: access.id,consume: true, // decrements one use atomically});console.log(check.valid); // => true// ── 4. Error Handling ────────────────────────────────────try {await passyn.passes.get("pass_unknown");} catch (err) {if (err instanceof PassynError) {console.error(err.code, err.status, err.message);}}
Webhook verification
The static helper Passyn.verifyWebhookSignature implements the timestamped HMAC-SHA256 verification with constant-time equality checks against replay attacks.
server.ts
import Passyn from "@passyn/node";import express from "express";const app = express();// IMPORTANT: signature verification requires the raw unparsed request bufferapp.post("/webhooks/passyn", express.raw({ type: "application/json" }), (req, res) => {const ok = Passyn.verifyWebhookSignature(req.body.toString("utf8"),req.headers["passyn-signature"] as string,process.env.PASSYN_WEBHOOK_SECRET!);if (!ok) return res.status(400).send("Invalid signature");const event = JSON.parse(req.body.toString("utf8"));if (event.event === "pass.expired") {// Revoke access or trigger customer notification}res.json({ received: true });});