Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.lintliot.com/llms.txt

Use this file to discover all available pages before exploring further.

The Express adapter wraps LintLiot’s full protection stack into standard Express middleware. You mount it once before your routes and every request is inspected — no per-route changes required. The adapter also exports helpers for per-route rate limits and permission guards when you need finer control.

Prerequisites

Basic setup

1

Create a Lintliot instance

Import createLintliot and initialize it with your API key. Create the instance once at the module level — not inside a request handler.
import { createLintliot } from '@lintliot/sdk'

const lintliot = createLintliot({
  apiKey: process.env.LINTLIOT_API_KEY!,
})
2

Mount the global middleware

Use lintliot.protect() as the first app.use call, before any router or route definition.
import express from 'express'
import { createLintliot } from '@lintliot/sdk'

const app = express()
const lintliot = createLintliot({ apiKey: process.env.LINTLIOT_API_KEY! })

// Mount before all routes
app.use(lintliot.protect())

app.get('/api/users', (req, res) => {
  res.json({ users: [] })
})

app.listen(3000)
lintliot.protect() must be registered before any route or router middleware. Mounting it after routes means those routes will not be protected.

Use the Express-specific adapter

For tighter Express integration — including typed req.lintliot context and proper error forwarding via next(err) — import from @lintliot/sdk/express:
import express from 'express'
import { createLintliot } from '@lintliot/sdk'
import { createExpressMiddleware } from '@lintliot/sdk/express'

const app = express()
const lintliot = createLintliot({ apiKey: process.env.LINTLIOT_API_KEY! })

app.use(createExpressMiddleware(lintliot, {
  rateLimit: { max: 200, windowMs: 60_000 },
  waf: 'block',
  securityHeaders: true,
  skipRoutes: ['/health', '/metrics'],
}))
After createExpressMiddleware runs, downstream handlers can read req.lintliot for the resolved IP address and user ID:
app.get('/api/profile', (req, res) => {
  const { ip, userId } = req.lintliot
  res.json({ ip, userId })
})

Per-route rate limiting

Use lintliot.rateLimit() to apply a stricter limit to a specific route, such as a login endpoint. Add it as a route-level middleware before the handler:
app.post(
  '/api/auth/login',
  lintliot.rateLimit({ max: 5, windowMs: 60_000 }),
  loginHandler
)
Or use the adapter’s expressRateLimit helper:
import { expressRateLimit } from '@lintliot/sdk/express'

app.post(
  '/api/auth/login',
  expressRateLimit(lintliot, { max: 5, windowMs: 60_000 }),
  loginHandler
)
The global lintliot.protect() middleware already applies a baseline rate limit to all routes. Per-route limits let you enforce tighter thresholds for sensitive endpoints like authentication and password reset.

Permission middleware

Use lintliot.can('permission') to guard a route. It checks the authenticated user’s permissions against LintLiot IAM before the handler runs:
// Single permission check
app.delete('/api/users/:id', lintliot.can('users:delete'), deleteUserHandler)

// Protect an admin route
app.get('/api/admin/reports', lintliot.can('admin:read'), reportsHandler)
Or use expressCan from the adapter for multiple permissions (all must pass):
import { expressCan } from '@lintliot/sdk/express'

app.post(
  '/api/admin/billing',
  expressCan(lintliot, 'admin:write', 'billing:manage'),
  billingHandler
)
If the request is not authenticated, the middleware returns 401. If the user lacks the required permission, it returns 403.

One-line setup (no separate instance)

If you prefer not to manage the lintliot instance yourself, use lintliotExpress which handles instance caching internally:
import express from 'express'
import { lintliotExpress } from '@lintliot/sdk/express'

const app = express()

app.use(lintliotExpress({ apiKey: process.env.LINTLIOT_API_KEY! }))

Register routes for pentest discovery

After defining all your routes, call registerExpressRoutes to send the route list to the LintLiot API. This powers the Pentest Engine’s route discovery:
import { registerExpressRoutes } from '@lintliot/sdk/express'

// Define all routes first
app.get('/api/users', usersHandler)
app.post('/api/login', loginHandler)

// Then register them (fire-and-forget, non-blocking)
registerExpressRoutes(lintliot, app)

Error handling

Mount lintliotErrorHandler as your last middleware to format LintLiot errors consistently:
import { lintliotErrorHandler } from '@lintliot/sdk/express'

// After all routes
app.use(lintliotErrorHandler())