Complete Guide: Using Gemini 3.6 Flash via Unorouter API
A comprehensive tutorial with runnable Python code for integrating Google's free Gemini 3.6 Flash model through the Unorouter API.
Introduction
Gemini 3.6 Flash is Google's latest fast and efficient AI model, available for free through Unorouter's unified API gateway. This tutorial provides step-by-step instructions and complete Python code examples for text generation, chat completion, and streaming responses.
Prerequisites
- Python 3.8 or higher
-
requestslibrary:pip install requests - Unorouter account (free at unorouter.com)
- API key from your Unorouter dashboard
Quick Start: Basic Text Generation
import requests
import os
from typing import Optional
# Configuration
UNOROUTER_BASE_URL = "https://api.unorouter.com/v1"
MODEL = "google/gemini-3.6-flash:free"
class GeminiClient:
"""Client for interacting with Gemini 3.6 Flash via Unorouter."""
def __init__(self, api_key: Optional[str] = None):
self.api_key = api_key or os.getenv("UNOROUTER_API_KEY")
if not self.api_key:
raise ValueError("API key required. Set UNOROUTER_API_KEY environment variable.")
self.headers = {
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json"
}
self.url = f"{UNOROUTER_BASE_URL}/chat/completions"
def generate(self,
prompt: str,
temperature: float = 0.7,
max_tokens: int = 1000,
system_prompt: Optional[str] = None) -> str:
"""Generate text completion."""
messages = []
if system_prompt:
messages.append({"role": "system", "content": system_prompt})
messages.append({"role": "user", "content": prompt})
data = {
"model": MODEL,
"messages": messages,
"temperature": temperature,
"max_tokens": max_tokens
}
response = requests.post(self.url, headers=self.headers, json=data, timeout=30)
response.raise_for_status()
return response.json()["choices"][0]["message"]["content"]
# Usage Example
if __name__ == "__main__":
client = GeminiClient()
# Simple text generation
prompt = "Write a Python function to calculate fibonacci numbers"
result = client.generate(prompt)
print(f"Prompt: {prompt}")
print(f"Response:\n{result}")
Advanced Features
Streaming Responses for Real-Time Output
import json
def stream_generate(self, prompt: str, system_prompt: Optional[str] = None):
"""Stream text generation for real-time display."""
messages = []
if system_prompt:
messages.append({"role": "system", "content": system_prompt})
messages.append({"role": "user", "content": prompt})
data = {
"model": MODEL,
"messages": messages,
"temperature": 0.7,
"max_tokens": 1000,
"stream": True
}
response = requests.post(
self.url,
headers=self.headers,
json=data,
timeout=30,
stream=True
)
response.raise_for_status()
for line in response.iter_lines():
if line:
line = line.decode('utf-8')
if line.startswith('data: '):
line = line[6:]
if line.strip() == '[DONE]':
break
try:
chunk = json.loads(line)
content = chunk["choices"][0]["delta"].get("content", "")
if content:
print(content, end="", flush=True)
except:
pass
print()
# Add to class
GeminiClient.stream = stream_generate
# Usage
client.stream("Write a short story about a robot learning to paint")
Multi-Turn Conversations
class ChatSession:
"""Maintains conversation context across multiple turns."""
def __init__(self, client: GeminiClient, system_prompt: Optional[str] = None):
self.client = client
self.messages = []
if system_prompt:
self.messages.append({"role": "system", "content": system_prompt})
def send(self, user_message: str) -> str:
self.messages.append({"role": "user", "content": user_message})
data = {
"model": MODEL,
"messages": self.messages,
"temperature": 0.7,
"max_tokens": 1000
}
response = requests.post(self.client.url, headers=self.client.headers, json=data, timeout=30)
response.raise_for_status()
reply = response.json()["choices"][0]["message"]["content"]
self.messages.append({"role": "assistant", "content": reply})
return reply
def get_history(self) -> list:
return self.messages
# Usage
client = GeminiClient()
chat = ChatSession(client, "You are a helpful Python tutor.")
print(chat.send("How do I read a JSON file in Python?"))
print(chat.send("Can you show me with error handling?"))
print(chat.send("What about writing JSON files?"))
Error Handling & Rate Limiting
import time
from functools import wraps
def retry_on_rate_limit(max_retries: int = 3, base_delay: float = 2.0):
"""Decorator for handling rate limits with exponential backoff."""
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
for attempt in range(max_retries):
try:
return func(*args, **kwargs)
except requests.exceptions.HTTPError as e:
if e.response.status_code in (429, 503):
delay = base_delay ** attempt
print(f"Rate limited. Waiting {delay}s... (attempt {attempt + 1}/{max_retries})")
time.sleep(delay)
else:
raise
raise Exception(f"Max retries ({max_retries}) exceeded")
return wrapper
return decorator
# Apply to generate method
@retry_on_rate_limit(max_retries=3)
def robust_generate(self, prompt: str, **kwargs) -> str:
return self.generate(prompt, **kwargs)
GeminiClient.robust_generate = robust_generate
Complete Working Example
Save this as gemini_demo.py and run it:
#!/usr/bin/env python3
"""
Complete Gemini 3.6 Flash Demo via Unorouter
Run: python gemini_demo.py
"""
import os
import requests
import json
import time
from typing import Optional
# ============== CONFIGURATION ==============
UNOROUTER_BASE_URL = "https://api.unorouter.com/v1"
MODEL = "google/gemini-3.6-flash:free"
API_KEY = os.getenv("UNOROUTER_API_KEY")
if not API_KEY:
print("ERROR: Please set UNOROUTER_API_KEY environment variable")
print("Get your free key at: https://unorouter.com")
exit(1)
# ============== CLIENT CLASS ==============
class GeminiClient:
def __init__(self, api_key: str):
self.api_key = api_key
self.headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
}
self.url = f"{UNOROUTER_BASE_URL}/chat/completions"
def generate(self, prompt: str, temperature: float = 0.7, max_tokens: int = 1000) -> str:
data = {
"model": MODEL,
"messages": [{"role": "user", "content": prompt}],
"temperature": temperature,
"max_tokens": max_tokens
}
response = requests.post(self.url, headers=self.headers, json=data, timeout=30)
response.raise_for_status()
return response.json()["choices"][0]["message"]["content"]
def stream(self, prompt: str):
data = {
"model": MODEL,
"messages": [{"role": "user", "content": prompt}],
"temperature": 0.7,
"max_tokens": 1000,
"stream": True
}
response = requests.post(self.url, headers=self.headers, json=data, timeout=30, stream=True)
response.raise_for_status()
for line in response.iter_lines():
if line:
line = line.decode('utf-8')
if line.startswith('data: '):
line = line[6:]
if line.strip() == '[DONE]':
break
try:
chunk = json.loads(line)
content = chunk["choices"][0]["delta"].get("content", "")
if content:
print(content, end="", flush=True)
except:
pass
print()
# ============== DEMO FUNCTIONS ==============
def demo_basic_generation(client: GeminiClient):
print("=" * 60)
print("DEMO 1: Basic Text Generation")
print("=" * 60)
prompt = "Explain decorators in Python in 3 sentences"
print(f"Prompt: {prompt}\n")
result = client.generate(prompt)
print(f"Response:\n{result}\n")
def demo_streaming(client: GeminiClient):
print("=" * 60)
print("DEMO 2: Streaming Response")
print("=" * 60)
prompt = "Write a haiku about coding"
print(f"Prompt: {prompt}\nResponse: ")
client.stream(prompt)
print()
def demo_code_generation(client: GeminiClient):
print("=" * 60)
print("DEMO 3: Code Generation")
print("=" * 60)
prompt = """Write a complete Python class for a simple REST API client with:
- GET, POST, PUT, DELETE methods
- Automatic JSON handling
- Error handling with retries
- Type hints"""
print(f"Prompt: {prompt}\n")
result = client.generate(prompt, temperature=0.5, max_tokens=1500)
print(f"Response:\n{result}\n")
def demo_creative_writing(client: GeminiClient):
print("=" * 60)
print("DEMO 4: Creative Writing")
print("=" * 60)
prompt = "Write a micro-fiction story (100 words) about an AI that discovers it can dream"
print(f"Prompt: {prompt}\n")
result = client.generate(prompt, temperature=0.9, max_tokens=500)
print(f"Response:\n{result}\n")
# ============== MAIN ==============
if __name__ == "__main__":
print("Gemini 3.6 Flash via Unorouter - Complete Demo")
print("=" * 60)
client = GeminiClient(API_KEY)
demo_basic_generation(client)
demo_streaming(client)
demo_code_generation(client)
demo_creative_writing(client)
print("=" * 60)
print("All demos completed successfully!")
print("=" * 60)
Best Practices
- Secure API Keys: Use environment variables, never hardcode
- Handle Rate Limits: Implement exponential backoff (shown above)
- Set Timeouts: Prevent hanging requests (30s recommended)
-
Use Appropriate Temperatures:
- 0.3-0.5 for code/factual tasks
- 0.7-0.9 for creative writing
- Monitor Token Usage: Free tier has limits
- Cache Responses: During development to save API calls
Troubleshooting
| Error | Solution |
|---|---|
| 401 Unauthorized | Check API key is correct and set in environment |
| 429 Too Many Requests | Implement backoff, reduce request frequency |
| 503 Service Unavailable | Wait and retry, service may be temporarily overloaded |
| Timeout | Increase timeout, check network connectivity |
Conclusion
The Unorouter API with Gemini 3.6 Flash provides a powerful, free way to integrate AI text generation into your Python applications. With the examples above, you can build chatbots, content generators, code assistants, and more - all without any API costs.
Next Steps:
- Experiment with different prompts and temperatures
- Build a CLI tool or web app using this client
- Explore other free models available on Unorouter
- Add conversation memory for chat applications
Published as part of the AI Tutorials series on Dev.to
Top comments (0)