Building a Public API: Versioning, Documentation, and Rate Limits
Shipping an internal API is forgiving. A public API is a contract. Breaking it breaks your users' production systems.
Versioning Strategy
URL versioning is recommended for most APIs:
app.use('/v1', v1Router);
app.use('/v2', v2Router);
Breaking changes require a new version: removing a field, changing a type, removing an endpoint.
Non-breaking: adding new fields, adding optional parameters, adding endpoints.
Rate Limiting
import rateLimit from 'express-rate-limit';
const apiLimiter = rateLimit({
windowMs: 60 * 1000,
max: 100,
standardHeaders: true,
keyGenerator: (req) => req.headers['x-api-key'] as string || req.ip,
});
app.use('/v1/', apiLimiter);
Always return standard headers: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset.
API Key Authentication
async function validateApiKey(req: Request, res: Response, next: NextFunction) {
const apiKey = req.headers['x-api-key'];
if (!apiKey) return res.status(401).json({ error: 'API key required' });
const keyHash = crypto.createHash('sha256').update(apiKey as string).digest('hex');
const key = await db.apiKeys.findUnique({ where: { hash: keyHash } });
if (!key || key.revokedAt) return res.status(401).json({ error: 'Invalid API key' });
req.apiKey = key;
next();
}
Sunset Policy
When deprecating old versions:
- Announce with a specific end-of-life date (minimum 6 months)
- Add
DeprecationandSunsetheaders - Email users who hit the deprecated version in last 30 days
MCP APIs: The Next Frontier
Model Context Protocol is changing how AI agents consume APIs. Before going public, audit your MCP server with the MCP Security Scanner — injection vulnerabilities and auth gaps in MCP servers are a growing attack surface.
Top comments (0)