Пока код не стал 200, в таблицу клиента я ничего не кладу.
Если пришли 201 или 202, следующий запрос делаю не сразу, а через паузу retryIn из ответа. Пока код не стал 200, строки в сводку не пишу. Боевой адрес держу в конфиге как api.direct.yandex.com/json/v501 и дальше имя сервиса. Для статистики это Reports. Тело, как и у остальных сервисов, содержит method и params. Обход у меня один: AgencyClients.get, затем для каждого логина отдельный Reports с заголовком Client-Login.
Колонки держу в одном шаблоне, иначе сводка разъезжается. Если нужны конверсии, в FieldNames одновременно указываю Goals и Conversions. Одна колонка без второй даёт успешный ответ без нужных чисел. Для денег ставлю returnMoneyInMicros в false, иначе суммы приходят в микроединицах. Период и тип отчёта тоже беру из шаблона.
Что я проверяю в выгрузке
Код 200 значит только, что интерфейс не отклонил операцию. Пустой список ошибок говорит о том же. Перед отправкой сверяю файл с кабинетом на знакомом срезе. В письмо не попадают ни токен, ни секрет приложения, ни заголовок Authorization.
Сначала логин и период, потом цели, деньги и остаток баллов.
- Сверяю Client-Login запроса с логином в шапке файла и с тем клиентом, которому уйдёт письмо.
- Проверяю период. Вчерашний день и скользящая неделя легко путаются, если подставился не тот шаблон.
- Смотрю, что колонки Goals и Conversions есть обе. Если в кабинете за этот период конверсии есть, в файле они тоже должны быть.
- Проверяю деньги. При returnMoneyInMicros false суммы читаются обычными единицами, а не микросуммами.
- Если перед отчётом я менял кампании, перечитываю поле State. Иначе в сводку попадает статус, которого уже нет.
- Сверяю одну знакомую кампанию с кабинетом. Расхождение по кликам или расходу — повод не отправлять файл, а повторить запрос.
- Смотрю заголовок Units. Если остаток тонкий, следующую пачку не запускаю, пока не решу, чьи баллы она съест.
В песочнице чеклист короче: одна кампания на отчёт и тестовые клиенты, а не боевые логины. Когда сверка на тесте сошлась, тот же набор полей переношу на боевой Client-Login. Так я ловлю пустые конверсии и микросуммы до того, как файл увидит клиент.
Где этот контур обычно ломается
- Заявка на API ещё не одобрена. Пока её нет, токен не заменяет доступ, даже если приложение в Яндекс ID уже создано.
- В токене нет scope direct:api или для паспортной организации нет passport:business.
- В запросе к данным клиента нет Client-Login, либо логин набран с опечаткой.
- AgencyClients вызван с Client-Login, хотя этот сервис как раз вызывается без него.
- Токен отозван или истёк, а скрипт продолжает слать старую схему Bearer.
- В FieldNames нет пары Goals и Conversions, и успешный код маскирует пустые конверсии.
- В очереди уже пять офлайн-отчётов, и новый запрос получает код 400.
Документацию держу на yandex.ru/dev/direct/doc/ru. Свой порядок короче: кампания и заявка, токен представителя, песочница, один Reports на одном Client-Login. После сверки файла включаю цикл AgencyClients.get по остальным логинам. Клиенту уходит сводка из проверенных колонок, а не из первого успешного кода.