@simplr-ai/express
v2.0.0
Published
Drop-in server middleware for Express, Fastify, Hono, and Next.js that auto-runs Simplr fraud/identity checks and ingests edge logs per request. Built on @simplr-ai/node.
Maintainers
Readme
@simplr-ai/express
Drop-in server middleware that auto-runs Simplr fraud/identity checks (and optionally ships edge logs) on every request — for Express, Fastify, Hono, and Next.js.
It wraps the @simplr-ai/node server SDK: same endpoints, same X-API-Key auth, same { success, message, content } envelope, same 15s default timeout. Use your secret key (sk_live_… / sk_test_…) — this runs server-side only.
Docs: https://simplr-docs-three.vercel.app/sdks/
Install
npm install @simplr-ai/express @simplr-ai/nodeFrameworks are optional peer dependencies — install only the one you use. Requires Node 18+ (built-in fetch).
Express
import express from "express";
import { simplrExpress } from "@simplr-ai/express";
const app = express();
app.use(express.json()); // so the default extractor can read email/phone from the body
app.use(simplrExpress({ apiKey: process.env.SIMPLR_API_KEY! }));
app.post("/signup", (req, res) => {
// req.simplr is the CheckResult (or null if the check failed open)
res.json({ risk: req.simplr?.risk_level });
});Blocked requests (risk high or above by default) get a 403 with a JSON envelope before your handler runs.
Fastify
import Fastify from "fastify";
import { simplrFastify } from "@simplr-ai/express/fastify";
const app = Fastify();
await app.register(simplrFastify, { apiKey: process.env.SIMPLR_API_KEY! });
app.post("/signup", async (req) => ({ risk: req.simplr?.risk_level }));Registers a preHandler hook and decorates request.simplr.
Hono
import { Hono } from "hono";
import { simplrHono, getSimplr } from "@simplr-ai/express/hono";
const app = new Hono();
app.use("*", simplrHono({ apiKey: process.env.SIMPLR_API_KEY! }));
app.post("/signup", (c) => c.json({ risk: getSimplr(c)?.risk_level }));The result is stored with c.set('simplr', result); read it with c.get('simplr') or the getSimplr(c) helper. Hono bodies are read async, so the default extractor uses headers only — pass a custom extract to also score body email/phone.
Next.js (app router)
Edge/Node middleware (middleware.ts):
import { simplrNextMiddleware } from "@simplr-ai/express/next";
export const middleware = simplrNextMiddleware({ apiKey: process.env.SIMPLR_API_KEY! });
export const config = { matcher: ["/api/:path*"] };Returns NextResponse.next() to allow, or a 403 NextResponse.json(...) to block.
Route-handler wrapper for app-router API routes (app/api/signup/route.ts):
import { withSimplr } from "@simplr-ai/express/next";
export const POST = withSimplr(
async (req) => {
// req.simplr is the CheckResult
return Response.json({ ok: true });
},
{ apiKey: process.env.SIMPLR_API_KEY! },
);Options
| Option | Type | Default | Description |
| --- | --- | --- | --- |
| apiKey | string | — (required) | Secret key (sk_…). Server-side only. |
| baseUrl | string | https://api.simplr-ai.com | API base URL (trailing slashes stripped). |
| timeoutMs | number | 15000 | Per-request timeout. |
| fetch | typeof fetch | global fetch | Override the fetch implementation. |
| extract | (req) => CheckInput | IP + user-agent + body email/phone | Build the CheckInput for a request. |
| onResult | (result, ctx) => void | — | Observe every result (and { req, input, blocked }). |
| block | (result) => boolean | { whenRiskAtLeast: RiskLevel } | { whenRiskAtLeast: "high" } | Decide whether to block. |
| ingestLogs | boolean | false | Ship a /v1/edge/logs entry per request. |
| deviceId | string | "simplr-edge-middleware" | Device id for ingested logs. |
| failOpen | boolean | true | Let requests through if the Simplr check fails. |
Threshold blocking
Risk levels are ordered low < medium < high < critical. The default block blocks when the result is at or above high (i.e. high and critical). Override with a threshold (block: { whenRiskAtLeast: "medium" }) or a custom predicate (block: (r) => r.risk_score > 80).
Fail-open
By default (failOpen: true) a Simplr outage — network error, timeout, or 5xx — does not take down your app: the middleware logs nothing to the client, attaches req.simplr = null, and continues to your handler. Set failOpen: false to fail closed and surface the error (Express forwards it to next(err); the other adapters re-throw).
API by subpath
@simplr-ai/express—createGuard,simplrExpress, helpers (riskRank,riskAtLeast,blockEnvelope,defaultExtract),createClient, and all types.@simplr-ai/express/fastify—simplrFastifyplugin.@simplr-ai/express/hono—simplrHono,getSimplr.@simplr-ai/express/next—simplrNextMiddleware,withSimplr.
License
Commercial software — see LICENSE.
