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:

bash
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:

bash
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:

bash
export OPENAI_BASE_URL=https://api.zukko.pro/v1
export OPENAI_API_KEY=fetch_your_key

The /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):

ModelZukko input / outputVendor price input / outputIntelligence index
gpt-6-astra0.62 / 3.0510 / 5053
gpt-6.1-sol0.27 / 1.322 / 1052
gpt-6-sol0.13 / 0.632 / 10—
gpt-5.6-sol0.22 / 1.075 / 30—
gpt-5.6-terra0.13 / 0.632.5 / 1542
gpt-6-luna0.04 / 0.210.1 / 0.538
gpt-5.6-luna0.06 / 0.31 / 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:

bash
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:

bash
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_format and 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, 404 model_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 code model_disabled means the model is switched off — pick another one from GET /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

  1. Create a key in the dashboard, set a daily limit and allowed models.
  2. Change base_url to https://api.zukko.pro/v1 (or set OPENAI_BASE_URL).
  3. Replace the old key with your fetch_... key.
  4. Check model names against GET /v1/models and move them into config.
  5. Add an if chunk.choices: check to streaming code.
  6. In the Responses API, send history in input; don't rely on previous_response_id.
  7. Run tests for every endpoint and parameter you actually use.
  8. Handle 402, 403 and 503 model_disabled.
  9. 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.

Get API keyDocumentation

api.zukko.pro · fetch_*

OpenAI API alternative from Russia: migrating your code · Zukko