NanoGPT API Tutorial: Python Guide with Code Examples

if you can use OpenAI's Python SDK, you can use NanoGPT. the API is identical. here's everything you need to know, with working code.

TL;DR: change the base URL to https://api.nano-gpt.com/v1, use your NanoGPT API key, done. everything else is standard OpenAI SDK usage.

👉 Get NanoGPT with 5% discount — you'll need an API key for this tutorial.


Setup

Install the OpenAI SDK

pip install openai

that's the only dependency. NanoGPT uses the OpenAI API format, so the official SDK works directly.

Basic Configuration

import openai

client = openai.OpenAI(
    base_url="https://api.nano-gpt.com/v1",
    api_key="your-nanogpt-api-key"
)

important: never hardcode your API key in source code. use environment variables:

import os
import openai

client = openai.OpenAI(
    base_url="https://api.nano-gpt.com/v1",
    api_key=os.environ.get("NANOGPT_API_KEY")
)

set the environment variable:

export NANOGPT_API_KEY="your-key-here"

see our API key setup guide for getting your key.


Basic Usage

Simple Chat Completion

response = client.chat.completions.create(
    model="gpt-4o",
    messages=[
        {"role": "user", "content": "Explain Python list comprehensions in 2 sentences."}
    ]
)

print(response.choices[0].message.content)

With System Prompt

response = client.chat.completions.create(
    model="claude-3-5-sonnet",
    messages=[
        {"role": "system", "content": "You are a Python expert. Be concise."},
        {"role": "user", "content": "What's the difference between a list and a tuple?"}
    ]
)

print(response.choices[0].message.content)

Multi-Turn Conversation

messages = [
    {"role": "system", "content": "You are a helpful coding assistant."},
    {"role": "user", "content": "Write a function to reverse a string."},
]

# first response
response = client.chat.completions.create(
    model="gpt-4o",
    messages=messages
)
assistant_msg = response.choices[0].message.content
print(assistant_msg)

# follow-up
messages.append({"role": "assistant", "content": assistant_msg})
messages.append({"role": "user", "content": "Now make it handle None values."})

response = client.chat.completions.create(
    model="gpt-4o",
    messages=messages
)
print(response.choices[0].message.content)

Streaming

streaming gives you token-by-token output. essential for chat applications.

Basic Streaming

stream = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Write a short story about a robot."}],
    stream=True
)

for chunk in stream:
    content = chunk.choices[0].delta.content
    if content:
        print(content, end="", flush=True)

print()  # newline after streaming

Streaming with Collection

def stream_response(client, model, messages):
    """Stream response and return full text."""
    stream = client.chat.completions.create(
        model=model,
        messages=messages,
        stream=True
    )
    
    full_response = ""
    for chunk in stream:
        content = chunk.choices[0].delta.content
        if content:
            full_response += content
            print(content, end="", flush=True)
    
    print()
    return full_response

# usage
response_text = stream_response(client, "gpt-4o", [
    {"role": "user", "content": "Explain async/await in Python."}
])

Advanced Features

Function Calling (Tools)

import json

tools = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "Get current weather for a city",
            "parameters": {
                "type": "object",
                "properties": {
                    "city": {
                        "type": "string",
                        "description": "City name"
                    }
                },
                "required": ["city"]
            }
        }
    }
]

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

# check if model wants to call a function
if response.choices[0].message.tool_calls:
    tool_call = response.choices[0].message.tool_calls[0]
    function_name = tool_call.function.name
    arguments = json.loads(tool_call.function.arguments)
    
    print(f"Model wants to call: {function_name}")
    print(f"Arguments: {arguments}")
    
    # simulate function result
    weather_result = {"temp": "22°C", "condition": "sunny"}
    
    # send result back to model
    messages = [
        {"role": "user", "content": "What's the weather in Tokyo?"},
        response.choices[0].message,
        {
            "role": "tool",
            "tool_call_id": tool_call.id,
            "content": json.dumps(weather_result)
        }
    ]
    
    final_response = client.chat.completions.create(
        model="gpt-4o",
        messages=messages
    )
    print(final_response.choices[0].message.content)

Controlling Output

control how the model responds:

response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Write a haiku about Python."}],
    max_tokens=100,        # limit response length (saves money)
    temperature=0.9,       # higher = more creative (0-2)
    top_p=0.95,            # nucleus sampling
    frequency_penalty=0.1, # reduce repetition
    presence_penalty=0.1   # encourage new topics
)

print(response.choices[0].message.content)

tip: always set max_tokens for routine tasks. without it, the model might generate 4000 tokens when you only needed 200. that's wasted money.

Model Switching

def ask_any_model(model, question):
    """Ask any NanoGPT model a question."""
    response = client.chat.completions.create(
        model=model,
        messages=[{"role": "user", "content": question}]
    )
    return response.choices[0].message.content

# same question, different models
question = "What is recursion?"

gpt4_answer = ask_any_model("gpt-4o", question)
claude_answer = ask_any_model("claude-3-5-sonnet", question)
deepseek_answer = ask_any_model("deepseek-v3", question)

print("GPT-4o:", gpt4_answer)
print("Claude:", claude_answer)
print("DeepSeek:", deepseek_answer)

Error Handling

Common Errors and Fixes

from openai import (
    APIError,
    RateLimitError,
    AuthenticationError,
    APITimeoutError
)

def safe_api_call(client, model, messages, max_retries=3):
    """API call with retry logic."""
    for attempt in range(max_retries):
        try:
            response = client.chat.completions.create(
                model=model,
                messages=messages,
                timeout=30  # 30 second timeout
            )
            return response.choices[0].message.content
            
        except AuthenticationError:
            print("Invalid API key. Check your NANOGPT_API_KEY.")
            return None
            
        except RateLimitError:
            wait_time = 2 ** attempt
            print(f"Rate limited. Waiting {wait_time}s...")
            time.sleep(wait_time)
            
        except APITimeoutError:
            print(f"Timeout on attempt {attempt + 1}/{max_retries}")
            if attempt == max_retries - 1:
                return None
                
        except APIError as e:
            print(f"API error: {e}")
            if attempt == max_retries - 1:
                return None
            time.sleep(1)
    
    return None

Error Reference

common errors you'll encounter and how to fix them:

ErrorCauseFix
401 UnauthorizedInvalid API keyCheck key in dashboard
429 Rate LimitedToo many requestsAdd retry with backoff
500 Internal ErrorNanoGPT server issueRetry after delay
502/503Service unavailableWait and retry
TimeoutSlow responseIncrease timeout, try smaller model

Practical Examples

Example 1: Code Reviewer

def review_code(code, language="python"):
    """Get AI code review."""
    response = client.chat.completions.create(
        model="claude-3-5-sonnet",
        messages=[
            {"role": "system", "content": "You are a senior code reviewer. Be direct and specific."},
            {"role": "user", "content": f"Review this {language} code:\n\n```{language}\n{code}\n```"}
        ]
    )
    return response.choices[0].message.content

# usage
code_to_review = """
def add(a, b):
    return a + b
"""
print(review_code(code_to_review))

Example 2: Multi-Model Comparison

def compare_models(question, models=None):
    """Ask the same question to multiple models."""
    if models is None:
        models = ["gpt-4o", "claude-3-5-sonnet", "deepseek-v3"]
    
    results = {}
    for model in models:
        response = client.chat.completions.create(
            model=model,
            messages=[{"role": "user", "content": question}],
            max_tokens=500
        )
        results[model] = response.choices[0].message.content
    
    return results

# usage
answers = compare_models("What's the best Python web framework?")
for model, answer in answers.items():
    print(f"\n--- {model} ---")
    print(answer[:200] + "...")

Example 3: Document Summarizer

def summarize_document(text, max_length=200):
    """Summarize a long document."""
    response = client.chat.completions.create(
        model="gemini-1.5-pro",  # good for long contexts
        messages=[
            {"role": "system", "content": f"Summarize in under {max_length} words."},
            {"role": "user", "content": text}
        ]
    )
    return response.choices[0].message.content

# usage
with open("long_document.txt", "r") as f:
    document = f.read()

summary = summarize_document(document)
print(summary)

Example 5: Conversation Memory

class ChatBot:
    """Simple chatbot with conversation memory."""
    
    def __init__(self, model="gpt-4o", system_prompt="You are a helpful assistant."):
        self.client = openai.OpenAI(
            base_url="https://api.nano-gpt.com/v1",
            api_key=os.environ.get("NANOGPT_API_KEY")
        )
        self.model = model
        self.messages = [{"role": "system", "content": system_prompt}]
    
    def chat(self, user_message):
        self.messages.append({"role": "user", "content": user_message})
        response = self.client.chat.completions.create(
            model=self.model,
            messages=self.messages
        )
        assistant_message = response.choices[0].message.content
        self.messages.append({"role": "assistant", "content": assistant_message})
        return assistant_message

# usage
bot = ChatBot(model="claude-3-5-sonnet", system_prompt="You are a Python tutor.")
print(bot.chat("What is a decorator?"))
print(bot.chat("Show me an example."))  # remembers the previous context

Example 4: Batch Processing

import time

def batch_process(tasks, model="gpt-4o-mini", delay=0.5):
    """Process multiple tasks with rate limiting."""
    results = []
    for i, task in enumerate(tasks):
        response = client.chat.completions.create(
            model=model,
            messages=[{"role": "user", "content": task}]
        )
        results.append(response.choices[0].message.content)
        print(f"Processed {i+1}/{len(tasks)}")
        time.sleep(delay)  # rate limit protection
    return results

# usage
tasks = [
    "Summarize: Python is a programming language...",
    "Translate to Spanish: Hello, how are you?",
    "Classify sentiment: This product is amazing!",
]

results = batch_process(tasks)

Checking Available Models

# list all available models
models = client.models.list()
for model in models.data:
    print(model.id)

see our full model list for details on each model.


API Tutorial FAQ

Do I need to install anything special?

just the OpenAI Python SDK: pip install openai. NanoGPT uses the same API format.

Can I use NanoGPT with other languages?

yes. any language with an OpenAI-compatible SDK works. JavaScript, Go, Rust, Java — all have OpenAI SDKs that work with NanoGPT.

How do I handle rate limits?

implement retry logic with exponential backoff. the example in the error handling section shows this.

Is streaming supported?

yes. use stream=True in the API call. works the same as OpenAI's streaming.

Can I use function calling?

yes. NanoGPT supports OpenAI's function calling (tools) format for models that support it (GPT-4o, Claude 3.5 Sonnet, etc.).

How do I reduce costs?

use cheaper models (GPT-4o-mini, DeepSeek V3) for simple tasks. set max_tokens to cap response length. batch related questions. see our pricing guide.


Next Steps

👉 Get started with NanoGPT


Last updated: July 2026


Disclosure: This article contains affiliate links. If you sign up through our referral link, you get a 5% discount and we earn a small commission. This doesn't affect our reviews — we pay for all services ourselves.