API Notiondesk обрабатывает каждую ошибку с помощью одного и того же JSON-конверта и машиночитаемого заголовка code, ограничивает количество операций чтения и записи для каждого ключа до 120 в минуту и позволяет безопасно повторить любое изменение с помощью заголовка Idempotency-Key. В этой статье перечислены все коды ошибок API Notiondesk, объясняются ограничения скорости и их заголовки, а также показано, как создавать сценарии повторных попыток, которые никогда не изменят ничего дважды.
Ошибка API Notiondesk
Каждая ошибка имеет одинаковую форму, и каждое поле всегда присутствует:
{
"object": "error",
"code": "validation_error",
"message": "The request parameters are invalid.",
"request_id": "0f2c1e94-7a1b-4c2d-9e3f-5a6b7c8d9e0f",
"errors": [
{"field": "page_size", "message": "This value should be between 1 and 100."}
]
}| Поле | Значение |
|---|---|
object | Всегда __СОХРАНЕНО_78__ |
code | Машинночитаемая ошибка. Разверните свой код, используя только это поле. |
message | Объяснение, понятное человеку. Оно может меняться, поэтому никогда не пытайтесь его расшифровать. |
request_id | Идентифицирует запрос при обращении в службу поддержки. null, если запрос не удался до достижения маршрута, например, по неизвестному пути. |
errors | Проблемы на уровне полей, каждая с field и message. Пусто, если ошибка не связана с конкретным входным параметром. |
Как field обозначает значение
- Поле верхнего уровня имеет свое название:
page_size.
- Внутри списка поле задает имя списка, затем в скобках указывается запись, а затем само поле:
items[fr].page_title.
- В скобках хранится идентификатор записи в том виде, в котором вы его отправили (
localeвitems,category_idвchangelog_categories), если каждая запись имеет свой уникальный идентификатор. В противном случае в скобках хранится позиция записи, начиная с нуля:items[0].locale.
- Проблема с запросом в целом имеет код
"field": null.
Коды ошибок API Notiondesk
code | HTTP-статус | Значение | Что делать |
|---|---|---|---|
authentication_error | 401 | Ключ или токен доступа отсутствует или не может быть использован. | Проверьте ключ, срок его действия и план. См. раздел «Аутентификация с помощью API Notiondesk». |
insufficient_scope | 403 | Данные учетные данные не соответствуют требованиям маршрута. | Используйте ключ с областью действия, указанной в WWW-Authenticate |
permission_denied | 402, 403 | Учетные данные не могут выполнить это действие с данным ресурсом, например, потому что в плане отсутствует соответствующая функция. | Проверьте тарифный план и настройки справочного центра. Не повторяйте попытку без изменений. |
invalid_version | 400 | Заголовочный файл nd-version указывает на неизвестную версию. | Отправьте 2026-10-16 или опустите заголовок. |
validation_error | 400, 422 | Параметр или поле тела запроса недопустимы, неизвестны или выходят за пределы допустимого диапазона. | Исправьте поля, перечисленные в errors |
not_found | 404, 405 | Путь, ресурс или метод не существуют. | Проверьте идентификаторы и метод. |
conflict_error | 409 | Запрос противоречит текущему состоянию, например, синхронизация уже выполняется. | Подождите, затем попробуйте снова. |
idempotency_key_invalid | 400 | Заголовок Idempotency-Key пуст или содержит более 255 символов. | Отправьте от 1 до 255 символов |
idempotency_key_reused | 422 | Номер Idempotency-Key уже был использован для другого запроса. | Используйте новый ключ для нового запроса. |
request_in_progress | 409 | Запрос с тем же номером Idempotency-Key всё ещё выполняется. | Подождите, затем попробуйте снова с тем же ключом. |
rate_limited | 429 | Слишком много запросов | Подождите Retry-After секунд |
internal_error | 500 и выше | Notiondesk failed | Попробуйте позже и укажите код request_id при обращении в службу поддержки. |
Запрос к справочному центру или ресурсу за пределами вашего рабочего пространства приводит к ошибке 404 not_found, поэтому API никогда не раскрывает информацию о его существовании.
Notiondesk Ограничения скорости API
Каждый API-ключ и каждое разрешение OAuth имеют два лимита запросов, отсчитываемых в течение скользящего минутного окна:
| Бюджет | Маршруты | Запросов в минуту |
|---|---|---|
| Читает | __СОХРАНЕННЫЕ_38__ маршруты | 120 |
| Пишет | маршруты POST, PATCH и DELETE | 20 |
Аналитические отчеты также учитываются в рамках бюджета в 30 запросов в минуту на каждый центр поддержки , который распределяется между всеми приложениями Key и OAuth в рабочем пространстве.
Ответы содержат три заголовка:
| Заголовок | Значение |
|---|---|
X-RateLimit-Limit | Запросы, разрешенные в текущем окне |
X-RateLimit-Remaining | Запросы, оставленные в текущем окне |
Retry-After | Секунды до принятия следующего запроса; 0 пока остаются запросы |
Запрос, превышающий бюджет, отвечает 429 rate_limited. Подождите количество секунд в Retry-After, прежде чем отправлять следующий запрос.
Повторите попытку безопасно с помощью Idempotency-Key
Истекло время ожидания в сети, поэтому вы не уверены, были ли внесены изменения. Заголовок Idempotency-Key позволяет отправить тот же запрос повторно, не внося никаких изменений дважды.
Принимаются любые изменения маршрута: изменения перенаправления страницы, обновления настроек и фирменной символики, изменения интеграции и триггеры синхронизации. При первой попытке отправляется уникальное значение от 1 до 255 символов, например, UUID, и то же значение при каждой повторной попытке:
Что происходит при повторной попытке:
curl -X POST "https://api.notiondesk.so/sites/c74781f6-1aea-4e17-ab23-bbb8b4d174b6/page-redirects" \
-H "Authorization: Bearer $NOTIONDESK_API_KEY" \
-H "nd-version: 2026-10-16" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 6f0d6b1e-create-getting-started" \
-d '{"type": "article", "source_path": "/legacy/getting-started", "target_id": "1761580412", "locale": "en"}'| Повторить попытку | Результат |
|---|---|
| Тот же ключ, то же тело запроса, тот же маршрут после завершения первого запроса. | Первый ответ снова, включая статус и текст, с X-Idempotent-Replay: true. Ничего не меняется. |
| Используйте тот же ключ, пока выполняется первый запрос. | 409 request_in_progress. Подождите и повторите попытку. |
| Тот же ключ, но с другими идентификаторами тела запроса, маршрута или пути. | 422 __СОХРАНЕНО_24__ |
| Тот же ключ и то же тело запроса после первого ответа привели к ошибке. | Запрос выполняется снова. |
Успешный ответ в первый раз содержит X-Idempotent-Replay: false, а при повторном воспроизведении — true. Notiondesk хранит ключ не менее 24 часов. Ключ принадлежит API-ключу или OAuth-гранту, который его отправил, и OAuth-грант сохраняет свои ключи при обновлении токена.
Без заголовка запрос выполняется один раз, и повторяется.
Эффективная стратегия повторных попыток
- Для каждого логического изменения генерируйте один объект
Idempotency-Keyи используйте его повторно при каждой попытке повторного внесения этого изменения.
- При достижении
429 rate_limitedподождитеRetry-Afterсекунд, затем повторите попытку.
- В
409 request_in_progressподождите несколько секунд, затем повторите попытку с тем же ключом. В409 conflict_errorуже запущена синхронизация справочного центра: подождите несколько минут, прежде чем запускать ее снова, или пропустите этот запуск.
- При возникновении ошибки
500и выше, или сетевой ошибки, повторите попытку с экспоненциальной задержкой, например, через 1, 2, 4 и 8 секунд.
- Никогда не пытайтесь повторно отправить запросы
400,401,403,404или422без изменений. Сначала исправьте запрос.
В JavaScript для любого маршрута, который что-то изменяет, процесс останавливается на conflict_error и оставляет принятие решения вашему коду:
Часто задаваемые вопросы
import { randomUUID } from "node:crypto";
const sleep = (seconds) => new Promise((resolve) => setTimeout(resolve, seconds * 1000));
async function notiondeskRequest(method, path, body, attempts = 5) {
const idempotencyKey = randomUUID();
for (let attempt = 0; attempt < attempts; attempt++) {
let response;
try {
response = await fetch(`https://api.notiondesk.so${path}`, {
method,
headers: {
Authorization: `Bearer ${process.env.NOTIONDESK_API_KEY}`,
"nd-version": "2026-10-16",
"Content-Type": "application/json",
"Idempotency-Key": idempotencyKey,
},
body: body ? JSON.stringify(body) : undefined,
});
} catch {
await sleep(2 ** attempt);
continue;
}
if (response.ok) {
return response.status === 204 ? null : response.json();
}
const error = await response.json().catch(() => ({}));
const retryable = response.status === 429 || response.status >= 500 || error.code === "request_in_progress";
if (!retryable) {
throw new Error(`${response.status} ${error.code}: ${error.message}`);
}
const retryAfter = Number(response.headers.get("Retry-After"));
await sleep(retryAfter > 0 ? retryAfter : 2 ** attempt);
}
throw new Error(`Notiondesk request failed after ${attempts} attempts`);
} Каковы ограничения скорости запросов к API Notiondesk?
120 запросов на чтение и 20 запросов на запись в минуту для каждого ключа API или разрешения OAuth, плюс 30 запросов на аналитику в минуту для каждого центра поддержки. Запрос, превышающий лимит, получает ответ 429 с заголовком Retry-After.
Какое поле должен проверять мой код при возникновении ошибки?
code. Это единственный стабильный машиночитаемый классификатор. message предназначен для людей и может изменяться.
Что мне следует отправить в службу поддержки, если запрос не удался?
Данные request_id из ответа об ошибке, вызванный вами маршрут и время запроса.
Безопасно ли повторять запуск синхронизации?
Да, с ключом Idempotency-Key. Повторная попытка с тем же ключом снова выдает первый результат и ничего не ставит в очередь. Без ключа запуск синхронизации второго сайта во время работы первого приводит к ошибке 409 conflict_error.