Skip to main content

ChatGPT API Best Practices

Complete guide to using the OpenAI API effectively, from authentication to production deployment.

Getting Started​

1. Get API Access​

  1. Create account at platform.openai.com
  2. Add payment method
  3. Generate API key
  4. 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:

ModelSpeedCostUse Case
gpt-5FastMidGeneral purpose
gpt-5-thinkingSlowMidComplex reasoning
gpt-4oFastestLowSimple tasks
gpt-4.1MediumHighHigh 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!