Development guide for using Limitly SDKs
# Node.js SDK
npm install @limitly/limitly-js
# Next.js SDK
npm install @limitly/limitly-nextjs
# Python SDK
pip install limitly-python
.env
file with your configuration:
LIMITLY_API_KEY=lk_1234567890abcdef1234567890abcdef
LIMITLY_BASE_URL=https://api.limitly.dev
// Node.js/Next.js
import { Limitly } from '@limitly/limitly-js';
const limitly = new Limitly({
apiKey: process.env.LIMITLY_API_KEY!
});
# Python
from limitly import Limitly
limitly = Limitly(api_key=os.getenv("LIMITLY_API_KEY"))
import express from 'express';
import { Limitly } from '@limitly/limitly-js';
const app = express();
const limitly = new Limitly({
apiKey: process.env.LIMITLY_API_KEY!
});
// Rate limiting middleware
app.use(async (req, res, next) => {
const userApiKey = req.headers['x-api-key'] as string;
if (!userApiKey) {
return res.status(401).json({ error: 'API key required' });
}
try {
const result = await limitly.validation.validate(
userApiKey,
req.path,
req.method
);
if (!result.success) {
return res.status(429).json({
error: result.error,
details: result.details
});
}
next();
} catch (error) {
console.error('Validation error:', error);
return res.status(500).json({ error: 'Internal server error' });
}
});
app.get('/api/users', (req, res) => {
res.json({ users: [] });
});
export default app;
// app/api/users/route.ts
import { Limitly } from '@limitly/limitly-nextjs';
const limitly = new Limitly({
apiKey: process.env.LIMITLY_API_KEY!
});
export async function GET(request: Request) {
const apiKey = request.headers.get('x-api-key');
if (!apiKey) {
return Response.json({ error: 'API key required' }, { status: 401 });
}
try {
const result = await limitly.validation.validate(
apiKey,
'/api/users',
'GET'
);
if (!result.success) {
return Response.json({
error: result.error,
details: result.details
}, { status: 429 });
}
return Response.json({ users: [] });
} catch (error) {
console.error('Validation error:', error);
return Response.json({ error: 'Internal server error' }, { status: 500 });
}
}
from fastapi import FastAPI, HTTPException, Depends
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from limitly import Limitly
app = FastAPI()
security = HTTPBearer()
limitly = Limitly(api_key=os.getenv("LIMITLY_API_KEY"))
async def validate_api_key(credentials: HTTPAuthorizationCredentials = Depends(security)):
api_key = credentials.credentials
result = limitly.validation.validate(api_key, "/api/users", "GET")
if not result.success:
raise HTTPException(status_code=429, detail="Rate limit exceeded")
return api_key
@app.get("/api/users")
async def get_users(api_key: str = Depends(validate_api_key)):
return {"users": []}
import { Limitly } from '@limitly/limitly-js';
describe('Rate Limiting', () => {
let limitly: Limitly;
beforeEach(() => {
limitly = new Limitly({
apiKey: process.env.LIMITLY_API_KEY!
});
});
test('should validate request successfully', async () => {
const result = await limitly.validation.validate(
'test_api_key',
'/api/test',
'GET'
);
expect(result.success).toBe(true);
expect(result.details).toBeDefined();
});
test('should handle rate limit exceeded', async () => {
const result = await limitly.validation.validate(
'exceeded_key',
'/api/test',
'GET'
);
expect(result.success).toBe(false);
expect(result.error).toBe('Rate limit exceeded');
});
});
describe('API Integration', () => {
test('should handle authentication', async () => {
const response = await request(app)
.get('/api/users')
.set('X-API-Key', 'valid_key');
expect(response.status).toBe(200);
});
test('should reject invalid API key', async () => {
const response = await request(app)
.get('/api/users')
.set('X-API-Key', 'invalid_key');
expect(response.status).toBe(401);
});
test('should handle rate limiting', async () => {
const response = await request(app)
.get('/api/users')
.set('X-API-Key', 'limited_key');
expect(response.status).toBe(429);
});
});
import { Limitly } from '@limitly/limitly-js';
const limitly = new Limitly({
apiKey: process.env.LIMITLY_API_KEY!,
debug: true // Enable debug logging
});
// Check your API key format
const apiKey = 'lk_1234567890abcdef1234567890abcdef'; // Must start with 'lk_'
// Check if user has exceeded their limit
const result = await limitly.validation.validate(apiKey, endpoint, method);
if (!result.success) {
console.log('Rate limit exceeded:', result.error);
console.log('Details:', result.details);
}
// Check API connectivity
try {
const response = await fetch('https://api.limitly.dev/v1/health');
console.log('API Status:', response.status);
} catch (error) {
console.error('API connectivity issue:', error);
}
import NodeCache from 'node-cache';
const cache = new NodeCache({ stdTTL: 60 }); // 60 seconds
app.use(async (req, res, next) => {
const userApiKey = req.headers['x-api-key'] as string;
const cacheKey = `${userApiKey}:${req.path}:${req.method}`;
// Check cache first
const cached = cache.get(cacheKey);
if (cached) {
// Use cached result
return next();
}
// Validate request
const result = await limitly.validation.validate(
userApiKey,
req.path,
req.method
);
if (result.success) {
// Cache successful validation
cache.set(cacheKey, result, 60);
}
next();
});
// For high-traffic applications, consider batching validation requests
const batchValidate = async (requests: Array<{apiKey: string, endpoint: string, method: string}>) => {
const results = await Promise.all(
requests.map(req =>
limitly.validation.validate(req.apiKey, req.endpoint, req.method)
)
);
return results;
};
# Production
LIMITLY_API_KEY=lk_production_key_here
LIMITLY_BASE_URL=https://api.limitly.dev
# Staging
LIMITLY_API_KEY=lk_staging_key_here
LIMITLY_BASE_URL=https://staging-api.limitly.dev
// Add health check endpoint
app.get('/health', async (req, res) => {
try {
// Test API connectivity
const result = await limitly.validation.validate(
'test_key',
'/health',
'GET'
);
res.json({
status: 'healthy',
api: 'connected'
});
} catch (error) {
res.status(500).json({
status: 'unhealthy',
error: error.message
});
}
});
try {
const result = await limitly.validation.validate(apiKey, endpoint, method);
if (!result.success) {
// Handle rate limiting
return res.status(429).json({
error: 'Rate limit exceeded',
retryAfter: result.details?.retryAfter
});
}
// Continue with request
} catch (error) {
// Handle network or API errors
console.error('Validation error:', error);
return res.status(500).json({ error: 'Internal server error' });
}
const result = await limitly.validation.validate(apiKey, endpoint, method);
if (!result.success) {
console.log('Rate limit exceeded:', {
apiKey: apiKey.substring(0, 8) + '...',
endpoint,
method,
error: result.error,
details: result.details
});
}
// Track validation results
const validationMetrics = {
total: 0,
allowed: 0,
rateLimited: 0,
errors: 0
};
const result = await limitly.validation.validate(apiKey, endpoint, method);
validationMetrics.total++;
if (result.success) {
validationMetrics.allowed++;
} else if (result.error?.includes('Rate limit')) {
validationMetrics.rateLimited++;
} else {
validationMetrics.errors++;
}
Was this page helpful?