@types/ package needed.
Current versions:
@bondify/node 3.0.2, @bondify/react 3.0.1 (Node ≥ 18; React 18/19; Next.js 14–16).
@bondify/react
<BondifyProvider config={…}>
Wrap your app once. config is a BondifyConfig:
string
required
Your project ID (
proj_…). Public.string
default:"https://api.bondify.dev"
Override the API base URL.
'redirect' | 'inline'
default:"'redirect'"
redirect opens the Telegram deep link in a new tab on startAuth. inline leaves opening the deep link to you (e.g. render a QR with <BondifyQR>).number
default:"1500"
Status poll interval, in milliseconds.
number
default:"120000"
How long the client polls before giving up (
POLLING_TIMEOUT), in milliseconds.(user: BondifyUser) => void
Called when the user confirms.
(error: BondifyError) => void
Called on failure.
() => void
Called when the user cancels in Telegram.
Hooks
Components
<BondifyButton> — label?, theme?: 'telegram' | 'dark' | 'light' | 'custom', size?: 'sm' | 'md' | 'lg', showIcon?: boolean, className?. Plus standard <button> attributes. Success/error/cancel are handled by the provider’s config callbacks.
<BondifyModal> — open?, onOpenChange?, title?, description?, className?. A dialog that runs the flow with a QR + button.
<BondifyQR> — size? (default 200), showLink?, className?. Renders a QR for the current session’s deep link.
Types
Server helpers — @bondify/react/server
Next.js App Router only. getServerUser and requireAuth read the JWT
secret from an explicit jwtSecret argument first; if omitted, they fall
back to environment variables in this order: BONDIFY_WEBHOOK_SECRET →
BONDIFY_JWT_SECRET → SERVER_SECRET. Use BONDIFY_WEBHOOK_SECRET unless
you already have one of the other two set for another purpose in your
project.
See the Next.js guide for usage.
@bondify/node
new BondifyServer(config)
string
required
Your project’s webhook secret (
whsec_…). Verifies the proof JWT.string
default:"= jwtSecret"
Secret used to verify webhook signatures. It’s the same
whsec_…, so you can omit it.string
default:"https://api.bondify.dev"
verifyProof / safeVerifyProof are async even though verification is
fully local (no network call is made) — this matches the convention used
by other auth SDKs (Clerk, NextAuth, Passport, …), so await and .then()
both behave as expected. verifyWebhook / safeVerifyWebhook remain
synchronous.Proofs expire 5 minutes after issuance. The JWT’s
exp claim is set 5
minutes after the user confirms in Telegram. Verify a proof promptly after
receiving it — a late one (slow network, a user idling on a confirmation
screen, etc.) throws BondifyVerificationError with code TOKEN_EXPIRED.
Handle that case explicitly rather than treating it the same as an invalid
signature:BondifyUser (returned by verifyProof) is camelCase — the same shape
@bondify/react returns on the client. WebhookEvent (from verifyWebhook)
stays snake_case, since it mirrors the raw JSON Bondify sends over the wire
for webhook deliveries — a deliberate, separate convention from the
SDK’s own ergonomic surface. The old snake_case type name
BondifyProofPayload is kept as a deprecated alias for BondifyUser so
existing type-only imports keep compiling.Middleware — @bondify/node/middleware
createBondifyMiddleware(server, options?)→ ExpressRequestHandler. Reads the proof fromAuthorization: Bearer …, a custom getter, or thebondify_proofcookie, verifies it (awaitsverifyProofinternally), and setsreq.bondifyUser. Options:cookieName,headerName,tokenGetter,onUnauthorized.
The cookie fallback reads
req.cookies, which Express only populates if you’ve applied the cookie-parser middleware before this one (app.use(cookieParser())). Without it, req.cookies is undefined and cookie-based auth silently falls through to a 401 — if you’re only using the Authorization: Bearer … header, you don’t need it.verifyNextRequest(server, request, cookieName?)→Promise<BondifyUser | null>. Async — alwaysawaitit. For Next.js App Router Route Handlers. Reads the proof from theAuthorization: Bearer …header first, then falls back to thebondify_proofcookie (or the customcookieNameyou pass); never throws — a missing header/cookie, invalid signature, or expired proof (5-minute lifetime) all resolve tonull, which you should treat as “unauthorized”. It’s a thin wrapper aroundsafeVerifyProof, so it doesn’t distinguish why verification failed — callverifyProofdirectly if you need that.