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