ChatGPT API Best Practices
Complete guide to using the OpenAI API effectively, from authentication to production deployment.
Getting Started
1. Get API Access
- Create account at platform.openai.com
- Add payment method
- Generate API key
- Security: Never commit API keys to code repositories
2. Install SDK
# Node.js
npm install openai
# Python
pip install openai
3. Basic Setup
import OpenAI from "openai";
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY, // Store in environment variables
});
const completion = await openai.chat.completions.create({
model: "gpt-5",
messages: [
{ role: "system", content: "You are a helpful assistant." },
{ role: "user", content: "Hello!" }
],
});
console.log(completion.choices[0].message.content);
Key Concepts
Models
Choose the right model for your task:
| Model | Speed | Cost | Use Case |
|---|---|---|---|
gpt-5 | Fast | Mid | General purpose |
gpt-5-thinking | Slow | Mid | Complex reasoning |
gpt-4o | Fastest | Low | Simple tasks |
gpt-4.1 | Medium | High | High quality |
Temperature
Controls randomness:
// More creative (0.7-1.0)
temperature: 0.9 // For creative writing
// Balanced (0.5-0.7)
temperature: 0.6 // For general chat
// More deterministic (0.0-0.4)
temperature: 0.2 // For code, data extraction
Max Tokens
Limit response length:
max_tokens: 150 // Short responses
max_tokens: 500 // Medium responses
max_tokens: 2000 // Long-form content
Production Best Practices
1. Error Handling
async function safeAPICall(messages) {
try {
const completion = await openai.chat.completions.create({
model: "gpt-5",
messages: messages,
});
return completion.choices[0].message;
} catch (error) {
if (error.response?.status === 429) {
// Rate limit - implement exponential backoff
await sleep(Math.pow(2, retryCount) * 1000);
return safeAPICall(messages); // Retry
} else if (error.response?.status === 500) {
// Server error - retry with different approach
console.error("Server error:", error);
throw error;
} else {
// Other errors
console.error("API error:", error);
throw error;
}
}
}
2. Rate Limiting
import pLimit from 'p-limit';
const limit = pLimit(10); // Max 10 concurrent requests
const promises = tasks.map(task =>
limit(() => processWithChatGPT(task))
);
await Promise.all(promises);
3. Retry Logic 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;
const delay = Math.min(1000 * Math.pow(2, i), 10000);
console.log(`Retry ${i + 1} after ${delay}ms`);
await sleep(delay);
}
}
}
4. Response Validation
function validateResponse(completion) {
if (!completion.choices || completion.choices.length === 0) {
throw new Error("No response from API");
}
const message = completion.choices[0].message;
if (!message.content || message.content.trim() === '') {
throw new Error("Empty response content");
}
return message;
}
Advanced Patterns
Streaming Responses
For better UX with long responses:
const stream = await openai.chat.completions.create({
model: "gpt-5",
messages: messages,
stream: true,
});
for await (const chunk of stream) {
const content = chunk.choices[0]?.delta?.content || '';
process.stdout.write(content); // Stream to user in real-time
}
Function Calling
Extend ChatGPT with custom functions:
const tools = [{
type: "function",
function: {
name: "get_weather",
description: "Get current weather in a location",
parameters: {
type: "object",
properties: {
location: {
type: "string",
description: "City name"
}
},
required: ["location"]
}
}
}];
const completion = await openai.chat.completions.create({
model: "gpt-5",
messages: messages,
tools: tools,
});
// Check if function was called
if (completion.choices[0].message.tool_calls) {
const toolCall = completion.choices[0].message.tool_calls[0];
// Execute your function
const result = getWeather(JSON.parse(toolCall.function.arguments));
// Send result back
messages.push({
role: "tool",
tool_call_id: toolCall.id,
content: JSON.stringify(result)
});
}
Conversation Management
class ConversationManager {
constructor(systemPrompt, maxMessages = 10) {
this.messages = [
{ role: "system", content: systemPrompt }
];
this.maxMessages = maxMessages;
}
addUserMessage(content) {
this.messages.push({ role: "user", content });
this.trimHistory();
}
addAssistantMessage(content) {
this.messages.push({ role: "assistant", content });
}
trimHistory() {
// Keep system message + last N messages
if (this.messages.length > this.maxMessages + 1) {
this.messages = [
this.messages[0], // Keep system message
...this.messages.slice(-(this.maxMessages))
];
}
}
async getResponse() {
const completion = await openai.chat.completions.create({
model: "gpt-5",
messages: this.messages,
});
const response = completion.choices[0].message.content;
this.addAssistantMessage(response);
return response;
}
}
Security Best Practices
1. API Key Management
// ❌ Never do this
const apiKey = "sk-...";
// ✅ Use environment variables
const apiKey = process.env.OPENAI_API_KEY;
// ✅ Use secret management services
const apiKey = await secrets.getSecret("OPENAI_API_KEY");
2. Input Sanitization
function sanitizeInput(userInput) {
// Remove potential injection attempts
return userInput
.replace(/[<>]/g, '') // Remove HTML tags
.slice(0, 4000); // Limit length
}
const userMessage = sanitizeInput(req.body.message);
3. Output Filtering
function filterSensitiveInfo(response) {
// Remove any accidentally generated sensitive patterns
return response
.replace(/\b\d{3}-\d{2}-\d{4}\b/g, '[SSN REDACTED]') // SSN
.replace(/\b\d{16}\b/g, '[CARD REDACTED]'); // Credit cards
}
4. Rate Limiting Per User
const userLimits = new Map();
function checkUserLimit(userId) {
const now = Date.now();
const userLimit = userLimits.get(userId) || {count: 0, resetTime: now + 3600000};
if (now > userLimit.resetTime) {
userLimit.count = 0;
userLimit.resetTime = now + 3600000; // Reset every hour
}
if (userLimit.count >= 100) { // 100 requests/hour
throw new Error("Rate limit exceeded");
}
userLimit.count++;
userLimits.set(userId, userLimit);
}
Monitoring & Logging
Usage Tracking
const usageStats = {
requests: 0,
tokens: 0,
cost: 0,
};
async function trackedAPICall(messages) {
const startTime = Date.now();
const completion = await openai.chat.completions.create({
model: "gpt-5",
messages: messages,
});
// Track metrics
usageStats.requests++;
usageStats.tokens += completion.usage.total_tokens;
usageStats.cost += calculateCost(completion.usage);
// Log
console.log({
timestamp: new Date().toISOString(),
duration: Date.now() - startTime,
tokens: completion.usage.total_tokens,
cost: calculateCost(completion.usage),
});
return completion;
}
Error Logging
function logError(error, context) {
console.error({
timestamp: new Date().toISOString(),
error: error.message,
stack: error.stack,
context: context,
// Send to monitoring service (e.g., Sentry, DataDog)
});
}
Performance Optimization
1. Batch Processing
async function batchProcess(items) {
const BATCH_SIZE = 10;
const results = [];
for (let i = 0; i < items.length; i += BATCH_SIZE) {
const batch = items.slice(i, i + BATCH_SIZE);
const batchPromises = batch.map(item => processItem(item));
const batchResults = await Promise.all(batchPromises);
results.push(...batchResults);
// Rate limiting pause between batches
if (i + BATCH_SIZE < items.length) {
await sleep(1000); // 1 second pause
}
}
return results;
}
2. Response Caching
const cache = new Map();
async function cachedCompletion(cacheKey, messages) {
if (cache.has(cacheKey)) {
return cache.get(cacheKey);
}
const completion = await openai.chat.completions.create({
model: "gpt-5",
messages: messages,
});
const response = completion.choices[0].message.content;
cache.set(cacheKey, response);
// Clear cache after 1 hour
setTimeout(() => cache.delete(cacheKey), 3600000);
return response;
}
Testing
Unit Testing API Calls
// Mock for testing
jest.mock('openai');
test('processes user message correctly', async () => {
const mockCreate = jest.fn().mockResolvedValue({
choices: [{
message: { content: "Hello!" }
}]
});
OpenAI.prototype.chat = {
completions: { create: mockCreate }
};
const result = await processMessage("Hi");
expect(result).toBe("Hello!");
expect(mockCreate).toHaveBeenCalledWith({
model: "gpt-5",
messages: expect.arrayContaining([
expect.objectContaining({ content: "Hi" })
])
});
});
Common Pitfalls
❌ Don't: Send Entire Conversation History
// Grows unbounded, wastes tokens
const messages = [...allPreviousMessages, newMessage];
✅ Do: Manage Context Window
// Keep only relevant recent messages
const messages = [systemMessage, ...last10Messages, newMessage];
❌ Don't: Ignore Token Limits
// No limit - can fail or cost too much
await openai.chat.completions.create({...});
✅ Do: Set Appropriate Limits
await openai.chat.completions.create({
max_tokens: 500, // Reasonable limit
...
});
Production Checklist
- API keys stored in environment variables
- Error handling implemented
- Rate limiting configured
- Retry logic with exponential backoff
- Input sanitization active
- Output validation in place
- Usage tracking enabled
- Logging configured
- Monitoring alerts set up
- Cost controls established
- Testing coverage adequate
- Documentation complete
Resources
Build robust, production-ready ChatGPT integrations with these best practices!