Documentation
Everything you need to point your code at 400+ models. If you already use the OpenAI SDK, change base_url and nothing else changes.
curl https://api.uttapen.ir/v1/chat/completions \
-H "Authorization: Bearer sk-up-…" \
-H "Content-Type: application/json" \
-d '{
"model": "openai/gpt-5",
"messages": [{"role": "user", "content": "Introduce yourself."}],
"stream": true
}'from openai import OpenAI
client = OpenAI(
base_url="https://api.uttapen.ir/v1",
api_key="sk-up-…",
)
stream = client.chat.completions.create(
model="openai/gpt-5",
messages=[{"role": "user", "content": "Introduce yourself."}],
stream=True,
)
for chunk in stream:
print(chunk.choices[0].delta.content or "", end="", flush=True)import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.uttapen.ir/v1",
apiKey: "sk-up-…",
});
const stream = await client.chat.completions.create({
model: "openai/gpt-5",
messages: [{ role: "user", content: "Introduce yourself." }],
stream: true,
});
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}<?php
// composer require openai-php/client guzzlehttp/guzzle
$client = OpenAI::factory()
->withBaseUri('https://api.uttapen.ir/v1')
->withApiKey('sk-up-…')
->make();
$result = $client->chat()->create([
'model' => 'openai/gpt-5',
'messages' => [['role' => 'user', 'content' => 'Introduce yourself.']],
]);
echo $result->choices[0]->message->content;package main
import (
"context"
"fmt"
"github.com/openai/openai-go"
"github.com/openai/openai-go/option"
)
func main() {
client := openai.NewClient(
option.WithBaseURL("https://api.uttapen.ir/v1"),
option.WithAPIKey("sk-up-…"),
)
resp, err := client.Chat.Completions.New(context.Background(), openai.ChatCompletionNewParams{
Model: "openai/gpt-5",
Messages: []openai.ChatCompletionMessageParamUnion{openai.UserMessage("Introduce yourself.")},
})
if err != nil {
panic(err)
}
fmt.Println(resp.Choices[0].Message.Content)
}Prefer to watch? Video guides: first request, streaming, images and speech, LangChain →
Getting started
- Quickstart — your first API call in 5 minutesSign up with a phone number, top up your toman wallet, create an sk-up key, and make your first model call with the official OpenAI SDK.
- API keys and authenticationHow sk-up keys work — the Authorization and X-API-Key headers, per-key spending limits, model allow-lists, rate limits, expiry and instant revocation.
- Migrate from OpenAI or Azure OpenAIMove existing code to uttapen by changing base_url and key — model id format, supported endpoints, fields that pass through, and common mistakes.
Capabilities
- Streaming responses with SSEStream output token by token with stream=true: SSE event format, the uttapen.meta cost event, client disconnects, and proxying from Next.js or Laravel.
- Tool calling (function calling)Declare tools with the OpenAI schema, run the full tool-call loop in Python, steer the model with tool_choice, and accumulate tool_calls while streaming.
- Vision: image and PDF inputSend images by URL or data URI and PDFs as a file part in chat/completions: picking a model, the 20 MB body limit, and how image usage is charged.
- Structured output: JSON and JSON SchemaGet valid JSON out of any model with response_format json_object or json_schema, in Python and Node, plus the Persian-text pitfalls that break parsers.
- Reasoning models: effort, tokens, costDrive o3, DeepSeek R1 and friends with reasoning_effort or the reasoning block, read reasoning tokens in response and stream, and budget the hold.
Media
- Media API: images, video, speech, musicThe uttapen media API: image generation, async video, text to speech and music, automatic model picking, signed file links and 30-day retention.
- Image generation API (images/generations)Generate and edit images with POST /v1/images/generations and the OpenAI SDK: automatic model picking, reference images, aspect ratio, URL or base64.
- Video generation API (videos)Async video with POST /v1/videos, polling GET /v1/videos/{id} and the content download: duration, resolution, sound, first frame and per-second pricing.
- Text to speech API (audio/speech)Narrate Persian and English text with POST /v1/audio/speech and the OpenAI SDK: voices, mp3 or wav, speed, Persian-capable auto model, per-character price.
- Music generation API (audio/music)Make music and short songs with POST /v1/audio/music: style and mood, an inspiration image, automatic model picking, the file link and per-track price.
API reference
- Error codes — 400 to 504 and what to doEvery uttapen API error from 400 to 504 — the JSON shape, what each code means, whether it costs you anything, and how the OpenAI SDKs raise it.
- Rate limits — per-minute, streams and quotasPer-key requests per minute, the X-RateLimit and Retry-After headers, the concurrent stream cap, free-model daily quotas and a correct backoff example.
- LLM API pricing in toman: pay only for real token usagePer-million-token prices in toman, charging on each request's real usage, free failed requests, the hold-and-settle cycle, and the usage report API.
- API privacy: what uttapen stores and what it never logsThe API path never stores prompts or responses. Exactly which metadata is kept, the dashboard chat exception, and how traffic reaches the provider.
SDKs and tools
- Python SDKOfficial openai Python package with uttapen: install, client, chat, streaming with uttapen.meta, tool calling, embeddings, async and error handling.
- Node.js SDKOfficial openai package for Node.js and TypeScript with uttapen: client, cost headers, streaming, AbortController, tool calling, embeddings, errors.
- PHP SDK (Laravel and openai-php)openai-php/client and Guzzle with uttapen in PHP and Laravel: client, chat, cost headers, streaming, tool calling, embeddings and error handling.
- Go SDKOfficial openai-go package with uttapen: client, chat, streaming with the accumulator and uttapen.meta, tool calling, embeddings, openai.Error handling.
- curl and raw HTTP: use the uttapen API without an SDKCall every uttapen endpoint with curl: chat, streaming with -N, cost and rate-limit headers, uttapen.meta, embeddings, models, usage and a deploy check.
- Integrations: coding agents, SDKs and chat appsEvery OpenAI-compatible tool needs three values. Coding agents with their own guides, LangChain, LlamaIndex, the Vercel AI SDK, and chat apps.
Coding tools
- opencode setup: custom provider, model ids and output limitsConfigure opencode for uttapen in opencode.json: an OpenAI-compatible provider, exact model ids, limit.output to keep holds small, a cheap title model.
- Cline in VS Code: OpenAI Compatible provider setupPoint the Cline extension at uttapen: pick OpenAI Compatible, set base URL, key and model id, cap Max Output Tokens to keep holds small, and fix errors.
- Kilo Code: custom provider and kilo.jsonc limitsAdd uttapen to Kilo Code as an OpenAI Compatible provider, set limit.context and limit.output in kilo.jsonc, and pick a cheap Small Model for titles.
- Roo Code with uttapen (discontinued extension)Roo Code was discontinued in May 2026. If you still run version 3.54, here is the OpenAI Compatible setup that keeps it working with uttapen.
- Continue: config.yaml setup and turning off the Responses APISet up Continue for uttapen in config.yaml: provider openai with apiBase, useResponsesApi false, explicit maxTokens, and chat and autocomplete roles.
- Cursor: base URL override, and what it does not coverUse your uttapen key in Cursor by overriding the OpenAI base URL: what works, why Tab and subagents do not, and when Agent mode returns an error.
- Zed: openai_compatible provider in settings.jsonAdd uttapen to Zed with an openai_compatible block in settings.json: model list, max_output_tokens to keep holds small, cheap models for commit messages.
- VS Code chat: Custom Endpoint with your own keyAdd uttapen to VS Code chat through the Custom Endpoint provider: the chatLanguageModels.json entry, token limits, and a cheap utility model.
- Aider: the openai/ prefix and model settings filesRun Aider against uttapen: OPENAI_API_BASE and OPENAI_API_KEY, the openai/ model prefix, an output ceiling in the settings file, and a cheap weak model.
- Crush: an openai-compat provider in crushrcAdd uttapen to Crush with provider add --type openai-compat, register models with context-window and default-max-tokens, and set a cheap small model.
- Goose: environment variables and a custom providerRun Goose on uttapen: OPENAI_HOST and GOOSE_MODEL, GOOSE_MAX_TOKENS to keep the hold small, and the model families that do not work in Goose today.
- Qwen Code: modelProviders in settings.jsonConfigure Qwen Code for uttapen: a modelProviders block in settings.json with baseUrl and envKey, a max_tokens ceiling, or the quick env-var route.
- Codex CLI and uttapen: why it does not work todaySince February 2026 Codex CLI speaks only the Responses API, which uttapen does not serve. Here is the full story and the terminal agents that do work.
- Claude Code and uttapen: why there is no direct routeClaude Code speaks only the Anthropic messages API, which uttapen does not serve. What that means, and the tools that do run Claude models.