Module 2: OpenAI API - Introduction

Pricing, Rate Limits, and Cost Optimization

Capsule overview

You already know how to use the OpenAI API. Now you need to understand:

  • How cost is calculated (input/output tokens)
  • Rate limits (how many requests you can make)
  • How to optimize costs (without sacrificing quality)

This capsule gives you tools to keep your bill under control.

Time: 25 minutes
Difficulty: Medium


💰 OpenAI Pricing (February 2026)

Models and prices:

ModelInput ($/1M tokens)Output ($/1M tokens)Context Window
gpt-4-turbo$10.00$30.00128k
gpt-4$30.00$60.008k
gpt-3.5-turbo$0.50$1.5016k

Updated: Always check at https://openai.com/pricing


How you're billed:

Formula:

Cost = (Input tokens × Input price) + (Output tokens × Output price)

Example:

  • Prompt: 100 tokens (input)
  • Response: 200 tokens (output)
  • Model: GPT-3.5-turbo

Calculation:

Input:  100 tokens × $0.50/1M = $0.00005
Output: 200 tokens × $1.50/1M = $0.00030
Total:  $0.00035 per request

For 1000 requests: $0.35


🔢 Counting Tokens

Method 1: From the response (exact)

response = client.chat.completions.create(
    model="gpt-3.5-turbo",
    messages=[{"role": "user", "content": "Hello"}]
)

usage = response.usage
print(f"Input tokens:  {usage.prompt_tokens}")
print(f"Output tokens: {usage.completion_tokens}")
print(f"Total tokens:  {usage.total_tokens}")

Output:

Input tokens:  8
Output tokens: 12
Total tokens:  20

Method 2: Estimating with tiktoken (before the request)

Useful for calculating cost BEFORE sending.

Installation:

pip install tiktoken

Code:

import tiktoken

def count_tokens(text: str, model: str = "gpt-3.5-turbo") -> int:
    """Count the tokens in a piece of text."""
    encoding = tiktoken.encoding_for_model(model)
    return len(encoding.encode(text))

# Test
prompt = "Explain what Python is in 50 words"
tokens = count_tokens(prompt)
print(f"Prompt has {tokens} tokens")

# Estimate cost (assuming 100 output tokens)
input_cost = tokens * 0.50 / 1_000_000
output_cost = 100 * 1.50 / 1_000_000
total_cost = input_cost + output_cost
print(f"Estimated cost: ${total_cost:.6f}")

Rules of thumb (approximate):

  • 1 token ≈ 4 characters (English)
  • 1 token ≈ 0.75 words (English)
  • Spanish: 1.2-1.5x more tokens (longer words)

Example:

  • "Hello world" = 2 tokens (English)
  • "Hola mundo" = 3 tokens (Spanish)

📊 Calculating Your App's Cost

Real example: FAQ Chatbot

Specs:

  • 1000 users/day
  • 3 average queries/user
  • 50 average input tokens
  • 100 average output tokens

Monthly calculation:

# Volume
users_per_day = 1000
queries_per_user = 3
days_per_month = 30
total_queries = users_per_day * queries_per_user * days_per_month  # 90,000

# Tokens
input_tokens_per_query = 50
output_tokens_per_query = 100

total_input_tokens = total_queries * input_tokens_per_query    # 4.5M
total_output_tokens = total_queries * output_tokens_per_query  # 9M

# Cost (GPT-3.5-turbo)
input_cost = (total_input_tokens / 1_000_000) * 0.50   # $2.25
output_cost = (total_output_tokens / 1_000_000) * 1.50  # $13.50

total_monthly_cost = input_cost + output_cost  # $15.75/month

Result: ~$16/month for 90k queries


🚦 Rate Limits

What they are:

Limits on requests/tokens per minute to prevent abuse.

Tiers (based on how much you've spent):

TierRequirementGPT-3.5 (RPM)GPT-4 (RPM)TPM
Free$0 spent60340k
Tier 1$5+ spent500500200k
Tier 2$50+ spent500050002M

RPM: Requests per minute
TPM: Tokens per minute

See your limits: https://platform.openai.com/account/rate-limits


Error when you exceed them:

openai.RateLimitError: Rate limit reached for requests

Solution: Implement retries (capsule 07).


💡 Cost Optimization Strategies

1. Use GPT-3.5 when it's enough

Rule: GPT-4 only if you NEED maximum quality.

Example:

  • Simple FAQ → GPT-3.5 ✅
  • Complex legal analysis → GPT-4 ✅
  • Classification → GPT-3.5 ✅

Savings: 20x (GPT-4 is 20x more expensive)


2. Minimize context (history)

❌ Bad:

messages = last_50_messages  # 5000 tokens

✅ Good:

messages = last_5_messages   # 500 tokens

Savings: 10x fewer input tokens


3. Use max_tokens to limit output

❌ Bad:

max_tokens=None  # GPT decides (may generate 1000+ tokens)

✅ Good:

max_tokens=150  # Enough for an FAQ

Savings: 6.6x fewer output tokens


4. Cache common responses

import json

# In-memory cache (simple)
cache = {}

def ask_with_cache(prompt: str) -> str:
    """Look in the cache before calling the API."""
    
    # Check cache
    if prompt in cache:
        print("[CACHE HIT]")
        return cache[prompt]
    
    # Cache miss → Call the API
    print("[CACHE MISS - API call]")
    response = client.chat.completions.create(
        model="gpt-3.5-turbo",
        messages=[{"role": "user", "content": prompt}]
    )
    
    answer = response.choices[0].message.content
    
    # Save in cache
    cache[prompt] = answer
    
    return answer

# Test
print(ask_with_cache("What is Python?"))  # MISS (calls the API)
print(ask_with_cache("What is Python?"))  # HIT (does not call the API)

Savings: 100% for repeated queries


5. Batching (grouped requests)

If you process many similar texts:

# ❌ Bad: 100 requests
for text in texts:
    response = client.chat.completions.create(...)

# ✅ Good: 1 request with a batch
batch_prompt = "\n\n".join([f"Text {i}: {text}" for i, text in enumerate(texts)])
response = client.chat.completions.create(
    messages=[{"role": "user", "content": f"Classify these texts:\n{batch_prompt}"}]
)

Savings: Request overhead (less time, similar cost)


6. Summarization of long conversations

Instead of sending 50 messages:

# Every 20 messages, summarize
if len(messages) > 20:
    summary = summarize(messages[:-5])  # Summarize the old ones
    messages = [system_message, summary] + messages[-5:]  # Keep the last 5

Savings: 80% input tokens in long conversations


📈 Usage Monitoring

OpenAI Dashboard:

  1. Go to: https://platform.openai.com/usage
  2. You'll see charts for:
    • Daily cost
    • Requests per model
    • Tokens consumed

Set up alerts:

  • Soft limit: $5/month (email alert)
  • Hard limit: $10/month (stops requests)

Logging in code:

import json
from datetime import datetime

def log_usage(prompt: str, response):
    """Save usage to a JSON file."""
    
    log_entry = {
        "timestamp": datetime.now().isoformat(),
        "model": response.model,
        "prompt_tokens": response.usage.prompt_tokens,
        "completion_tokens": response.usage.completion_tokens,
        "total_tokens": response.usage.total_tokens,
        "prompt_preview": prompt[:50],  # First 50 chars
    }
    
    # Append to file
    with open("usage_log.json", "a") as f:
        f.write(json.dumps(log_entry) + "\n")

# Usage
response = client.chat.completions.create(...)
log_usage(prompt, response)

Analysis afterwards:

import json

total_tokens = 0
with open("usage_log.json") as f:
    for line in f:
        entry = json.loads(line)
        total_tokens += entry["total_tokens"]

cost = (total_tokens / 1_000_000) * 1.0  # Assuming an avg of $1/1M
print(f"Total cost: ${cost:.2f}")

🧮 Cost Calculator (Tool)

def calculate_cost(
    input_tokens: int,
    output_tokens: int,
    model: str = "gpt-3.5-turbo"
) -> dict:
    """Calculate the cost of a request."""
    
    pricing = {
        "gpt-3.5-turbo": {"input": 0.50, "output": 1.50},
        "gpt-4-turbo": {"input": 10.00, "output": 30.00},
        "gpt-4": {"input": 30.00, "output": 60.00},
    }
    
    if model not in pricing:
        raise ValueError(f"Unknown model: {model}")
    
    prices = pricing[model]
    
    input_cost = (input_tokens / 1_000_000) * prices["input"]
    output_cost = (output_tokens / 1_000_000) * prices["output"]
    total_cost = input_cost + output_cost
    
    return {
        "input_tokens": input_tokens,
        "output_tokens": output_tokens,
        "input_cost": input_cost,
        "output_cost": output_cost,
        "total_cost": total_cost,
        "model": model
    }

# Test
result = calculate_cost(100, 200, "gpt-3.5-turbo")
print(f"Total cost: ${result['total_cost']:.6f}")

📊 Summary

Key concepts:

  1. Pricing:

    • Input tokens × Input price
    • Output tokens × Output price
    • GPT-3.5: $0.50/$1.50 per 1M tokens
  2. Rate limits:

    • Free tier: 60 RPM (GPT-3.5)
    • Tier 1: 500 RPM ($5+ spent)
    • Implement retries to handle limits
  3. Optimization:

    • Use GPT-3.5 when it's enough
    • Minimize context/history
    • Cache common responses
    • Limit output with max_tokens
  4. Monitoring:

    • OpenAI Dashboard (daily usage)
    • Custom logs (detailed analysis)
    • Alerts (soft/hard limits)

🔗 Additional resources

  1. OpenAI Pricing - Updated
  2. Rate Limits - Official docs
  3. Tiktoken - Token counter
  4. Usage Dashboard - Monitoring

➡️ Next step

Next capsule: 07-error-handling-and-retries.md

You'll learn to handle production errors:

  • Rate limit errors (429)
  • Timeouts
  • API errors (500, 503)
  • Exponential backoff
  • Retry strategies

Time: 25 minutes


Estimated time: 25 minutes
Next: 07-error-handling-and-retries.md