The three tiers are not just for show. The top-tier OpenAI model in the bot is 20 times more expensive than the lower-tier model, both for input and output. If everyone is given access only to the flagship, a simple “translate a paragraph” will cost as much as analyzing a contract.

For images, I chose Nano Banana 2.1. It was released in October and, at the same resolution, is about a quarter cheaper than Nano Banana 2. Version 2 remains a backup in case the new one starts malfunctioning.

The models are connected through a common provider layer. Adding a new family or replacing a model means adding a new adapter and a catalog entry; the business logic does not change.

Billing: how to avoid going into the red

This was the main engineering challenge. The cost of a request to the neural network is unknown in advance: no one knows how many tokens the model will produce in its response.

The naive “check balance → send request → deduct” scheme breaks down immediately. A user with a balance of 100 credits sends two computationally heavy requests, from a phone and a laptop. Both pass the check, both are processed, and the balance goes negative. The bot owner will end up paying for that deficit.

Therefore, every request goes through four steps.

1. Top-down estimate.We count input tokens through the vendors' own APIs: OpenAI has a token-counting endpoint, Gemini has countTokens. We limit output with the max_output_tokens parameter. The model's reasoning counts toward this same limit, so the model physically cannot spend more.

Price = input tokens × input price + output limit × output price. This is an upper bound, not a forecast. The user sees it before sending the request.

With images it's simpler: a fixed price per image based on resolution plus the input tokens of the prompt.

2. Reserve (hold). We reserve the amount in a single transaction in PostgreSQL. The balance check condition sits right in the UPDATE, so two parallel requests cannot both pass the check.

BEGIN; -- idempotency key = the update ID from MAX: -- a webhook redelivery will not create a second hold INSERT INTO holds (idem_key, user_id, amount) VALUES (:update_id, :user_id, :hold); UPDATE wallets SET held = held + :hold, active_holds = active_holds + 1 WHERE user_id = :user_id AND balance - held >= :hold AND active_holds < 2; -- 0 rows updated → ROLLBACK -- and the message "insufficient credits" COMMIT;

PostgreSQL locks the wallet row for the duration of the UPDATE. The second request waits and rechecks the condition already taking the first hold into account. I also limited the number of concurrent requests to two, so that a single user can't clog the queue.

3. Charge the actual amount. Once the model has responded, we take the real usage from usage and charge min(actual, hold). The remainder of the hold is returned to the balance.Usually, the actual amount is significantly lower than the upper estimate, so the user only overpays temporarily.

4. Cleanup. If the process crashes in the middle of a request, the hold will get stuck. It is released by a background TTL task. It is important that the vendor request timeout be shorter than the hold’s TTL—otherwise, the hold will expire while the model is still responding.

All money movements are written to an append-only log. The balance can always be reconstructed from the log, and it is possible to trace where every credit went.

I tested race conditions on a real PostgreSQL instance, not on mocks: the tests initiate parallel holds on the same wallet and verify that the balance does not fall below zero.

Нейросети в MAX за рубли: что решить до первого платежа
Neural networks in MAX for rubles: what to decide before the first payment

The entire request path: money is reserved before the model is called and is only debited after the response.

How self-employed individuals can accept payments in 2026

I work as a self-employed individual, and this is where I got a surprise. The usual route through YuKassa no longer works: as of December 29, 2025, it has stopped sending self-employed individuals’ receipts to “My Tax.”

Manually processing receipts is not an option either. When paying by card or via SBP, a receipt must be generated at the time of settlement—as required by the NPD law (Part 3, Article 14 of Federal Law No. 422-FZ). With a stream of small top-ups, there is no way to keep up with this manually.

In the end, I chose Robokassa with the “Robocheki SMZ” service.What matters for the bot:

  • receipts are sent to “My Tax” automatically and for free;

  • payment via a link is exactly what is needed in MAX, which has no built-in payment functionality;

  • there is a server-side payment notification (ResultURL);

  • according to their calculator, the fee on the “Starter” plan is 3.9% for cards and 2.7% for SBP.

The top-up process works like this. The user clicks “Top up” and selects a package. The bot sends a payment link. After payment, Robokassa calls the ResultURL: we verify the signature, credit the funds, and send the user a message in the chat.

The ResultURL handler must be idempotent by invoice number. Payment providers repeat notifications, and without this, a single payment will be credited twice.

Refunds of the unused balance are also automated through Robokassa’s refund API, with the receipt being voided. Why it is needed is explained in the next section.

What laws apply to such a bot

There is no direct ban on such a service, but there are many mandatory requirements. I am not a lawyer—below is what I found on my own and incorporated into the product.

Нейросети в MAX за рубли: что решить до первого платежа
Neural networks in MAX for rubles: what to decide before the first payment

A separate matter is the notification to Roskomnadzor. It is often overlooked, and since May 30, 2025, a citizen can be fined RUB 5,000–10,000 for failing to submit it. It is filed online on Roskomnadzor’s website, so it is cheaper to take care of it right away.

Another clause in the terms of service is easy to forget: the prohibition on uploading other people’s photos for processing without their consent.If the bot accepts photos for editing, other people’s photos will be sent there on the very first day.

What this all came down to

Less time went into the bot itself—the dialogue, model selection, and image generation. Most of it went into making sure the money was accounted for fairly: no one’s balance goes negative, receipts are sent to the tax authority, and the remainder can be refunded.

If you’re building your own paid bot in MAX, start with three things:

  1. Check that you can register on the partner platform.

  2. Choose a payment provider that automatically sends receipts to “My Tax.”

  3. Design the funds reserve before the first request to the model, not after the first negative balance.

You can see how it works from the user’s perspective in the bot itself—“Ask AI” in MAX. There you can see the cost estimate before the request and how the remainder of the reserve is returned.

Questions about billing, the MAX Bot API, or self-employed receipts—ask in the comments, and I’ll answer.