Skip to main content

Обзор API

API запроса логов возвращает подробную запись каждого API-вызова, выполненного в рамках вашей учётной записи, включая использованную модель, фактически списанную сумму, задержку, был ли вызов выполнен с потоковой передачей, и код ошибки, если вызов завершается ошибкой. Он дополняет API запроса баланса: запрос баланса показывает, сколько кредита осталось, а запрос логов — куда он ушёл. Три типичных сценария использования:

Автоматическая сверка

Суммируйте фактические расходы по временному диапазону или по модели и сверяйте их с собственной тарификацией

Самостоятельная диагностика

Проверяйте коды ошибок в неудачных запросах, чтобы отличать проблемы с параметрами от проблем на стороне upstream

Обращения в поддержку

Передайте request_id в поддержку, чтобы они могли точно определить вызов
Журналы также доступны для просмотра в консоли на странице Logs. Этот API — программная точка входа к тем же данным, предназначенная для автоматической сверки, запланированного экспорта или передачи в вашу систему мониторинга. Для ручного просмотра используйте консоль — см. Как посмотреть мои записи вызовов.
Рекомендуемое использование: синхронизируйте данные раз в день и храните журналы в собственной базе данных.Этот API предназначен для запланированного инкрементального экспорта, а не для повторяющихся запросов в реальном времени:
  • Запускайте его раз в день, выбирая только записи, созданные с момента последней синхронизации, в свою базу данных или CSV-файл
  • Запрашивайте больше за один запрос: pageSize может достигать 5000 — не оставляйте его значением по умолчанию 10. См. ниже примечания к параметрам, чтобы избежать этого подводного камня
  • Не используйте его для массовой догрузки исторических данных (например, выгрузки трёх месяцев за один раз) и не используйте его для live-пагинации в UI
  • Не вызывайте его параллельно — переходите по страницам последовательно, делая между ними паузу примерно в одну секунду
  • Ограничивайте каждый временной интервал одним днём или меньше; для аккаунтов с большим объёмом разбивайте по часам
См. раздел «Примечания по производительности» ниже, чтобы понять почему: чем старее окно и чем глубже пагинация, тем дороже обходится каждый запрос. После превышения серверного лимита вы получите ошибку, и повторная попытка с теми же параметрами не будет быстрее. Пример на Python на этой странице уже следует этой схеме, и его можно сразу встроить в ежедневную cron-задачу.

Как получить ваш System Token

Log Query API выполняет аутентификацию с помощью System Token, который не является тем же самым, что и API key (см. Важные примечания в конце этой страницы).
1

Открыть консоль

Перейдите на api.apiyi.com/account/profile, чтобы открыть страницу вашего профиля
2

Найдите System Token

Найдите раздел «Account Options - System Token» в нижней части страницы
3

Сгенерируйте AccessToken

Введите пароль своей учетной записи, чтобы получить AccessToken, который можно использовать для последующих запросов к API
Получить System Token

Информация об API

Сведения о запросе

Заголовки запроса

Параметры запроса

Считайте временное окно обязательным.Этот эндпоинт на самом деле не требует соблюдения этих двух параметров — запрос без них выполнится успешно. Но если их опустить, сервер начнет искать по всей истории вашего аккаунта в обратном направлении от самой новой записи, и учетные записи с большой историей вызовов упрутся в серверный лимит и получат ошибку вместо медленного ответа.Это самая легкая ошибка на этой странице и та, у которой самые прямые последствия. Мы помечаем его как обязательное не потому, что сервер отклоняет запрос, а потому, что режим сбоя сложно распознать: он не сообщает об отсутствии параметра, он сообщает о тайм-ауте.
pageSize — единственный параметр в camelCase на этом эндпоинте. Написание его как page_size будет молча проигнорировано.Все остальные параметры (model_name, token_name, start_timestamp, request_id, …) используют snake_case — этот нет. Если указать его неправильно, ошибка не возникнет: сервер считает параметр отсутствующим и вернется к значению по умолчанию — 10 записей на страницу, что легко можно принять за «лимит — 10» или «за этот период я сделал только 10 вызовов».
Превышение 5000 действительно вызывает явную ошибку вместо молчаливого усечения.
Увеличение pageSize — самая эффективная оптимизация для этого эндпоинта. При 10 записях на страницу аккаунту, выполняющему 500,000 вызовов в день, потребуется 50,000 запросов; при 5000 на страницу — 100. Это на два порядка меньше запросов, и смещение пагинации уменьшается вместе с ним — см. Примечания по производительности ниже.Страница на 5000 записей имеет размер примерно 700 KB в gzip и обрабатывается примерно за 2,5 секунды. Если пропускная способность или память ограничены, 1000 — удобный компромисс.

Примечания по производительности

Стоимость одного запроса не фиксирована. Она зависит от трёх факторов. Следуйте этим правилам, и API будет работать быстро; проигнорируйте их, и вы упрётесь в серверный лимит запроса в 60 секунд и получите ошибку. Четыре практических правила:
  1. Всегда передавайте start_timestamp и end_timestamp. Не указывать окно — самый дорогостоящий способ вызвать этот API.
  2. Увеличьте pageSize. Это самый простой пункт: переход от 10 к 1000–5000 записей на страницу сокращает число запросов на два порядка, а вместе с ним падает и смещение.
  3. Сужайте окно вместо того, чтобы углублять смещение. Платите вы не за «какая это страница», а за «сколько записей было пропущено, чтобы до неё дойти», и этот показатель растёт сверхлинейно. Вместо того чтобы проходить всё большое окно постранично, разбейте его на 24 часовых окна, чтобы каждое окно снова начиналось со смещения 0.
  4. Один раз выгрузите историю, сохраните её, а затем синхронизируйте только приращения. Старые данные обходятся намного дороже при запросе, чем недавние, поэтому повторное чтение одной и той же истории — это чистая трата ресурсов.
Если одно окно всё ещё занимает десятки страниц при pageSize=1000, объём вызовов для этого периода высокий — разбейте окно пополам и запросите каждую половину отдельно. Это намного быстрее, чем уходить глубже по страницам. Константа MAX_PAGES в примере на Python ниже делает именно это.

60 секунд — это жёсткий лимит, и его превышение возвращает ошибку

Сервер ограничивает любой отдельный запрос 60 секундами. После этого вы не получаете медленный ответ — вы получаете ошибку, а уже затраченное время не даёт вам никаких данных. С высокой вероятностью его вызовут эти три сценария. Избегайте их сразу, а не повторяйте запрос и надеетесь на удачу: Повторная попытка с теми же параметрами не будет быстрее, она просто съест ещё 60 секунд. Правильная реакция — сузить временное окно или увеличить pageSize, чтобы было меньше постраничной навигации — в любом случае дайте серверу меньше данных на обработку за один вызов.

Типы журналов

Всегда передавайте type=2 при расчёте расходов. Без него также возвращаются записи о пополнениях и системных начислениях. Их quota равно 0, но model_name и token_name также пусты, поэтому простое суммирование или группировка по модели приведёт к неверным результатам.Если аккаунт использует асинхронные модели видео (Seedance и аналогичные), также запрашивайте type=11: при сбое задачи её предварительное списание возвращается в виде отрицательной записи о возврате, и суммирование только type=2 засчитает это предварительное списание как расход.

Детали ответа

Пример успешного ответа

Ключевые поля ответа

Поле other содержит строку JSON, а не вложенный объект, поэтому требуется повторный разбор (json.loads() в Python, JSON.parse() в JavaScript). Оно содержит billing_type, request_path (фактически вызванный эндпоинт), group_ratio, model_ratio и usage.Записи о расчётах для асинхронных задач генерации видео также содержат final_quota (итоговую сумму задачи), original_quota (авансовое списание при отправке), adjustment_quota (разницу для этой записи) и actual_tokens; см. раздел FAQ ниже.

Конвертация квоты

Правило конвертации

500,000 квоты = $1.00 USD
Формула: сумма в USD = quota ÷ 500,000 Примеры:
  • quota: 7500 → $0.015 USD
  • quota: 22500 → $0.045 USD
  • quota: 18 → $0.000036 USD
Это та же конвертация, которая используется API запроса баланса, поэтому результаты напрямую совпадают.

Сообщения об ошибках

HTTP 401 - Сбой аутентификации

Причина: system token недействителен или истёк, либо API key, начинающийся с sk-, был по ошибке использован как system token. Решение: Перегенерируйте system token в консоли и убедитесь, что Authorization содержит необработанное значение без префикса Bearer.

Примеры кода

Пример cURL (одна страница, быстрая проверка)

Опция --compressed обязательна, потому что API возвращает содержимое, сжатое gzip. Без неё вы получите нечитаемый вывод.
Используйте это, чтобы убедиться, что ваш token работает. Для реальной сверки используйте приведённый ниже ежедневный скрипт синхронизации.

Пример на Python: ежедневная инкрементальная синхронизация (готово для использования как задание cron)

Это рекомендуемый стандартный способ использования: запускайте его раз в день, получайте только то, что появилось с момента последней синхронизации, и записывайте это в локальную базу данных SQLite. Повторный запуск безопасен (записи дедуплицируются по request_id), а выполнение, прерванное на середине, возобновляется с места остановки.
Пример вывода:
Когда данные уже локально, любой нужный вам разбор — по модели, по дню, по token — выполняется на основе вашей собственной базы данных, так что вам больше никогда не придется запрашивать для этого API. Это намного быстрее, и это позволяет обойти проблему, когда нужны данные, которые уже вышли за пределы окна хранения.

Пример на Node.js (одно временное окно)

Та же идея: разбивайте по часам, последовательно обрабатывайте страницы и уменьшайте окно, если пагинация становится слишком глубокой.
И библиотека requests для Python, и fetch API в Node.js автоматически распаковывают gzip, так что дополнительная настройка там не нужна. Только curl требует явного флага --compressed.

Распространённые сценарии

Ежедневная сверка (рекомендуемый подход)

Настройте запуск приведённого выше Python-скрипта раз в день и сохраняйте журналы в локальную базу данных. Любую нужную вам детализацию — общие расходы, по модели, по token — затем можно получить с помощью SQL-запроса к вашей собственной базе данных. Есть три причины, почему это правильный вариант: локальные запросы выполняются быстро; вы не зависите от окна хранения журналов; и вы избегаете замедления API из-за повторного чтения старой истории. Чтобы синхронизировать записи только одной модели, добавьте параметр model_name в запрос.

Поиск неудачных вызовов

Когда данные находятся локально, выполняйте запрос непосредственно к своей таблице:
Запросы, отклонённые шлюзом (неверные параметры и тому подобное), имеют quota равный 0 и не тарифицируются. error_code в журнале позволяет вам отделить «вызов завершился с ошибкой» от «вызов завершился успешно, но мне не понравился результат».

Предоставление request ID для поддержки

Найдите проблемный вызов в журналах и передайте поддержке request_id. Это идентифицирует точный запрос end to end, что гораздо эффективнее, чем описывать «вызов к какой-то модели завершился с ошибкой примерно в определённое время».

Часто задаваемые вопросы

Сначала проверьте эти три пункта; почти каждый медленный запрос связан с одним из них:
  1. Передаёте ли вы start_timestamp и end_timestamp? Пропуск временного окна — самый затратный способ вызвать этот API: сервер выполняет поиск по всей вашей истории.
  2. Окно слишком старое или слишком широкое? Запрос данных месячной давности обходится значительно дороже, чем запрос данных за вчера. Сохраняйте диапазон менее одного дня, а при больших объёмах разбивайте его по часам.
  3. Достигло ли p нескольких тысяч? Стоимость пагинации растёт сверхлинейно. Решение — сузить временное окно так, чтобы для каждого окна требовалось лишь несколько десятков страниц, а не углублять пагинацию в рамках одного большого окна.
Повторная попытка с теми же параметрами не будет быстрее. При тайм-ауте скорректируйте параметры, как описано выше, вместо повторения идентичного запроса: обычная повторная попытка лишь заставит вас снова ждать.
В девяти случаях из десяти параметр был записан как page_size в snake_case.Правильное написание — camelCase pageSize. Это единственный параметр camelCase в этом эндпоинте: все остальные (model_name, token_name, start_timestamp, …) используют snake_case, поэтому здесь легко ошибиться. Ошибка не возникает: сервер считает параметр отсутствующим и использует 10 записей на страницу по умолчанию.
Максимальное значение — 5000, а при превышении возвращается понятная ошибка. При больших объёмах вам всё равно нужно использовать пагинацию (p=0, p=1, …), пока ответ не вернёт пустой массив: примеры на Python и Node.js выше уже включают эту логику.
Да — передайте request_id, и будет возвращена только эта запись:
При исследовании одного конкретного вызова это значительно быстрее, чем загружать временной диапазон и самостоятельно фильтровать его.
Нет. Некоторые поля содержат внутреннюю информацию платформы и пусты или равны нулю с точки зрения обычного аккаунта. Это ожидаемо и не влияет на поля, необходимые для сверки или устранения неполадок: quota, model_name, error_code и request_id всегда полностью заполнены.
API возвращает идентификатор группы, а консоль отображает метку группы. Они могут различаться: например, API возвращает default, а консоль показывает «По умолчанию».Полное сопоставление доступно в публичном эндпоинте https://api.apiyi.com/api/pricing в поле usable_group, которое сопоставляет идентификатор с меткой. Если вы хотите, чтобы ваши отчёты совпадали с консолью, примените это сопоставление самостоятельно.
Используйте quota. Это сумма, фактически списанная за вызов, и единственное поле, подходящее для сверки. Для моделей с ценой за вызов, таких как генерация изображений и генерация видео, количество tokens в ответе может быть значением-заполнителем, не участвующим в тарификации — такие модели передают by_count в other.billing_type.
Проектируйте логику синхронизации, исходя из того, что доступны для запроса только последние 30 дней.На практике доступный для запроса диапазон обычно больше, но мы не даём никаких гарантий по сроку хранения: он меняется в зависимости от политики очистки журналов, и такие изменения отдельно не объявляются. Считайте 30 дней минимальным ориентиром для планирования, и ваша сверка не сломается при изменении этой политики.Кроме того, чем старее окно, тем дороже запрос: даже если данные всё ещё существуют, получить их значительно медленнее.Поэтому правильный подход — синхронизировать данные раз в день в собственную базу данных и выполнять исторический анализ локально. Всё, что необходимо хранить в долгосрочной перспективе, архивируйте самостоятельно — не полагайтесь на этот API для последующего получения этих данных.
Причина: API возвращает содержимое, сжатое gzip (Content-Encoding: gzip), а curl не распаковывает его.Решение: добавьте флаг --compressed:
Библиотека requests для Python и API fetch в Node.js распаковывают данные автоматически.
Асинхронные задачи генерации видео (Seedance и аналогичные) тарифицируются по принципу «предварительное списание при отправке, расчёт разницы после завершения», поэтому одно видео оставляет две записи: предварительное списание (completion_tokens равно 0, присутствует request_id) и расчёт (completion_tokens — фактическое использование, request_id пусто, quota — только разница). Ни одна из записей не содержит task_id, поэтому этот API не может сопоставить записи с задачами.Чтобы узнать фактическую стоимость видео, запросите API задач по task_id; его quota — это сумма двух записей:
Обратите внимание: параметры пагинации используют snake_case page_size, при этом p начинается с 1, в отличие от этого API. Неудачная задача всё равно показывает предварительное списание в quota, но её фактическая стоимость равна 0 (журналы содержат отрицательную запись возврата type=11). Подробное руководство: Как узнать фактическую стоимость видео Seedance по task_id.
Нет. Эндпоинт запроса журналов не расходует квоту.

Важные примечания

System token — это не API-ключ, и эти два понятия не взаимозаменяемы
  • API-ключ (начинается с sk-) предназначен для /v1/* эндпоинтов inference. При использовании с /api/log/self возвращает 401.
  • System token (обычная строка без префикса) предназначен для /api/* эндпоинтов управления. При использовании с /v1/chat/completions возвращает ошибку invalid-token.
Область действия system token охватывает всю вашу учетную запись, поэтому относитесь к нему как к паролю от учетной записи: храните его в secret manager, а не в коде, никогда не коммитьте его в репозиторий и периодически меняйте его.
Ответы логов содержат ваши собственные API-ключи в открытом видеКаждая запись лога содержит информацию о token, который сделал вызов. Не вставляйте необработанные ответы логов в публичные места, не делитесь их скриншотами и не передавайте их третьим лицам — удаляйте конфиденциальные поля перед экспортом.Обратите внимание, что этот открытый текст не содержит префикс sk-, поэтому обычные сканеры секретов могут его не обнаружить. Не полагайтесь на автоматические проверки, чтобы они нашли его за вас.
Рекомендуемый шаблон вызовов
  • Синхронизируйте один раз в день — чаще не нужно; каждый запуск загружает только новое
  • Используйте pageSize в размере 1000–5000, а не значение по умолчанию 10 — это важнее всего остального вместе взятого
  • Вызывайте последовательно, примерно с интервалом в одну секунду между страницами, никогда не параллельно
  • Установите тайм-аут клиента на 60 секунд (ограничение запроса на стороне сервера тоже составляет 60 секунд)
  • Ограничивайте каждый временной интервал одним днем или меньше; для аккаунтов с большим объемом данных разбивайте по часам
  • При тайм-ауте уменьшите окно перед повторной попыткой — идентичная повторная попытка не будет быстрее
Это не жесткие квоты; это просто самый быстрый способ выгрузить ваши собственные данные. При соблюдении этого шаблона типичный аккаунт синхронизирует полный день логов менее чем за минуту, а даже для нагруженного аккаунта, выполняющего сотни тысяч вызовов в день, требуется всего около сотни запросов.
Мы оставляем за собой право в будущем ввести rate limiting на этом эндпоинте.Сегодня на нем нет rate limit, но, пожалуйста, не проектируйте свои запланированные задания вокруг «безлимитности». Следуйте приведенному выше шаблону — один раз в день, последовательно, большой pageSize — и будущий rate limit не повлияет на вас.

Связанная документация