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:
| Error | Cause | Fix |
|---|---|---|
| 401 Unauthorized | Invalid API key | Check key in dashboard |
| 429 Rate Limited | Too many requests | Add retry with backoff |
| 500 Internal Error | NanoGPT server issue | Retry after delay |
| 502/503 | Service unavailable | Wait and retry |
| Timeout | Slow response | Increase 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 your API key set up
- explore available models
- learn about cost optimization
- connect to Open WebUI or LibreChat
Last updated: July 2026
Related Articles
- NanoGPT API Key Setup — get your key
- Best Models for Coding — model recommendations
- NanoGPT for Developers — developer workflow
- NanoGPT Pricing — cost breakdown
- All NanoGPT Models — complete list
- NanoGPT + Open WebUI — GUI setup
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.