Лимиты
Ограничения на задачи, вложения и запросы к API.
Лимиты держат DoneBy быстрым для всех. Обычные списки до них не доходят, но если вы строите интеграцию или переносите большой архив задач, лучше знать их заранее.
Задачи, списки и файлы
| Что ограничено | Лимит |
|---|---|
| Задач в одном списке | 5 000 |
| Подзадач у задачи | 100 |
| Пунктов в чек-листе | 200 |
| Размер одного вложения | 100 МБ |
| Длина названия задачи | 500 символов |
| Длина описания | 20 000 символов |
| Напоминаний у задачи | 5 |
| Сохранённых подборок | 50 на участника |
Если упереться в лимит в приложении, DoneBy покажет подсказку прямо в поле. Через API придёт 422 unprocessable с указанием лимита в details — см. Коды ошибок.
Совет
5 000 задач в списке — много, но выполненное копится годами. Раз в квартал переносите закрытые проекты в архивный список: рабочие списки останутся обозримыми, а история никуда не денется.
Лимиты по тарифам
| Возможность | Старт | Команда | Бизнес |
|---|---|---|---|
| Участники | 1 | до 50 | от 10, без верхнего лимита |
| Гостевой доступ | — | до 5 гостей | без лимита |
| Вложения | 5 ГБ | 10 ГБ на участника | 50 ГБ на участника |
| REST API | — | 300 запросов/мин | 1200 запросов/мин |
| Вебхуки | — | до 20 адресов | до 100 адресов |
| История изменений | 30 дней | 90 дней | 1 год + журнал действий |
| Выгрузка по расписанию | — | — | есть |
Полное сравнение — на странице Тарифы.
Лимиты API
| Параметр | Значение |
|---|---|
| Запросов в минуту, тариф Команда | 300 |
| Запросов в минуту, тариф Бизнес | 1 200 |
| Как считается | На рабочее пространство, по всем токенам вместе |
Размер страницы (limit) | от 1 до 100, по умолчанию 50 |
| Размер тела запроса | 1 МБ |
Срок жизни Idempotency-Key | 24 часа |
| Время на ответ вебхуку | 10 секунд |
| Адресов вебхуков | Команда — до 20 адресов, Бизнес — до 100 адресов |
Важно
Лимит общий для пространства. Ночная сверка, которая выбирает весь запас за минуту, оставит без запросов интеграцию, создающую задачи из CRM. Разносите тяжёлые фоновые задачи по времени или ограничивайте их скорость на своей стороне.
Заголовки X-RateLimit
Каждый ответ API сообщает, сколько запросов осталось:
| Заголовок | Значение |
|---|---|
X-RateLimit-Limit | Лимит запросов в минуту для пространства: 300 или 1 200. |
X-RateLimit-Remaining | Сколько запросов осталось в текущем окне. |
X-RateLimit-Reset | Когда окно обновится, — Unix-время в секундах. |
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 287
X-RateLimit-Reset: 1758200460
X-Request-Id: req_4Hc9QmЕсли X-RateLimit-Remaining подходит к нулю, лучше притормозить заранее, чем ловить 429: подождите до X-RateLimit-Reset и продолжайте.
Что делать при 429
HTTP/1.1 429 Too Many Requests
Content-Type: application/json; charset=utf-8
Retry-After: 18
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1758200460
X-Request-Id: req_7Yp2kX
{
"error": {
"code": "rate_limited",
"message": "Слишком много запросов. Повторите через 18 секунд.",
"details": { "retry_after": 18 },
"request_id": "req_7Yp2kX"
}
}- Прочитайте
Retry-After— сколько секунд подождать. Повтор раньше срока снова получит429. - Если заголовка нет (например, при
500), ждите по экспоненте: 1, 2, 4, 8 секунд и так далее, с небольшим случайным разбросом и не дольше минуты. - Ограничьте число попыток — пяти обычно хватает — и записывайте в лог
X-Request-Idнеудачных запросов. - Повторяйте
POSTс тем жеIdempotency-Key, что и в первой попытке: тогда повтор не создаст дубль.
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
const RETRYABLE = new Set([429, 500, 503]);
export async function withRetry(send, { attempts = 5, maxDelayMs = 60000 } = {}) {
for (let attempt = 0; ; attempt++) {
let res;
try {
res = await send();
} catch (networkError) {
if (attempt + 1 >= attempts) throw networkError;
}
if (res && !RETRYABLE.has(res.status)) return res;
if (attempt + 1 >= attempts) return res;
const retryAfter = res ? Number(res.headers.get('Retry-After')) : 0;
const backoff = Math.min(1000 * 2 ** attempt, maxDelayMs);
const delay = retryAfter > 0 ? retryAfter * 1000 : backoff;
await sleep(delay + Math.random() * 250);
}
}const key = crypto.randomUUID();
const res = await withRetry(() =>
fetch(process.env.DONEBY_API_URL + '/tasks', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.DONEBY_TOKEN}`,
'Content-Type': 'application/json',
'Idempotency-Key': key,
},
body: JSON.stringify({
title: 'Передать показания счётчиков',
due_date: '2026-09-25',
}),
})
);В скриптах на curl достаточно флага --retry: curl сам повторяет 429 и 503 и учитывает Retry-After.
curl --retry 5 --retry-max-time 120 \
"https://doneby.app/api/v1/tasks?limit=100" \
-H "Authorization: Bearer $DONEBY_TOKEN"Как тратить меньше запросов
- Вебхуки вместо опроса. Проверка раз в 5 секунд — это 12 запросов в минуту на одну задачу интеграции, даже когда ничего не меняется. Вебхук приходит только тогда, когда есть что сообщить.
- `updated_since` вместо полной выборки. При синхронизации забирайте только изменённые задачи.
- `limit=100`. Полная выгрузка займёт вдвое меньше запросов, чем со страницами по 50.
- Кэш для редко меняющегося. Участников и списки достаточно перечитывать по вебхукам
member.joined,list.createdиlist.archived.