Skip to content

OpenAI API

The most widely used LLM API. OpenAI provides GPT-4o (text + vision), Whisper (audio), embeddings, fine-tuning, and DALL·E (images). This sheet is the practical reference for calling the API, handling responses, and building reliable applications.

Table of Contents

Installation / Setup

pip install openai                       # or: uv add openai
export OPENAI_API_KEY="YOUR_API_KEY"     # never commit real keys
from openai import OpenAI
client = OpenAI(api_key="YOUR_API_KEY")  # or reads OPENAI_API_KEY env var

Core Syntax

Chat completions (the core endpoint)

response = client.chat.completions.create(
    model="gpt-4o",                    # or gpt-4o-mini, o3, o3-mini
    messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Explain machine learning in one paragraph."},
    ],
    temperature=0.7,
    max_tokens=500,
)
print(response.choices[0].message.content)
print(response.usage)                  # PromptTokens, CompletionTokens, TotalTokens

Models available

Model Context Best for Cost
gpt-4o 128K General, multimodal, complex reasoning $$$
gpt-4o-mini 128K Fast, cheap, good for most tasks $
o3 128K Hard reasoning, math, code $$$$
o3-mini 128K Reasoning at lower cost $$
gpt-4o-audio 128K Audio input/output $$$
dall-e-3 — Image generation $$

Messages format

# system — sets behavior
{"role": "system", "content": "Answer in 3 bullet points."}

# user — the input
{"role": "user", "content": "What is pandas?"}

# assistant — previous model output (multi-turn)
{"role": "assistant", "content": "Pandas is a Python library for data analysis."}

# tool — function call result
{"role": "tool", "tool_call_id": "call_abc123", "content": '{"temp": 72}'}

Vision (image understanding)

response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{
        "role": "user",
        "content": [
            {"type": "text", "text": "What is in this image?"},
            {"type": "image_url", "image_url": {
                "url": "https://example.com/photo.jpg",
                "detail": "high"          # "low" for faster/cheaper
            }},
        ],
    }],
)

# or from a local file
import base64
with open("image.jpg", "rb") as f:
    b64 = base64.b64encode(f.read()).decode()
response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{
        "role": "user",
        "content": [
            {"type": "text", "text": "Describe this image."},
            {"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{b64}"}},
        ],
    }],
)

Streaming

stream = client.chat.completions.create(
    model="gpt-4o",
    messages=messages,
    stream=True,
)
full_response = ""
for chunk in stream:
    delta = chunk.choices[0].delta
    if delta.content:
        full_response += delta.content
        print(delta.content, end="", flush=True)

Function / tool calling

tools = [{
    "type": "function",
    "function": {
        "name": "get_stock_price",
        "description": "Get the current stock price for a ticker symbol.",
        "parameters": {
            "type": "object",
            "properties": {
                "ticker": {"type": "string", "description": "Stock ticker, e.g. AAPL"},
            },
            "required": ["ticker"],
        },
    },
}]

response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "What's the price of AAPL?"}],
    tools=tools,
    tool_choice="auto",
)

# handle the tool call
tool_call = response.choices[0].message.tool_calls[0]
print(tool_call.function.name)       # "get_stock_price"
print(tool_call.function.arguments)  # '{"ticker": "AAPL"}'

# send the result back
import json
result = json.dumps({"price": 195.50, "currency": "USD"})
messages.append(response.choices[0].message)
messages.append({"role": "tool", "tool_call_id": tool_call.id, "content": result})

JSON mode

response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "List 3 programming languages with their years."}],
    response_format={"type": "json_object"},
)
# response.choices[0].message.content is valid JSON

Embeddings

response = client.embeddings.create(
    model="text-embedding-3-small",     # 1536 dims, fast
    # model="text-embedding-3-large",   # 3072 dims, better
    input=["Hello world", "Testing embeddings"],
)
vectors = [e.embedding for e in response.data]

Fine-tuning

# upload training data
file = client.files.create(file=open("train.jsonl", "rb"), purpose="fine-tune")

# create a fine-tuning job
job = client.fine_tuning.jobs.create(
    training_file=file.id,
    model="gpt-4o-mini-2024-07-18",
    hyperparameters={"n_epochs": 3},
)
print(job.id)

# check status
status = client.fine_tuning.jobs.retrieve(job.id)
print(status.status)   # "succeeded"

Practical Examples

Example 1 — Customer support bot with function calling

from openai import OpenAI
import json

client = OpenAI(api_key="YOUR_API_KEY")

tools = [{
    "type": "function",
    "function": {
        "name": "lookup_order",
        "description": "Look up an order by order ID",
        "parameters": {
            "type": "object",
            "properties": {"order_id": {"type": "string"}},
            "required": ["order_id"],
        },
    },
}]

def handle_customer_message(user_msg):
    messages = [
        {"role": "system", "content": "You are a customer support agent. Use tools to look up orders."},
        {"role": "user", "content": user_msg},
    ]
    response = client.chat.completions.create(
        model="gpt-4o", messages=messages, tools=tools, tool_choice="auto")

    msg = response.choices[0].message
    if msg.tool_calls:
        # execute tool and return result
        args = json.loads(msg.tool_calls[0].function.arguments)
        order_data = {"status": "shipped", "tracking": "12345"}  # fake result
        messages.append(msg)
        messages.append({"role": "tool", "tool_call_id": msg.tool_calls[0].id,
                         "content": json.dumps(order_data)})
        final = client.chat.completions.create(model="gpt-4o", messages=messages)
        return final.choices[0].message.content
    return msg.content

Example 2 — Image analysis pipeline

import base64
from openai import OpenAI

client = OpenAI(api_key="YOUR_API_KEY")

def analyze_image(path, question="What do you see?"):
    with open(path, "rb") as f:
        b64 = base64.b64encode(f.read()).decode()
    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[{
            "role": "user",
            "content": [
                {"type": "text", "text": question},
                {"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{b64}"}},
            ],
        }],
        max_tokens=1000,
    )
    return response.choices[0].message.content
from openai import OpenAI
import numpy as np

client = OpenAI(api_key="YOUR_API_KEY")

def get_embeddings(texts, model="text-embedding-3-small"):
    response = client.embeddings.create(model=model, input=texts)
    return np.array([e.embedding for e in response.data])

docs = ["Python for data science", "JavaScript for web dev", "R for statistics"]
doc_vecs = get_embeddings(docs)

query = "data analysis tools"
q_vec = get_embeddings([query])[0]

sims = np.dot(doc_vecs, q_vec) / (np.linalg.norm(doc_vecs, axis=1) * np.linalg.norm(q_vec))
print(docs[np.argmax(sims)])

Common Patterns

Pattern: structured extraction with JSON mode

def extract(text, schema_description):
    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[
            {"role": "system", "content": f"Extract info as JSON. Schema: {schema_description}"},
            {"role": "user", "content": text},
        ],
        response_format={"type": "json_object"},
        temperature=0.0,
    )
    return json.loads(response.choices[0].message.content)

Pattern: retry on rate limits

import time

def safe_call(func, max_retries=3):
    for i in range(max_retries):
        try:
            return func()
        except openai.RateLimitError:
            time.sleep(2 ** i * 5)
    raise Exception("Rate limit exceeded after retries")

Pattern: multi-model routing

def route_task(task_type, text):
    if task_type == "extraction":
        return client.chat.completions.create(model="gpt-4o-mini", messages=messages, temperature=0)
    elif task_type == "reasoning":
        return client.chat.completions.create(model="o3", messages=messages)
    elif task_type == "creative":
        return client.chat.completions.create(model="gpt-4o", messages=messages, temperature=0.9)

Best Practices

  • Always set response_format={"type": "json_object"} for structured output — don't just ask in the prompt.
  • Use gpt-4o-mini for classification, extraction, and simple tasks — much cheaper and faster.
  • Use gpt-4o or o3 for complex reasoning, multi-step analysis, and vision tasks.
  • System messages are cheap — use them to constrain output format and behavior.
  • Streaming is essential for UX — always stream=True for user-facing applications.
  • Cache API responses when possible — same input + temperature 0 = same output.
  • Always implement retry with backoff for rate limits.
  • Use tool_choice="required" to force function calling when you need it.
  • Keep function definitions clear — the model chooses based on descriptions.

Common Mistakes

Mistake Fix
Using gpt-4o for every task Use gpt-4o-mini for simple tasks to save cost
Not checking response.usage Monitor token usage to control costs
Hard-coding API keys Use environment variables (OPENAI_API_KEY)
Not streaming for user-facing apps Add stream=True and iterate on chunks
Ignoring rate limits Check x-ratelimit-* headers; implement backoff
Sending images without resizing Resize large images before base64 encoding
Not handling finish_length truncation Increase max_tokens or continue generation

Troubleshooting

Symptom Cause / Fix
AuthenticationError Invalid API key — check OPENAI_API_KEY
RateLimitError Too many requests — implement backoff
ContextLengthExceeded Input too long — truncate or use longer-context model
Model returns truncated output Hit max_tokens — increase it
JSON parse error on response Use response_format={"type": "json_object"}
Model ignores function calling Ensure tools parameter is passed correctly
Slow first response Cold start — first API call is slower
High costs Switch to gpt-4o-mini for simple tasks; cache results

Official Documentation

Last Updated

2026-09-06 — Initial version.