Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.limitly.dev/llms.txt

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

This guide covers development workflows and best practices for integrating Limitly into your applications.

Getting Started

Setting Up Your Environment

  1. Install the SDK
    # Node.js SDK
    npm install @limitly/limitly-js
    
    # Next.js SDK
    npm install @limitly/limitly-nextjs
    
    # Python SDK
    pip install limitly-python
    
  2. Environment Variables Create a .env file with your configuration:
    LIMITLY_API_KEY=lk_1234567890abcdef1234567890abcdef
    LIMITLY_BASE_URL=https://api.limitly.dev
    
  3. Initialize the SDK
    // 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"))
    

Integration Examples

Express.js Integration

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;

Next.js Integration

// 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 });
  }
}

FastAPI Integration

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": []}

Testing Your Integration

Unit Testing

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');
  });
});

Integration Testing

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);
  });
});

Debugging

Enable Debug Logging

import { Limitly } from '@limitly/limitly-js';

const limitly = new Limitly({
  apiKey: process.env.LIMITLY_API_KEY!,
  debug: true // Enable debug logging
});

Common Issues

1. Authentication Errors

// Check your API key format
const apiKey = 'lk_1234567890abcdef1234567890abcdef'; // Must start with 'lk_'

2. Rate Limiting Issues

// 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);
}

3. Network Issues

// Check API connectivity
try {
  const response = await fetch('https://api.limitly.dev/functions/v1/health');
  console.log('API Status:', response.status);
} catch (error) {
  console.error('API connectivity issue:', error);
}

Performance Optimization

Caching Validation Results

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();
});

Batch Validation

// 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;
};

Deployment

Environment Configuration

# 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

Health Checks

// 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
    });
  }
});

Best Practices

1. Error Handling

Always handle validation errors gracefully:
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' });
}

2. Logging

Implement proper logging for debugging:
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
  });
}

3. Monitoring

Monitor your rate limiting implementation:
// 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++;
}

Next Steps