@holdify/express
Express.js middleware for Holdify.
Installation
bash
npm install @holdify/expressQuick start
typescript
import express from 'express';
import { holdifyMiddleware } from '@holdify/express';
const app = express();
// Protect all /api routes
app.use('/api', holdifyMiddleware({
apiKey: process.env.HOLDIFY_PROJECT_KEY,
}));
app.get('/api/data', (req, res) => {
// Verification result available on req.holdify
const { remaining, plan } = req.holdify;
res.json({ data: 'protected', remaining });
});
app.listen(3000);Configuration
typescript
holdifyMiddleware({
// Required
apiKey: process.env.HOLDIFY_PROJECT_KEY,
// Optional: Custom API URL
baseUrl: 'https://api.holdify.io',
// Optional: Custom key extraction
getKey: (req) => {
return req.headers['x-custom-key'];
},
// Optional: Custom error handling
onError: (error, req, res) => {
res.status(error.statusCode || 500).json({
error: error.code,
message: error.message,
});
},
// Optional: Success callback
onSuccess: (result, req) => {
console.log(`Verified: ${result.remaining} remaining`);
},
});Key extraction
By default, the middleware looks for API keys in:
Authorization: Bearer <key>headerx-api-key: <key>header?api_key=<key>query parameter
Custom extraction:
typescript
holdifyMiddleware({
apiKey: process.env.HOLDIFY_PROJECT_KEY,
getKey: (req) => {
// Your custom logic
return req.headers['x-my-api-key'];
},
});Accessing verification result
typescript
app.get('/api/data', (req, res) => {
// Always available after middleware
const {
valid, // boolean
remaining, // number
limit, // number
reset, // unix timestamp
plan, // string
entitlements // string[]
} = req.holdify;
// Check entitlements
if (req.holdify.entitlements?.includes('feature:premium')) {
// Premium access
}
});Rate limit headers
The middleware automatically sets these headers:
| Header | Description |
|---|---|
| X-RateLimit-Limit | Maximum requests allowed |
| X-RateLimit-Remaining | Requests remaining |
| X-RateLimit-Reset | Unix timestamp when limit resets |
Selective protection
typescript
// Only protect specific routes
app.use('/api/protected', holdifyMiddleware({ apiKey }));
// Public routes (no middleware)
app.get('/api/public', (req, res) => {
res.json({ public: true });
});TypeScript
typescript
import type { Request } from 'express';
import type { VerifyResult } from '@holdify/express';
// req.holdify is typed
app.get('/api/data', (req: Request, res) => {
const result: VerifyResult = req.holdify;
});