Ліміти та квоти
Запити різні за вагою: картка контакту й список зі 100 замовлень навантажують сервер по-різному. Тому рахуємо не лише кількість запитів, а й їхню ціну в очках, як це роблять Shopify, GitHub чи Microsoft Dataverse.
Три обмеження одночасно
Квоти діють на компанію (усі токени разом) і перевіряються до виконання запиту. Якщо спрацювала будь-яка з них, відповідь буде 429.
| Обмеження | Що рахує | X-RateLimit-Reason |
|---|---|---|
| Запитів на секунду | Не більше 5 запитів у будь-якому вікні в 1 секунду, для всіх тарифів. | rps |
| Бюджет очок | Кожен запит має ціну. Бюджет поповнюється з постійною швидкістю й має запас на сплески. | points |
| Одночасні запити | Скільки запитів компанії виконується в цю мить. Захищає від довгих важких запитів. | concurrency |
Відхилений запит бюджет не витрачає, тому повторювати його безпечно.
Тарифи
| Тариф | Поповнення | Запас (сплеск) | Одночасно | Орієнтир |
|---|---|---|---|---|
| Service | 5 очок/с | 100 очок | 2 | ≈ 1 запис або 5 читань на секунду |
| Business | 15 очок/с | 300 очок | 4 | синхронізація замовлень маркетплейсу |
| Enterprise | 40 очок/с | 800 очок | 8 | упирається в 5 запитів/с раніше, ніж в очки |
Потрібно більше для конкретної інтеграції? Напишіть у підтримку: бюджет очок можна підняти індивідуально. Стеля 5 запитів/с діє для всіх.
Скільки коштує запит
| Запит | Очки |
|---|---|
GET однієї картки, довідник | 1 |
Список до 20 записів без expand, /count | 2 |
Список більше 20 записів або з expand | 5 |
| Створення, зміна, видалення: контакт, контрагент, лід, завдання, товар | 5 |
| Створення, зміна, видалення документів зі складом чи проводками: замовлення, рахунок, платіж та їхні позиції | 10 |
Доплата за час
Якщо запит виконувався довше 500 мс, після відповіді списується ще 1 очко за кожні 100 мс понад поріг. Так повільний фільтр у великій таблиці платить за себе сам. Бюджет при цьому може піти в мінус, і тоді наступні запити чекатимуть, доки він поповниться.
Фактичну ціну кожного запиту видно в журналі запитів (Налаштування → API).
Заголовки відповіді
| Заголовок | Значення |
|---|---|
X-RateLimit-Limit | Місткість бюджету очок (запас) за тарифом. |
X-RateLimit-Remaining | Скільки очок лишилось після цього запиту. |
X-RateLimit-Reset | Через скільки секунд бюджет знову буде повний. |
X-RateLimit-Cost | Ціна цього запиту в очках (без доплати за час). |
Retry-After | Лише в 429: через скільки секунд повторити. |
X-RateLimit-Reason | Лише в 429: rps, points або concurrency. |
Приклад 429
HTTP/1.1 429 Too Many Requests
Retry-After: 1
X-RateLimit-Reason: rps
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 244
{
"error": {
"code": "rate_limited",
"reason": "rps",
"message": "Перевищено ліміт запитів на секунду",
"retry_after": 1
}
}Як писати клієнта
- ●Отримали 429? Чекайте
Retry-Afterі повторіть той самий запит. Не «довбіть» без паузи. - ●Стежте за
X-RateLimit-Remainingі сповільнюйтесь заздалегідь, коли він малий. - ●Не більше 2–4 паралельних потоків, залежно від тарифу.
- ●Беріть сторінки по 100 замість 5 сторінок по 20: 5 очок замість 10.
- ●Замість повного перечитування використовуйте інкрементальну синхронізацію за
updated_at(Синхронізація). - ●Просіть лише потрібні поля через
fields=: відповідь швидша, доплати за час немає.
Python: повтор із Retry-After
import time, requests
def call(method, url, **kw):
for attempt in range(5):
r = requests.request(method, url, timeout=30, **kw)
if r.status_code != 429:
return r
time.sleep(int(r.headers.get("Retry-After", "1")))
r.raise_for_status()