An OpenAI API alternative from Russia: what to change in your code
Code built on the OpenAI SDK moves to an OpenAI-compatible gateway with very few edits. Which lines to change, what to check in streaming and the Responses API, and how to pay from Russia.
6 min · · development · payments
If your project already runs on the OpenAI SDK and paying for access from Russia has become a problem, you don't need to rewrite anything to find an OpenAI API alternative. Zukko accepts requests in the same format, so moving over comes down to the address, the key and model names. Below: exactly what to change, what to double-check, and how to top up your balance.
What changes and what stays
Zukko is an API gateway to Claude, GPT, Gemini, DeepSeek, Qwen and GLM models: one fetch_... key, a single balance in dollars, pay per token with no subscription. The OpenAI-compatible format lives at https://api.zukko.pro/v1:
POST /v1/chat/completions— chat;POST /v1/responses— the Responses API;GET /v1/models— the list of available models.
The official openai SDKs for Python and Node.js stay the same — you just point them at a different address. Business logic, prompts and response parsing don't change.
An OpenAI API alternative from Russia: three code changes
1. The API address
Python:
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.zukko.pro/v1",
api_key=os.environ["ZUKKO_API_KEY"],
)
response = client.chat.completions.create(
model="gpt-6.1-sol",
messages=[{"role": "user", "content": "Suggest three names for a coffee shop"}],
)
print(response.choices[0].message.content)Node.js:
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.zukko.pro/v1",
apiKey: process.env.ZUKKO_API_KEY,
});
const response = await client.chat.completions.create({
model: "gpt-6.1-sol",
messages: [{ role: "user", content: "Suggest three names for a coffee shop" }],
});
console.log(response.choices[0].message.content);If you'd rather not touch code at all, set environment variables — the SDKs read them automatically:
export OPENAI_BASE_URL=https://api.zukko.pro/v1
export OPENAI_API_KEY=fetch_your_keyThe /v1 suffix is required: the OpenAI SDK only appends chat/completions or responses to the base address.
2. The key
Create a key on the API keys page of the dashboard. The full key is shown only once — store it in a secrets manager or an environment variable. Each key can have a daily and monthly dollar limit and a list of allowed models, which makes it easy to issue a separate key per service.
3. Model names
Take model names from the Zukko catalog, not from your old code. GPT models as of October 6, 2026 ($ per 1M tokens):
| Model | Zukko input / output | Vendor price input / output | Intelligence index |
|---|---|---|---|
gpt-6-astra | 0.62 / 3.05 | 10 / 50 | 53 |
gpt-6.1-sol | 0.27 / 1.32 | 2 / 10 | 52 |
gpt-6-sol | 0.13 / 0.63 | 2 / 10 | — |
gpt-5.6-sol | 0.22 / 1.07 | 5 / 30 | — |
gpt-5.6-terra | 0.13 / 0.63 | 2.5 / 15 | 42 |
gpt-6-luna | 0.04 / 0.21 | 0.1 / 0.5 | 38 |
gpt-5.6-luna | 0.06 / 0.3 | 1 / 6 | — |
The intelligence index is the Artificial Analysis Intelligence Index shown in the Zukko catalog; a dash means the catalog has no value. If a model from your old code isn't on the list, the request will return 404 model_not_found — move model names into config and check the list on deploy. For the current list and prices, see GET https://api.zukko.pro/v1/models (no key needed for this call) or the Models page in your dashboard.
The same client can call other models too: claude-sonnet-5, deepseek-v4.1-flash, gemini-3.8-flash and the rest of the catalog. The gateway handles format conversion.
The Responses API
The /v1/responses endpoint exists, so Responses API code also moves over with an address change:
response = client.responses.create(
model="gpt-6.1-sol",
instructions="Answer briefly.",
input="What's the difference between a list and a tuple in Python?",
)
print(response.output_text)One detail to check before you switch: according to the Zukko API reference the gateway is stateless, and previous_response_id and store are ignored. If your code continues conversations via previous_response_id, send the full history in input as an array of messages. There's an agents example in the article on the OpenAI Agents SDK via /v1/responses.
Streaming: one check your code needs
In OpenAI-format streaming, the server sends a final chunk with usage stats and an empty choices array. Code that reads chunk.choices[0] unconditionally will hit an IndexError on that chunk. The correct loop:
stream = client.chat.completions.create(
model="gpt-6.1-sol",
messages=[{"role": "user", "content": "Write a short poem about autumn"}],
stream=True,
)
for chunk in stream:
if chunk.choices:
delta = chunk.choices[0].delta.content
if delta:
print(delta, end="", flush=True)
elif chunk.usage:
print(f"\n[input: {chunk.usage.prompt_tokens}, output: {chunk.usage.completion_tokens}]")A side benefit: token counts arrive with every response, so you can log usage without extra calls. More in the chat/completions reference.
What else to check before switching
- Endpoints. If you use embeddings, audio, files or fine-tuning, check the Zukko API reference before migrating: move only what's described there.
- Parameters. Run
tools,response_formatand similar through your own tests with the chosen model: support depends on the model. - Errors. 401 — invalid key, 402 — insufficient balance, 403
model_not_allowed_for_key— the model isn't on the key's allowed list, 404model_not_found— unknown model name, 413 — request too large, 429 — the key's daily or monthly limit is used up (key_daily_limit_reached/key_monthly_limit_reached) or a limit on the model provider's side (Zukko has no general rate limit), 503 — provider unavailable. A 503 with codemodel_disabledmeans the model is switched off — pick another one fromGET /v1/models. - Cache. For GPT models, cached tokens show up in
usage.prompt_tokens_details.cached_tokens; cache reads are billed at their own catalog price, and a write is not charged separately — the first request is billed in full at the input price.
What it costs: a worked example
Say a service uses 10M input and 2M output tokens a month on gpt-6.1-sol.
- Zukko: 10 × $0.27 + 2 × $1.32 = $2.70 + $2.64 = $5.34.
- Vendor's official price: 10 × $2 + 2 × $10 = $20 + $20 = $40.
This ignores caching: if you have a long repeated system prompt, part of the input will be billed at the cache read price — $0.013 per 1M tokens for gpt-6.1-sol on Zukko. Plug in your own volumes from your stats rather than our example.
Paying from Russia
The balance is in dollars, top-ups start at $1:
- SBP and Russian bank cards (Mir, Visa, Mastercard) — in rubles at the market rate at the time of payment;
- cryptocurrency (USDT and others);
- a foreign Mastercard EU card — with a fee of about 13%, amounts from $2 to $594.
There's no sign-up bonus, but subscribing to the @zukkopro Telegram channel gives you $0.50 — once per Telegram account: link Telegram in the dashboard, subscribe and press "Check".
Migration checklist
- Create a key in the dashboard, set a daily limit and allowed models.
- Change
base_urltohttps://api.zukko.pro/v1(or setOPENAI_BASE_URL). - Replace the old key with your
fetch_...key. - Check model names against
GET /v1/modelsand move them into config. - Add an
if chunk.choices:check to streaming code. - In the Responses API, send history in
input; don't rely onprevious_response_id. - Run tests for every endpoint and parameter you actually use.
- Handle 402, 403 and 503
model_disabled. - For the first week, compare spend in the dashboard's Usage section.
You can start with the quick start: create a key, top up from $1 and switch one service over.
FAQ
Do I need to change the SDK or library?
No. The official openai SDKs for Python and Node.js work as is — only the address and key change. LangChain, Codex and other tools with an OpenAI-compatible provider connect the same way: base address with /v1; details are in the integrations section of the docs.
Can I call Claude through the same client?
Yes, any catalog model can be used in OpenAI format. But note: for Claude, the prompt cache discount only applies in Anthropic format (/v1/messages); in OpenAI format all Claude input is billed at the input price. If your code uses the Anthropic SDK, see the article on moving from the Anthropic API.
Does previous_response_id work?
No, according to the Zukko API reference the gateway doesn't store response state. Send the conversation history in input yourself.
Is there a trial balance?
There's no sign-up bonus. You can get $0.50 for subscribing to the @zukkopro channel, and the minimum top-up is $1.
zukko
Pay 25×
less
for Claude Code & ChatGPT
One fetch_* key and base URL api.zukko.pro — for Cursor, Claude Code, Codex, and any SDK.
Related articles
- Prompt Injection: What It Is and How to Protect a Bot and an AgentHow prompt injection works through user input and third-party documents, and which measures limit the damage: data isolation, tool permissions, key limits.
- Your Own Neural Network Proxy on Node.js: Keep the API Key Off the FrontendA small Express server between your frontend and the model API: the key stays on the server, and models, request size and rate are capped.
- DeepSeek API in Python: Requests, Streaming, JSON and Error HandlingReady code for DeepSeek V4.1 Flash and V4 Pro on the OpenAI SDK: a request, streaming, JSON parsing and careful error handling.
- Prompt Engineering Examples: 12 Ready-Made Templates for WorkTwelve prompt templates for everyday tasks: what each one says, why it is built that way, and what a single API call costs.