Надёжность

    Ошибки

    Обрабатывайте HTTP-статус и машинный error.code, а не сравнивайте полный текст сообщения. Текст предназначен человеку и может уточняться.

    {
      "error": {
        "message": "Безопасное описание ошибки",
        "type": "neuroapi_error",
        "code": "upstream_unavailable"
      }
    }
    HTTPКодДействиеПовтор
    400/422invalid_request / invalid_video_requestИсправить поля, формат или несовместимое сочетание параметров.Нет
    400invalid_external_mediaПроверить публичную HTTPS-ссылку либо передать Base64/data URL.Нет
    403pre_consume_token_quota_failedПополнить баланс или проверить лимит ключа.Нет
    403moderation_blockedПровайдер отклонил содержимое; переформулировать запрос или убрать спорное медиа.Нет
    429rate_limit_exceededСнизить параллелизм и повторить с задержкой.Да
    503upstream_unavailableСервис генерации временно перегружен; повторить с backoff.Да
    5xxinternal_errorВременная ошибка NeuroAPI; повторить с backoff и сохранить request id.Да

    Когда повторять

    Повторяйте только явно полученные временные 429/502/503/504. Используйте экспоненциальную задержку, jitter и ограничение числа попыток. Сетевой таймаут после отправки тела запроса может означать, что генерация уже началась: не повторяйте создающий POST вслепую.

    Когда не повторять

    400/422, цензура, неверные медиа и недостаток баланса требуют действия пользователя. Автоматический повтор только создаст лишнюю нагрузку.

    const retryable = new Set([429, 502, 503, 504]);
    
    async function requestWithBackoff(run: () => Promise<Response>) {
      for (let attempt = 0; attempt < 3; attempt += 1) {
        const response = await run();
        if (response.ok || !retryable.has(response.status)) return response;
        if (attempt === 2) return response;
    
        const retryAfter = Number(response.headers.get("retry-after"));
        const delay = Number.isFinite(retryAfter)
          ? retryAfter * 1000
          : 1000 * 2 ** attempt + Math.random() * 300;
        await new Promise((resolve) => setTimeout(resolve, delay));
      }
      throw new Error("unreachable");
    }
    Для асинхронного видео действуют более строгие правила: если получен task ID или HTTP 202, повторять POST нельзя. Повторяйте только GET статуса или скачивания.

    Медиа по внешней ссылке

    Ссылка может быть недоступна, слишком медленна либо затронута сетевой фильтрацией и ТСПУ Роскомнадзора. Проверьте, что URL публичный и открывается без cookie/авторизации. Для небольших файлов надёжнее скачать их в приложении и передать Base64.

    Если запрос завершился ошибкой NeuroAPI или провайдера, стоимость успешной генерации не списывается. При спорном списании сохраните время, модель и request id и обратитесь в поддержку.