Best Practices
Follow these best practices to build robust and efficient applications.
Security
Protect Your API Keys
- Never commit API keys to version control
- Use environment variables for sensitive data
- Rotate keys regularly
- Use different keys for development and production
// Good ✅
const client = new Client({
apiKey: process.env.API_KEY
});
// Bad ❌
const client = new Client({
apiKey: 'sk_live_abc123...'
});
Validate Input
Always validate and sanitize user input before sending to the API:
function validatePrompt(prompt) {
if (typeof prompt !== 'string') {
throw new Error('Prompt must be a string');
}
if (prompt.length > 10000) {
throw new Error('Prompt too long');
}
return prompt.trim();
}
Performance
Use Streaming for Long Responses
For better user experience, stream responses instead of waiting for completion:
const stream = await client.generateStream({ prompt });
for await (const chunk of stream) {
updateUI(chunk.text);
}
Implement Caching
Cache responses when appropriate to reduce API calls:
const cache = new Map();
async function cachedGenerate(prompt) {
if (cache.has(prompt)) {
return cache.get(prompt);
}
const result = await client.generate({ prompt });
cache.set(prompt, result);
return result;
}
Batch Requests
Group multiple requests when possible to reduce latency:
const results = await Promise.all(
prompts.map(p => client.generate({ prompt: p }))
);
Error Handling
Implement Retry Logic
Handle transient failures with exponential backoff:
async function retryWithBackoff(fn, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await fn();
} catch (error) {
if (i === maxRetries - 1) throw error;
if (error.status >= 500 || error.status === 429) {
await new Promise(r => setTimeout(r, Math.pow(2, i) * 1000));
} else {
throw error;
}
}
}
}
Handle Rate Limits
Monitor and respect rate limits:
class RateLimitedClient {
constructor(client, requestsPerMinute) {
this.client = client;
this.queue = [];
this.interval = 60000 / requestsPerMinute;
}
async generate(params) {
return new Promise((resolve, reject) => {
this.queue.push({ params, resolve, reject });
this.processQueue();
});
}
processQueue() {
if (this.queue.length === 0) return;
const { params, resolve, reject } = this.queue.shift();
this.client.generate(params)
.then(resolve)
.catch(reject);
setTimeout(() => this.processQueue(), this.interval);
}
}
Monitoring
Log API Usage
Track your API usage and performance:
const startTime = Date.now();
try {
const result = await client.generate({ prompt });
const duration = Date.now() - startTime;
console.log(`Request completed in ${duration}ms`);
console.log(`Tokens used: ${result.usage.totalTokens}`);
} catch (error) {
console.error('Request failed:', error);
}
Set Timeouts
Always set appropriate timeouts:
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 30000);
try {
const result = await client.generate(
{ prompt },
{ signal: controller.signal }
);
} finally {
clearTimeout(timeout);
}
Testing
Mock API Calls
Use mocks in your tests:
import { jest } from '@jest/globals';
const mockClient = {
generate: jest.fn().mockResolvedValue({
text: 'Mocked response',
usage: { totalTokens: 10 }
})
};
Next Steps
- Review the API Reference
- Check out Code Examples
- Learn about FAQ