Node.js SDK
The official stile Node.js library. Works with any Node.js backend framework.
Installation
npm install @stile/nodeInitialization
Create a single client instance and reuse it throughout your application. Pass your API key as the first argument.
import Stile from "@stile/node";
const stile = new Stile(process.env.STILE_API_KEY!);The SDK automatically retries failed requests and handles timeouts. Use vk_test_ keys in development and vk_live_ in production.
Verification Sessions
Create a session
const session = await stile.verificationSessions.create({
type: "identity",
return_url: "https://yourapp.com/verify/done",
cancel_url: "https://yourapp.com/verify/cancel",
client_reference_id: "user_123",
});
// session.id — e.g. "vks_abc123"
// session.client_secret — pass to the frontend widget
// session.expires_at — Unix timestamp (24h from now)
// session.status — "created"Retrieve a session
const session = await stile.verificationSessions.retrieve("vks_abc123");Cancel a session
const session = await stile.verificationSessions.cancel("vks_abc123");
// session.status === "cancelled"List sessions
const { data, has_more } = await stile.verificationSessions.list({
limit: 20,
starting_after: "vks_xyz",
});Webhook Endpoints
// Create
const endpoint = await stile.webhookEndpoints.create({
url: "https://yourapp.com/api/webhooks",
enabled_events: ["verification_session.verified", "verification_session.failed"],
description: "Production webhook",
});
// endpoint.secret — save this to verify signatures
// Retrieve
const ep = await stile.webhookEndpoints.retrieve("we_abc123");
// Update
await stile.webhookEndpoints.update("we_abc123", {
enabled_events: ["*"],
status: "enabled",
});
// Delete
await stile.webhookEndpoints.del("we_abc123");
// List
const { data } = await stile.webhookEndpoints.list();
// List delivery attempts
const { data: deliveries } = await stile.webhookEndpoints.listDeliveries("we_abc123");Events
// Retrieve a single event
const event = await stile.events.retrieve("evt_abc123");
// List events
const { data } = await stile.events.list({ limit: 20 });Verified Persons
Check if a user has been previously verified across any site in the stile network. Call this from your backend before loading the SDK to skip verification for returning users.
const result = await stile.verifiedPersons.lookup({
email: "user@example.com",
methods: ["document_capture"],
min_strength: "document_capture",
max_age: "30",
});
if (result.verified) {
// User already verified — grant access, skip SDK
console.log(result.verified_person_id, result.credentials);
} else {
// Create a session and load the SDK
}Webhook Signature Verification
Verify incoming webhook signatures to prevent processing spoofed events. The SDK provides two methods:
fromRequest() — for any Web API framework
Works with Next.js, Hono, Cloudflare Workers, Bun, Deno, and any framework using the standard Request object:
export async function POST(req: Request) {
const event = await stile.webhooks.fromRequest(
req,
process.env.WEBHOOK_SECRET!,
);
if (event.type === "verification_session.verified") {
console.log("Session verified:", event.data.id);
}
return Response.json({ received: true });
}constructEvent() — low-level
For frameworks that don't use the standard Request object, pass the raw body and header directly:
const event = stile.webhooks.constructEvent(
rawBody, // string or Buffer
signatureHeader, // stile-signature header value
process.env.WEBHOOK_SECRET!,
);Always use raw body
JSON body parsers modify the request body before it reaches your handler, which invalidates the signature. Always pass the raw, unmodified request body.
Error handling
import {
StileError,
StileAuthenticationError,
StileRateLimitError,
} from "@stile/node";
try {
await stile.verificationSessions.create({ type: "identity" });
} catch (err) {
if (err instanceof StileAuthenticationError) {
// 401 — invalid or expired API key
} else if (err instanceof StileRateLimitError) {
// 429 — slow down, retry after err.retryAfter seconds
} else if (err instanceof StileError) {
console.error(err.type, err.code, err.message);
}
}For a complete guide to error types, retry strategies, and idempotency, see Error Handling.