Examples
All examples are available in the SDK repository.
Express — Basic auth
Section titled “Express — Basic auth”Protect routes with the built-in middleware:
// Usage: npx tsx examples/express-basic.ts
import express from 'express';import { Rakomi } from '@rakomi/node';
const app = express();const ca = new RakomiClient({ apiKey: 'akm_live_your_api_key' });
// Protect all /api routes — auto-detects dev/prod from hostnameapp.use('/api', ca.middleware());
// Access authenticated user data via req.authapp.get('/api/profile', (req, res) => { const { userId, email, tenantId } = (req as any).auth; res.json({ userId, email, tenantId });});
// Public route — no middlewareapp.get('/health', (_req, res) => { res.json({ status: 'ok' });});
app.listen(3000, () => { console.log('Server running on http://localhost:3000');});Express — Webhook verification
Section titled “Express — Webhook verification”Verify webhook signatures with raw body handling:
// Usage: npx tsx examples/express-webhook.ts
import express from 'express';import { Rakomi } from '@rakomi/node';
const app = express();const ca = new RakomiClient({ apiKey: 'akm_live_your_api_key', webhookSecret: 'whsec_your_webhook_secret',});
// Webhook route must use raw body (not parsed JSON)app.post('/webhooks/rakomi', express.raw({ type: '*/*' }), async (req, res) => { const result = await ca.verifyWebhook(req.body as Buffer, req.headers);
if (!result.ok) { console.error('Webhook verification failed:', result.error.code); res.status(400).json({ error: result.error.code }); return; }
const { payload, deliveryId } = result.data; console.log(`Received ${payload.type} (delivery: ${deliveryId})`);
switch (payload.type) { case 'user.created': console.log('New user:', payload.data); break; case 'user.deleted': console.log('User deleted:', payload.userId); break; }
res.status(200).json({ received: true });});
app.listen(3000, () => { console.log('Webhook server running on http://localhost:3000');});Fastify
Section titled “Fastify”Wrap the Rakomi middleware as a Fastify preHandler:
// Usage: npx tsx examples/fastify-basic.ts
import Fastify from 'fastify';import { Rakomi } from '@rakomi/node';
const fastify = Fastify({ logger: true });const ca = new RakomiClient({ apiKey: 'akm_live_your_api_key' });const authMiddleware = ca.middleware();
fastify.addHook('preHandler', (request, reply, done) => { if (request.url === '/health') { done(); return; }
const req = { headers: request.headers, auth: undefined as any }; const res = { status: (code: number) => { reply.code(code); return res; }, json: (body: unknown) => void reply.send(body), };
authMiddleware(req, res, () => { (request as any).auth = req.auth; done(); });});
fastify.get('/api/profile', async (request) => { const { userId, email, tenantId } = (request as any).auth; return { userId, email, tenantId };});
fastify.get('/health', async () => ({ status: 'ok' }));
fastify.listen({ port: 3000 }, () => { console.log('Fastify server running on http://localhost:3000');});Use verifyToken() directly in Hono middleware:
// Usage: npx tsx examples/hono-basic.ts
import { Hono } from 'hono';import { serve } from '@hono/node-server';import { Rakomi } from '@rakomi/node';
const app = new Hono();const ca = new RakomiClient({ apiKey: 'akm_live_your_api_key' });
app.use('/api/*', async (c, next) => { const result = await ca.verifyToken( c.req.header('authorization')?.slice(7) ?? '', );
if (!result.ok) { const { code, message, docs_url } = result.error; return c.json({ error: { code, message, docs_url } }, 401); }
c.set('auth' as never, result.data as never); await next();});
app.get('/api/profile', (c) => { const auth = c.get('auth' as never) as { userId: string; email: string }; return c.json({ userId: auth.userId, email: auth.email });});
app.get('/health', (c) => c.json({ status: 'ok' }));
serve({ fetch: app.fetch, port: 3000 }, () => { console.log('Hono server running on http://localhost:3000');});Next.js middleware
Section titled “Next.js middleware”Protect Next.js routes at the edge:
// Copy to your Next.js project root as middleware.ts
import { NextResponse, type NextRequest } from 'next/server';import { Rakomi } from '@rakomi/node';
const ca = new RakomiClient({ apiKey: 'akm_live_your_api_key' });
export async function middleware(request: NextRequest) { if (request.nextUrl.pathname.startsWith('/public')) { return NextResponse.next(); }
const token = request.headers.get('authorization')?.slice(7); if (!token) { return NextResponse.json({ error: 'Missing token' }, { status: 401 }); }
const result = await ca.verifyToken(token); if (!result.ok) { const { code, message, docs_url } = result.error; return NextResponse.json({ error: { code, message, docs_url } }, { status: 401 }); }
const response = NextResponse.next(); response.headers.set('x-user-id', result.data.userId); response.headers.set('x-tenant-id', result.data.tenantId); return response;}
export const config = { matcher: ['/api/:path*', '/dashboard/:path*'],};