Documentation Index
Fetch the complete documentation index at: https://docs.esperr.com/llms.txt
Use this file to discover all available pages before exploring further.
Start With Integrations For Faster SetupIf you want a recipe-backed path for a specific platform, start with the
Integrations guides. The SDK is best when you want
direct control inside your own middleware or handler code.
Installation
npm install esper-ts-client
# or
yarn add esper-ts-client
# or
pnpm add esper-ts-client
Basic Usage
import { EsperClient, MitigationAction } from "esper-ts-client";
const client = new EsperClient({
apiKey: "your-api-key",
});
// Send the first request's traffic to Esper beacon for analysis.
await client.sendBeaconEvent({
type: "http_request",
ip: "192.168.1.1",
userAgent: req.headers["user-agent"],
path: "/login",
method: "POST",
sessionId: "session-123",
data: {
requestId: "req-1",
},
});
// Check a later request against active mitigation state.
const result = await client.checkMitigation({
ip: "192.168.1.1",
userAgent: req.headers["user-agent"],
path: "/checkout",
method: "POST",
metadata: {
requestId: "req-2",
sessionId: "session-123",
},
});
if (result.action === MitigationAction.Block) {
res.status(403).json({ error: "Access denied" });
} else if (result.action === MitigationAction.Challenge) {
res.status(429).json({ challenge: result.challenge });
} else {
// Allow request to proceed
next();
}
Configuration
const client = new EsperClient({
apiKey: "your-api-key", // Required
apiUrl: "https://api.esperr.com", // Optional
timeout: 30000, // Optional (milliseconds)
retries: 3, // Optional
retryDelay: 1000, // Optional (milliseconds)
});
API Methods
checkMitigation(request)
Check if a request should be mitigated.const result = await client.checkMitigation({
ip: '192.168.1.1', // Required
userAgent: 'Mozilla/5.0...', // Optional
path: '/api/endpoint', // Optional
method: 'POST', // Optional
headers: { // Optional
'x-custom': 'value'
},
metadata: { // Optional
userId: '123',
sessionId: 'abc-xyz'
}
});
// Response
{
action: MitigationAction,
reason?: string,
score?: number,
challenge?: {
type: string,
token: string,
params?: Record<string, any>
}
}
verifyChallenge(token, response)
Verify a user’s response to a challenge.const isValid = await client.verifyChallenge(
"challenge-token-123",
"user-response-456",
);
if (isValid) {
console.log("Challenge passed");
}
sendBeaconEvent(event)
Send request traffic to the beacon server so Esper can analyze it and update state for later mitigation checks.await client.sendBeaconEvent({
type: "page_view",
ip: "192.168.1.1",
userAgent: "Mozilla/5.0...",
sessionId: "session-123",
data: {
page: "/home",
referrer: "/login",
},
});
getUsage()
Get API usage statistics.const usage = await client.getUsage();
console.log(`Total requests: ${usage.requests}`);
console.log(`Blocked: ${usage.blocked}`);
console.log(`Challenged: ${usage.challenged}`);
console.log(`Allowed: ${usage.allowed}`);
Framework Integration
Express Middleware
import express from "express";
import { EsperClient, MitigationAction } from "esper-ts-client";
const app = express();
const esper = new EsperClient({
apiKey: process.env.ESPER_API_KEY,
});
// Middleware function
const esperMiddleware = async (req, res, next) => {
try {
const result = await esper.checkMitigation({
ip: req.ip,
userAgent: req.headers["user-agent"],
path: req.path,
method: req.method,
});
if (result.action === MitigationAction.Block) {
return res.status(403).json({
error: "Access denied",
});
}
if (result.action === "challenge") {
return res.status(429).json({
challenge: result.challenge,
});
}
// Store result for later use
req.esperResult = result;
next();
} catch (error) {
console.error("Esper error:", error);
// Allow request on error
next();
}
};
// Apply middleware
app.use(esperMiddleware);
Next.js API Routes
// pages/api/protected.ts
import { NextApiRequest, NextApiResponse } from "next";
import { EsperClient, MitigationAction } from "esper-ts-client";
const esper = new EsperClient({
apiKey: process.env.ESPER_API_KEY,
});
export default async function handler(
req: NextApiRequest,
res: NextApiResponse,
) {
// Check mitigation
const result = await esper.checkMitigation({
ip: req.headers["x-forwarded-for"] || req.socket.remoteAddress,
userAgent: req.headers["user-agent"],
path: req.url,
method: req.method,
});
if (result.action === MitigationAction.Block) {
return res.status(403).json({
error: "Access denied",
});
}
if (result.action === "challenge") {
return res.status(429).json({
challenge: result.challenge,
});
}
// Handle protected route
res.json({ message: "Protected data" });
}
Fastify Plugin
import fastify from "fastify";
import { EsperClient, MitigationAction } from "esper-ts-client";
const app = fastify();
app.register(async function esperPlugin(app) {
const esper = new EsperClient({
apiKey: process.env.ESPER_API_KEY,
});
app.addHook("preHandler", async (request, reply) => {
const result = await esper.checkMitigation({
ip: request.ip,
userAgent: request.headers["user-agent"],
path: request.url,
method: request.method,
});
if (result.action === MitigationAction.Block) {
reply.code(403).send({
error: "Access denied",
});
}
if (result.action === "challenge") {
reply.code(429).send({
challenge: result.challenge,
});
}
request.esperResult = result;
});
});
Browser Usage
The SDK can be used in browser environments for client-side protection:<script type="module">
import { EsperClient } from "https://cdn.jsdelivr.net/npm/esper-ts-client/+esm";
const client = new EsperClient({
apiKey: "your-public-api-key",
});
// Send page view event
client.sendBeaconEvent({
type: "page_view",
sessionId: sessionStorage.getItem("sessionId"),
data: {
page: window.location.pathname,
referrer: document.referrer,
},
});
</script>
Error Handling
import { EsperClient, MitigationAction } from "esper-ts-client";
try {
const result = await client.checkMitigation(request);
// Handle result
} catch (error) {
if (error.response) {
// API error response
console.error("API error:", error.response.data);
} else if (error.request) {
// Network error
console.error("Network error:", error.message);
} else {
// Other error
console.error("Error:", error.message);
}
// Allow request on error
next();
}
TypeScript Support
The SDK includes full TypeScript definitions:import {
EsperClient,
EsperConfig,
MitigationRequest,
MitigationResponse,
BeaconEvent,
ChallengeData,
} from "esper-ts-client";
// All types are fully typed
const config: EsperConfig = {
apiKey: "your-api-key",
timeout: 30000,
};
const request: MitigationRequest = {
ip: "192.168.1.1",
userAgent: "Mozilla/5.0...",
};
Testing
// Mock the client for testing
jest.mock("esper-ts-client");
import { EsperClient, MitigationAction } from "esper-ts-client";
const mockClient = EsperClient as jest.MockedClass<typeof EsperClient>;
beforeEach(() => {
mockClient.prototype.checkMitigation.mockResolvedValue({
action: "allow",
score: 10,
});
});
test("should allow valid request", async () => {
const result = await client.checkMitigation({
ip: "192.168.1.1",
});
expect(result.action).toBe("allow");
});