Skip to content

Using the API

This guide shows how to integrate Routstr with your applications using various programming languages and tools.

API Compatibility

Routstr maintains full compatibility with the OpenAI API, meaning:

  • Existing OpenAI client libraries work without modification
  • Only the base URL and API key need to change
  • All parameters and responses match OpenAI's format

Basic Setup

Python

Using the official OpenAI Python library:

from openai import OpenAI

# Initialize client with Routstr endpoint
client = OpenAI(
    api_key="sk-...",
    base_url="https://api.routstr.com/v1"
)

# Use exactly like OpenAI
response = client.chat.completions.create(
    model="gpt-3.5-turbo",
    messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Hello!"}
    ]
)

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

JavaScript/TypeScript

Using the official OpenAI Node.js library:

import OpenAI from 'openai';

// Initialize client
const openai = new OpenAI({
    apiKey: 'sk-...',
    baseURL: 'https://api.routstr.com/v1'
});

// Make a request
async function main() {
    const completion = await openai.chat.completions.create({
        model: 'gpt-3.5-turbo',
        messages: [
            { role: 'system', content: 'You are a helpful assistant.' },
            { role: 'user', content: 'Hello!' }
        ]
    });

    console.log(completion.choices[0].message.content);
}

main();

cURL

Direct HTTP requests:

curl https://api.routstr.com/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sk-..." \
  -d '{
    "model": "gpt-3.5-turbo",
    "messages": [
      {"role": "user", "content": "Hello!"}
    ]
  }'

Common Use Cases

Chat Completions

Standard chat with conversation history:

messages = []

def chat(user_input):
    # Add user message
    messages.append({"role": "user", "content": user_input})

    # Get AI response
    response = client.chat.completions.create(
        model="gpt-3.5-turbo",
        messages=messages,
        temperature=0.7,
        max_tokens=150
    )

    # Add AI response to history
    ai_message = response.choices[0].message
    messages.append({"role": "assistant", "content": ai_message.content})

    return ai_message.content

# Usage
print(chat("What's the weather like?"))
print(chat("How should I dress?"))  # Maintains context

Streaming Responses

For real-time output:

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

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

Function Calling

Using OpenAI's function calling feature:

tools = [{
    "type": "function",
    "function": {
        "name": "get_weather",
        "description": "Get current weather",
        "parameters": {
            "type": "object",
            "properties": {
                "location": {"type": "string"},
                "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
            },
            "required": ["location"]
        }
    }
}]

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

# Check if function was called
if response.choices[0].message.tool_calls:
    tool_call = response.choices[0].message.tool_calls[0]
    print(f"Function: {tool_call.function.name}")
    print(f"Arguments: {tool_call.function.arguments}")

Embeddings

Generate text embeddings:

response = client.embeddings.create(
    model="text-embedding-3-small",
    input="The quick brown fox jumps over the lazy dog"
)

embedding = response.data[0].embedding
print(f"Embedding dimension: {len(embedding)}")

Image Generation

Create images with DALL-E:

response = client.images.generate(
    model="dall-e-3",
    prompt="A futuristic city with flying cars",
    size="1024x1024",
    quality="standard",
    n=1
)

image_url = response.data[0].url
print(f"Image URL: {image_url}")

Audio Transcription

Convert speech to text:

with open("audio.mp3", "rb") as audio_file:
    response = client.audio.transcriptions.create(
        model="whisper-1",
        file=audio_file,
        response_format="text"
    )

print(response.text)

Error Handling

Balance Errors

Handle insufficient balance gracefully:

try:
    response = client.chat.completions.create(
        model="gpt-4",
        messages=[{"role": "user", "content": "Hello"}]
    )
except Exception as e:
    if "insufficient_balance" in str(e):
        print("Low balance! Please top up your API key.")
        # Implement top-up logic
    else:
        raise

Rate Limiting

Implement exponential backoff:

import time
from typing import Optional

def make_request_with_retry(
    func, 
    max_retries: int = 3,
    initial_delay: float = 1.0
) -> Optional[any]:
    for attempt in range(max_retries):
        try:
            return func()
        except Exception as e:
            if "rate_limit" in str(e) and attempt < max_retries - 1:
                delay = initial_delay * (2 ** attempt)
                print(f"Rate limited. Waiting {delay}s...")
                time.sleep(delay)
            else:
                raise
    return None

Connection Errors

Handle network issues:

import httpx

# Configure timeout and retries
client = OpenAI(
    api_key="sk-...",
    base_url="https://your-node.com/v1",
    timeout=httpx.Timeout(60.0, connect=5.0),
    max_retries=2
)

Advanced Features

Using Tor

Route requests through Tor for privacy:

import httpx

# Configure Tor proxy
proxies = {
    "http://": "socks5://127.0.0.1:9050",
    "https://": "socks5://127.0.0.1:9050"
}

http_client = httpx.Client(proxies=proxies)

client = OpenAI(
    api_key="sk-...",
    base_url="http://your-onion-address.onion/v1",
    http_client=http_client
)

Custom Headers

Add custom headers if needed:

import httpx

class CustomClient(httpx.Client):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.headers["X-Custom-Header"] = "value"

client = OpenAI(
    api_key="sk-...",
    base_url="https://your-node.com/v1",
    http_client=CustomClient()
)

Azure OpenAI compatibility

To use Azure OpenAI through Routstr with minimal changes:

  • Set UPSTREAM_BASE_URL to your Azure deployments URL, for example: https://<resource>.openai.azure.com/openai/deployments/<deployment>
  • Set CHAT_COMPLETIONS_API_VERSION=2024-05-01-preview

When this env var is set, Routstr automatically appends api-version=2024-05-01-preview to all upstream /chat/completions requests.

Async Operations

For high-performance applications:

import asyncio
from openai import AsyncOpenAI

async_client = AsyncOpenAI(
    api_key="sk-...",
    base_url="https://your-node.com/v1"
)

async def process_messages(messages):
    tasks = []
    for msg in messages:
        task = async_client.chat.completions.create(
            model="gpt-3.5-turbo",
            messages=[{"role": "user", "content": msg}]
        )
        tasks.append(task)

    responses = await asyncio.gather(*tasks)
    return [r.choices[0].message.content for r in responses]

# Run async
messages = ["Hello", "How are you?", "What's 2+2?"]
results = asyncio.run(process_messages(messages))

Best Practices

1. Environment Variables

Never hardcode API keys:

import os
from openai import OpenAI

client = OpenAI(
    api_key=os.getenv("ROUTSTR_API_KEY"),
    base_url=os.getenv("ROUTSTR_BASE_URL", "https://api.routstr.com/v1")
)

2. Error Logging

Implement comprehensive logging:

import logging

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

try:
    response = client.chat.completions.create(...)
    logger.info(f"Request successful. Tokens used: {response.usage.total_tokens}")
except Exception as e:
    logger.error(f"API request failed: {e}")
    raise

3. Cost Tracking

Monitor your usage:

class UsageTracker:
    def __init__(self):
        self.total_tokens = 0
        self.total_requests = 0

    def track(self, response):
        self.total_tokens += response.usage.total_tokens
        self.total_requests += 1

        # Estimate cost (example rates)
        cost_per_1k = 0.002  # $0.002 per 1K tokens
        estimated_cost = (self.total_tokens / 1000) * cost_per_1k

        logger.info(f"Total usage: {self.total_tokens} tokens, "
                   f"${estimated_cost:.4f} (~{estimated_cost * 50000:.0f} sats)")

tracker = UsageTracker()
response = client.chat.completions.create(...)
tracker.track(response)

4. Caching Responses

Reduce costs with intelligent caching:

import hashlib
import json
from functools import lru_cache

@lru_cache(maxsize=100)
def cached_completion(prompt: str, model: str = "gpt-3.5-turbo"):
    response = client.chat.completions.create(
        model=model,
        messages=[{"role": "user", "content": prompt}],
        temperature=0  # Deterministic for caching
    )
    return response.choices[0].message.content

# Repeated calls with same prompt use cache
result1 = cached_completion("What is 2+2?")
result2 = cached_completion("What is 2+2?")  # From cache, no API call

Testing

Mock Responses

For development without spending sats:

class MockOpenAI:
    class Completions:
        def create(self, **kwargs):
            return type('Response', (), {
                'choices': [type('Choice', (), {
                    'message': type('Message', (), {
                        'content': 'Mock response'
                    })()
                })],
                'usage': type('Usage', (), {
                    'total_tokens': 10
                })()
            })()

    def __init__(self):
        self.chat = type('Chat', (), {
            'completions': self.Completions()
        })()

# Use mock in tests
if os.getenv('TESTING'):
    client = MockOpenAI()
else:
    client = OpenAI(...)

Integration Tests

Test your Routstr integration:

def test_routstr_connection():
    try:
        # Test models endpoint
        models = client.models.list()
        assert len(models.data) > 0

        # Test simple completion
        response = client.chat.completions.create(
            model="gpt-3.5-turbo",
            messages=[{"role": "user", "content": "test"}],
            max_tokens=5
        )
        assert response.choices[0].message.content

        print("✅ Routstr integration working!")
        return True
    except Exception as e:
        print(f"❌ Integration test failed: {e}")
        return False

Troubleshooting

Common Issues

SSL Certificate Errors

# For development only - not for production!
import ssl
import httpx

client = OpenAI(
    api_key="sk-...",
    base_url="https://localhost:8000/v1",
    http_client=httpx.Client(verify=False)
)

Timeout Issues

# Increase timeout for slow connections
client = OpenAI(
    api_key="sk-...",
    base_url="https://your-node.com/v1",
    timeout=httpx.Timeout(120.0)  # 2 minutes
)

Debugging Requests

import logging
import httpx

# Enable debug logging
logging.basicConfig(level=logging.DEBUG)
httpx_logger = logging.getLogger("httpx")
httpx_logger.setLevel(logging.DEBUG)

Next Steps