> ## 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.

# Development

> Development guide for using Limitly SDKs

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

## Getting Started

### Setting Up Your Environment

1. **Install the SDK**
   ```bash theme={null}
   # 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:
   ```bash theme={null}
   LIMITLY_API_KEY=lk_1234567890abcdef1234567890abcdef
   LIMITLY_BASE_URL=https://api.limitly.dev
   ```

3. **Initialize the SDK**

   ```typescript theme={null}
   // Node.js/Next.js
   import { Limitly } from '@limitly/limitly-js';

   const limitly = new Limitly({
     apiKey: process.env.LIMITLY_API_KEY!
   });
   ```

   ```python theme={null}
   # Python
   from limitly import Limitly

   limitly = Limitly(api_key=os.getenv("LIMITLY_API_KEY"))
   ```

## Integration Examples

### Express.js Integration

```typescript theme={null}
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

```typescript theme={null}
// 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

```python theme={null}
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

```typescript theme={null}
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

```typescript theme={null}
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

```typescript theme={null}
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

```typescript theme={null}
// Check your API key format
const apiKey = 'lk_1234567890abcdef1234567890abcdef'; // Must start with 'lk_'
```

#### 2. Rate Limiting Issues

```typescript theme={null}
// 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

```typescript theme={null}
// 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

```typescript theme={null}
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

```typescript theme={null}
// 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

```bash theme={null}
# 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

```typescript theme={null}
// 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:

```typescript theme={null}
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:

```typescript theme={null}
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:

```typescript theme={null}
// 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

* [SDK Installation](/sdk/installation) - Install and configure the SDK
* [Request Validation](/sdk/validation) - Learn about request validation
* [API Key Management](/sdk/api-keys) - Manage API keys
* [Plans](/sdk/plans) - Configure usage plans
