Усі статті
8 хв читання

Як прибрати помилку 429 «Too Many Requests» на toncenter

Помилка 429 «Too Many Requests» на toncenter: чому вона б’є по ШІ-агентах, швидкий фікс бекофом і справжнє рішення — власний ключ із гарантованим throughput.

toncenterпомилка 429rate limit TONMCP TONTONNodeШІ-агенти TON

Токен-агент на TON падає в найневдаліший момент: користувач просить «покажи мій баланс і останні угоди», агент чесно йде в toncenter — а у відповідь прилітає не JSON з даними, а сухе HTTP 429 Too Many Requests. Агент за один тік спробував зібрати баланс гаманця, стан акаунта, історію транзакцій і смикнути пару get-методів — і публічний toncenter зачинив двері вже на другому запиті. Користувач бачить «щось пішло не так», а ви — стіну червоних логів з одним і тим самим статусом. Це не баг вашого коду. Це публічний rate limit toncenter, у який упирається будь-який агент, щойно починає працювати активніше за один запит на секунду.

Розберімо, звідки береться toncenter 429, чому саме ШІ-агенти ловлять Too Many Requests на TON найчастіше, як швидко збити частоту помилок бекофом — і як прибрати стелю зовсім, перейшовши на власний ключ із гарантованою пропускною здатністю.

Що означає 429 «Too Many Requests» на toncenter

Код 429 — це стандартна HTTP-відповідь «занадто багато запитів». Сервер не зламався і не відхилив ваші дані: він просто каже, що ви перевищили дозволену частоту звернень і вас пригальмовують (rate limiting). У toncenter (v2) тіло відповіді при цьому має приблизно такий вигляд:

{ "ok": false, "error": "Rate limit exceeded", "code": 429 }

Ключове: "ok": false і "code": 429 — це HTTP-статус, продубльований у тілі, а не внутрішній код помилки контракту. І зверніть увагу: поля result з даними акаунта тут узагалі немає — текст ліміту лежить у полі error. Тож якщо ваш код одразу тягне дані з result, він отримає undefined і, найімовірніше, впаде десь далі по стеку з невиразною помилкою парсингу — хоча справжня причина лежить в error. Правило просте: коли ok: false, спершу перевіряйте code і читайте error, а не розбирайте неіснуючий result.

Окремо про фольклор: у TON-ком’юніті гуляє «помилка 228». Це не код API, а мем — жоден сервер вам 228 не поверне. Реальний код ліміту — саме 429, і шукати в документації треба саме його. 429 — тимчасова помилка: той самий виклик пройде, якщо зробити його повільніше або з валідним ключем.

Чому без ключа toncenter дає ~1 запит/с

Публічний toncenter без API-ключа обмежує вас приблизно одним запитом на секунду. Це не баг і не жадібність — це захист спільного безкоштовного ресурсу, яким користуються тисячі людей одночасно. Кілька нюансів, на яких спотикаються навіть досвідчені розробники:

  • Спільний пул — це про анонімний трафік. Без ключа ви ділите єдиний публічний ліміт приблизно в 1 rps з усіма безіменними запитами з усього світу. У годину пік реально доступна вам частота може виявитися навіть нижчою.
  • Платний ключ піднімає стелю — але тільки якщо він справді переданий у запиті. Класична пастка: ключ є, а заголовок X-API-Key загубився під час рефакторингу HTTP-клієнта, і ви знову сидите на публічному ліміті, годинами не розуміючи, чому платний тариф «не працює».

Один запит на секунду — це нормально для ручного дебагу в браузері чи скрипта, який раз на хвилину перевіряє баланс. Для будь-якої автоматизації, а тим паче для агента, це вбивчо мало.

Чому ШІ-агенти ловлять 429 найчастіше: берст-патерн

І ось тут починається найцікавіше. Звичайний застосунок шле запити більш-менш рівномірно. ШІ-агент працює інакше — берстами (burst, сплеск). Він живе тіками: на одному кроці міркування йому треба зібрати контекст, і він смикає десятки викликів поспіль, майже одночасно.

Уявіть один крок: «користувач просить перевірити, чи прийшов платіж». Щоб відповісти, агент за частки секунди смикає поспіль:

  1. get_masterchain_info — дізнатися поточну голову блокчейна;
  2. get_balance — баланс гаманця;
  3. get_account_state — статус і прапорці акаунта;
  4. get_transactions — останні транзакції;
  5. run_get_method — прочитати get-метод контракту;
  6. get_jetton_balance — а заразом і баланс USDT.

Шість викликів за один тік. Ліміт — один на секунду. Перший пройде, а решта повернуть 429, і агент або застрягне, або почне галюцинувати на неповних даних. Причому це не «кривий агент» — це нормальна архітектура автономного міркування: збери контекст, потім думай. Ба більше, впіймавши помилки, агент часто намагається «полагодити» їх повторними викликами — і добиває вже вичерпану квоту. Публічний ліміт просто не розрахований на такий профіль навантаження.

Схожа історія і з публічними лайтсерверами з глобального конфігу TON — під навантаженням вони відповідають not ready або відвалюються по ADNL-таймауту. Про це окремо: чому лайтсервер відповідає «not ready» і що робити. І в tonapi.io та сама хвороба 429 — розбір тут.

Швидкий фікс: ретраї з експоненційним бекофом і Retry-After

Перше, що варто зробити просто зараз, — перестати бити в стіну на повній швидкості. Якщо 429 усе ж прилетів, не гатіть у сервер повторно одразу: це лише подовжує бан. Це паліатив — він знижує частоту 429, але не піднімає стелю. Правильний паліатив складається з чотирьох частин.

1. Експоненційний бекоф із джитером. Перед кожною наступною спробою чекайте довше, ніж перед попередньою, плюс випадкова добавка, щоб паралельні воркери не синхронізувалися і не били в одну й ту саму секунду.

async function fetchWithBackoff(url, opts = {}, maxRetries = 5) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    const res = await fetch(url, opts);
    if (res.status !== 429) return res;

    // Пріоритет — Retry-After від сервера, інакше експонента з джитером
    const retryAfter = res.headers.get("Retry-After");
    const baseMs = retryAfter
      ? Number(retryAfter) * 1000
      : Math.min(1000 * 2 ** attempt, 16000);
    const jitter = Math.random() * 300;
    await new Promise((r) => setTimeout(r, baseMs + jitter));
  }
  throw new Error("toncenter: 429 не відпустив після ретраїв");
}

2. Зважайте на заголовок Retry-After, якщо він прийшов. toncenter на 429 його зазвичай не надсилає, тому основну ставку робіть на власну формулу бекофу. Але якщо сервер усе ж указав, скільки чекати, — чекайте рівно стільки, а не вгадуйте (у коді вище саме це й робить гілка if (retryAfter)).

3. Обмежте конкурентність. Поставте перед toncenter чергу або семафор, який випускає не більше ~1 запиту на секунду. Тоді берст агента розтягнеться в часі: той самий список із шести викликів виконається послідовно, за ~6 секунд, але без жодного 429.

4. Кешуйте повторювані читання. get_masterchain_info у межах одного кроку можна запросити один раз і перевикористати. Метадані жетона (decimals, символ) не змінюються — читайте їх один раз. Баланс, який ви читали 300 мс тому, навряд чи змінився.

Це працює і робить агента ввічливішим, але визнаймо чесно: бекоф не піднімає стелю. Ви все ще замкнені в 1 rps, просто тепер чемно стоїте в черзі замість того, щоб падати. Користувач чекає секунди там, де міг би чекати мілісекунди. Для агента, якому важлива швидкість відгуку, це лікування симптому, а не хвороби. Інші обхідні шляхи публічних API — у добірці альтернатив toncenter на 2026.

Справжнє рішення: власний ключ і TON через MCP

Корінь проблеми в тому, що ви ділите вузький публічний канал із тисячами анонімних запитів. Єдиний спосіб прибрати 429 по-справжньому — отримати власну гарантовану пропускну здатність замість спільної квоти. Тоді берст агента з шести викликів проходить цілком, а не впирається в стіну на п’ятому, і агент може збирати контекст на повній швидкості. Ретраї з бекофом залишаються як страховка від мережевих збоїв, але перестають бути основним механізмом виживання.

І є шлях, який на додачу прибирає вовтузіння з HTTP-статусами взагалі. Якщо дані з TON потрібні саме ШІ-агенту, логічніше віддавати їх не сирою REST-відповіддю, яку треба парсити й обробляти на 429, а як готові інструменти через MCP.

MCP (Model Context Protocol) — стандарт, за яким ШІ-агенти (Claude, Cursor, ChatGPT/Codex, будь-який MCP-клієнт) викликають зовнішні інструменти. Замість того щоб учити агента правильно формувати HTTP-запит до toncenter, ловити 429, читати Retry-After і парсити JSON, ви даєте йому типізовані інструменти, а всю чорну роботу з мережею бере на себе сервер.

TONNode — це hosted MCP-сервер для TON, рівно 16 інструментів. Ті шість читань, якими агент зазвичай і пробиває ліміт toncenter, тут — готові виклики:

  • get_masterchain_info — голова мастерчейна;
  • get_balance — баланс GRAM;
  • get_account_state — статус, прапорці, остання транзакція;
  • get_transactions — історія транзакцій;
  • run_get_method — будь-який read-only get-метод контракту;
  • get_jetton_balance — баланс жетона або USDT (адреса жетон-гаманця обчислюється он-чейн).

(До речі, GRAM — це перейменований у червні 2026 року Toncoin. Мережа й далі називається TON, змінилася лише назва монети.)

Під капотом пакет @tonnode/mcp працює за нативним протоколом TON — ADNL, без HTTP-прошарків. Тобто ви не просто міняєте один REST-ендпоінт на інший: агент спілкується з мережею напряму, а ви перестаєте вручну розгрібати HTTP-семантику лімітів. Пакет open source (MIT), лежить на npm і GitHub (tonnode/mcp).

Різниця на практиці: агенту більше не треба знати, що таке 429, Retry-After чи ADNL-таймаут. Він каже «дай баланс і останні транзакції цієї адреси» — і отримує структуровану відповідь. Той самий берст із шести викликів іде на сервер, у якого є пропускна здатність під вашим ключем, а не на спільний публічний ліміт.

Як підключити і з чого почати безкоштовно

Є два шляхи, і почати можна взагалі без реєстрації.

Безкоштовно й локально

Повний набір інструментів читання через публічний конфіг — просто додайте в налаштування вашого MCP-клієнта:

{
  "mcpServers": {
    "ton": {
      "command": "npx",
      "args": ["-y", "@tonnode/mcp"]
    }
  }
}

Жодних ключів, npx сам підтягне пакет. Цього досить, щоб спробувати й переконатися, що агент читає TON без жодного 429. Детальний розбір — у гайді про безкоштовний MCP для TON.

Hosted-ендпоінт із власним ключем

Коли потрібна гарантована пропускна здатність під реальне навантаження, підключаєте hosted-ендпоінт із власним ключем:

{
  "mcpServers": {
    "ton": {
      "type": "http",
      "url": "https://mcp.tonnode.io/mcp",
      "headers": { "Authorization": "Bearer tn_live_…" }
    }
  }
}

Далі просто розмовляєте з агентом людською мовою — він сам обере потрібний інструмент:

«Перевір адресу EQC…: візьми баланс через get_balance, статус акаунта через get_account_state і останні 10 транзакцій через get_transactions. Потім через get_jetton_balance подивися баланс USDT.»

Агент викличе потрібні інструменти в потрібному порядку — а не гатитиме наосліп у rate limit.

Тарифи

На всіх тарифах доступні всі 16 інструментів — платите ви лише за пропускну здатність:

Тариф Ціна Пропускна здатність
Hobby безкоштовно назавжди 60 запитів/хв
Pro $29/міс 300 запитів/хв
Scale $199/міс 1200 запитів/хв

Навіть безкоштовний Hobby на 60 запитів/хв — це зовсім інший режим, ніж публічний toncenter з його ~1 rps: ті самі ~60 запитів на хвилину, але вже гарантовано ваші, а не спільні з натовпом анонімів. Берст агента з десятка викликів проходить цілком, без жодного 429. Ключ Hobby видається одразу після входу, без картки.

Оплатити платні тарифи можна в GRAM або USDT у мережі TON через TonConnect, або в BTC/ETH/SOL та інших через рахунок xRocket у Telegram.

Кілька чесних застережень, щоб не було завищених очікувань: TONNode зараз закриває завдання читання й побудови транзакцій, але не пропонує як готові продукти pay-per-request, REST-API v2, вебхуки, SSE-стрими чи письмовий SLA з відсотками аптайму. Архівна нода з глибокою історією ще синхронізується — це пункт роадмапу, а не сьогоднішня гарантія. Усе, що описано вище, працює вже зараз.

Практичний план переходу

  1. Заберіть безкоштовний ключ Hobby (60 запитів/хв, без картки): tonnode.io/dashboard?plan=hobby.
  2. Пропишіть hosted-конфіг вище у свій MCP-клієнт.
  3. Замініть ручні виклики toncenter на інструменти get_balance, get_account_state, get_transactions, run_get_method, get_jetton_balance.
  4. Щойно агент упреться в 60 запитів/хв під навантаженням — переходьте на Pro за $29/міс (300 запитів/хв): tonnode.io/pricing.

Підсумок

  • 429 «Too Many Requests» на toncenter — це означає, що ви вперлися в публічний ліміт ~1 rps, а не збій у вашому коді. (І це точно не «228» — такого коду не існує.)
  • ШІ-агенти ловлять його найчастіше через берст-патерн: десятки викликів за один тік міркування.
  • Ретраї з експоненційним бекофом, Retry-After, семафор і кеш знижують частоту 429, але стелю не рухають — і то ціною швидкості.
  • Справжній вихід — власний ключ із гарантованою пропускною здатністю. А якщо дані потрібні саме агенту, TONNode віддає ті самі читання TON як MCP-інструменти, і питання «як обробити 429» просто зникає з вашого коду.

Почніть безкоштовно: отримати ключ Hobby — 60 запитів/хв, без картки. Якщо в агента реальне навантаження і берсти щільні — одразу беріть Pro за $29/міс, 300 запитів/хв.

Дайте вашому агенту доступ до TON

16 MCP-інструментів: читання, некастодіальні свопи, кросчейн і гаманці. Безкоштовний тариф — 60 зап/хв, картка не потрібна.