Я писал обработку, которая читает заказы интернет-магазина на InSales через API (программный интерфейс магазина) и показывает их в 1С. По дороге столкнулся с рядом подводных камней. Поведение магазина я, где мог, перепроверил запросами к тестовому магазину в сентябре 2026 года; то, что взято только из документации InSales, так и помечено.
Заказ, созданный вчера, за вчера не находится
Менеджер ищет вчерашний заказ, ставит период «вчера», а в выборке пусто. На сайте заказ есть и создан именно вчера.
Магазин отбирает заказы только по дате изменения. Метод GET /admin/orders.json отдаёт список заказов в JSON (текстовом формате данных), и для отбора по дате у него один параметр, updated_since. В справочнике у метода перечислены fulfillment_status, delivery_variant, payment_gateway_id, updated_since, from_id, per_page и page, отбора по дате создания среди них нет. Я пробовал передать created_at_min, created_since, updated_at_min и updated_at_max: ошибки магазин не вернул и отдал все заказы тестового магазина, будто параметров не было. Скорее всего, вчерашний заказ сегодня уже трогали, например перевели в другой статус. Дата изменения стала сегодняшней, и граница «по вчера» его отрезала.
Имена вне справочника ведут себя по-разному. created_at_from тот же магазин принял молча, но вернул пустой список, и count.json с этим параметром ответил {"count":0}. Дата в любом виде давала тот же пустой ответ, а значение, не похожее на дату, магазин пропускал мимо. Пустой ответ для обмена опаснее лишних заказов: он читается как «изменений нет», и заказы тихо не загрузятся.
В обработке поля периода так и называются: «Изменены с» и «Изменены по», а под ними подсказка о том, как магазин отбирает заказы. В списке есть обе даты, «Создан» и «Изменён». При широком периоде сразу видны заказы, которые создали давно, а трогали недавно.

Рисунок 1. Отбор заказов по дате изменения, под полями периода подсказка о нижней границе
Если обмену нужны заказы по дате создания, запрашивать их придётся по дате изменения с начала нужного периода: измениться раньше, чем его создали, заказ не может. Отбор по created_at потом делается на своей стороне, по уже полученным данным.
За прошлый месяц приходят и свежие заказы
Обмен просит заказы за август, а в 1С появляются ещё и сентябрьские.
Параметр updated_since задаёт только нижнюю границу. Магазин отдаёт всё, что изменилось начиная с этого момента и до текущей секунды. Верхней границы по дате у заказов нет ни в справочнике API, ни на деле: updated_at_max магазин пропускает мимо. Граница включительная: справочник пишет «updated after it», статья вендора говорит «больше либо равен», и запрос подтвердил статью. Заказ, изменённый ровно в момент границы, пришёл, а с границей на миллисекунду позже пропал.
Обработка отрезает верх сама. Она получает всё, что изменено с даты «Изменены с», и выбрасывает заказы, изменённые позже даты «Изменены по». При проверке узкий период дал ноль заказов.
В обмене верхнюю границу тоже придётся ставить самому. И помнить про объём: запрос за январь, отправленный в сентябре, вытянет всё, что менялось с января, а на живом магазине это много страниц.
Заказы первых часов периода не приходят
Со стороны это похоже на случайность. Период задан с полуночи, утренние заказы на месте, а изменённые между полуночью и тремя часами ночи пропали.
Причина в том, как часовой пояс попадает в адрес запроса. Статья вендора называет updated_since временем в UTC (всемирном координированном времени), в примере передаёт его со смещением +03:00 и просит правильно экранировать значение. Однако незакодированный плюс в строке запроса по правилам разбора веб-форм означает пробел. Магазин теряет пояс, считает время всемирным, и граница уезжает на три часа вперёд.
Я проверил это запросами. Границу взял по заказу из середины списка: 31.08.2026 23:10:07 по Москве. С незакодированным +03:00 магазин вернул 36 заказов, с %2B03:00 вернул 37. Разница в один заказ, потому что за эти три часа в тестовом магазине изменился только заказ, стоящий на самой границе. Время без пояса дало те же 36: его магазин тоже читает как всемирное. С +00:00 потеря плюса безвредна, потому что нулевой пояс и есть UTC. Так же верно сработали %2B00:00 и Z. Дата без времени, 2026-08-31, дала начало суток. А слипшаяся строка вроде 2026-08-31T20:10:0700:00 сняла отбор целиком, и пришла вся история магазина.
Обход простой: собрать границу со смещением и закодировать плюс. В 1С смещение считается как разница между местным и всемирным временем и дописывается к дате:
ЧасыСтрокой = Прав("0" + Строка(Часы), 2);
МинутыСтрокой = Прав("0" + Строка(Минуты), 2);
Возврат Формат(ДатаЛокальная, "ДФ=yyyy-MM-ddTHH:mm:ss") + Знак
+ ЧасыСтрокой + ":" + МинутыСтрокой;
Ведущий ноль дописывается вручную: форматная строка с ведущими нулями для нулевого значения даёт пустую строку, и смещение превращается в +03:.
Плюс кодируется там, где собирается путь запроса:
Путь = "/admin/orders.json?page=" + Формат(НомерСтраницы, "ЧГ=0")
+ "&per_page=" + Формат(РазмерСтраницы, "ЧГ=0");
Если ЗначениеЗаполнено(ИзмененыС) Тогда
Путь = Путь + "&updated_since="
+ СтрЗаменить(ГраницаПериодаДляЗапроса(ИзмененыС), "+", "%2B");
КонецЕсли;
Границу видно в протоколе запросов, в колонке «Путь». После времени должно стоять %2B03:00; +03:00 или отсутствие пояса означают потерю первых часов периода.

Рисунок 2. Протокол запросов: в пути граница updated_since с закодированным плюсом
В своём обмене я бы проверил две вещи: у границы есть смещение со знаком, а плюс уходит как %2B.
Заказы приходят по 25 при любом per_page
В обмене задано сто заказов на страницу, а приходит 25. Хуже, если цикл останавливается на странице короче заказанной. Так устроена, например, библиотека самого InSales для языка Ruby. Тогда обмен забирает первые 25 заказов, решает, что это всё, и спокойно завершается.
Двадцать пять приходит тогда, когда per_page до магазина не дошёл: имя написано с опечаткой, параметр потерялся при сборке адреса или его отрезала обёртка над HTTP. Значение по умолчанию в документации не указано, запрос показал 25. Максимум для заказов тоже не описан: на 84 заказах тестового магазина и per_page=250, и per_page=1000 вернули всё одной страницей, до предела я не дошёл. Статья вендора о запросах к API предупреждает, что запрос дольше 50 секунд сервер прерывает с кодом 504, так что огромные страницы лучше не заказывать.
Что размер доехал, видно в протоколе запросов по числу обращений: семь десятков заказов по сто на страницу дают два запроса, второй приходит пустым и останавливает загрузку (рисунок 2). Проигнорируй магазин размер, запросов было бы четыре.
После смены размера страницы стоит один раз посмотреть, сколько заказов пришло на первой.
Две характеристики слились в одну позицию
Покупатель заказал два фасада одной модели разного цвета, а в документе 1С одна строка с количеством два или две строки с одинаковой характеристикой.
Строку заказа с товаром магазина связывает пара product_id и variant_id. Первое число у всех вариантов одного товара общее, второе у каждого варианта своё. Если обмен ищет номенклатуру только по товару, варианты склеятся. Артикул и наименование на роль ключа не годятся: их заводят и меняют люди, а документация API не отмечает, какие поля ответа заполнены всегда. В моём тестовом магазине артикулы у вариантов разные, но это заслуга того, кто заводил товары. Значений опций варианта, цвета или размера, в строке заказа нет совсем. По справочнику API их отдаёт отдельный метод варианта товара в поле option_values.
В обработке на вкладке «Состав» есть колонка «Ключ сопоставления (товар / вариант)». В заказе 1002 тестового магазина два фасада одного товара: у обоих первое число 1885247385, а вторые разные, 2279823225 и 2279823793.

Рисунок 3. Состав заказа 1002: два фасада одного товара различаются вторым числом ключа
Если пишете обмен, держите связь с номенклатурой на обоих числах: по одному product_id характеристику не восстановить.
У заказа пустая доставка
Заказ с курьерской доставкой пришёл в 1С без строки доставки и без названия службы.
Название способа доставки магазин кладёт в поле верхнего уровня delivery_title. Рядом есть вложенный узел delivery_info со своим полем title, и искать название хочется именно там. Судя по составу узла (tariff_id, shipping_company, outlet), он рассчитан на службы доставки с собственным расчётом стоимости. Документация назначение узла не описывает: во всех её примерах delivery_info пуст, а delivery_title заполнен. В тестовом магазине таких служб нет, узел приходит заполненным наполовину: delivery_variant_id и price на месте, а название, shipping_company, shipping_company_handle и outlet пустые у всех заказов. Проверить предположение про службы с собственным расчётом стоимости я не смог.
Название берётся из верхнего уровня, и тогда по заказу 1002 видно «Самовывоз» со стоимостью 0, по заказу 1005 «Курьером» и 300,00.

Рисунок 4. Вкладка «Доставка» заказа 1005: служба «Курьером», стоимость 300,00, код службы и пункт выдачи пусты

Рисунок 5. Сырой ответ по заказу 1005: название способа доставки в поле delivery_title
В обмене название стоит брать из delivery_title. В моём тестовом магазине у самовывоза стоимость 0, и это нормальный ответ магазина. Судя по названиям полей, пункт выдачи и машинный код службы должны лежать в delivery_info.outlet и delivery_info.shipping_company_handle, но таких данных в моём магазине нет, и как они заполняются, я не проверял.
Сумма или цена стала нулём либо ошибкой
Загрузка падает на разборе числа, или в документе появляется нулевая цена у позиции, которая на сайте стоит денег.
Числа в ответе магазина приходят разными типами. В примере из справочника API у строки заказа sale_price пришёл числом, а вес в одной строке равен null, в соседней записан текстом "0.3". У заказа 1005 на рисунке 5 items_price число, а margin_amount строка "0.0". После ПрочитатьJSON значение null превращается в Неопределено, и арифметика с ним заканчивается ошибкой. Ноль появляется там, где разбор тихо проглатывает исключение.
В обработке этим занимается функция ЧислоИзОтвета. Число она возвращает как есть. Строку пробует преобразовать напрямую, а если не вышло, то ещё раз с запятой вместо точки. Вторая попытка оставлена как страховка:
Попытка
Возврат Число(Текст);
Исключение
КонецПопытки;
Попытка
Возврат Число(СтрЗаменить(Текст, ".", ","));
Исключение
Возврат 0;
КонецПопытки;
Для просмотра ноль при неудачном разборе допустим, потому что исходное значение всегда видно на вкладке «Сырой ответ». В обмене я бы так делать не стал: нечитаемая сумма заказа должна давать ошибку.
«Соединение не установлено» при живом интернете
Браузер на том же рабочем месте открывает сайт магазина, а 1С сообщает, что соединение не установлено. Или соединение есть, но магазин отвечает кодом ошибки.
Сначала стоит понять, с какой машины уходит запрос. В клиент-серверном режиме соединение по HTTP (протоколу, по которому 1С обращается к магазину) создаёт код на сервере 1С. Значит, доступ в интернет, прокси и разрешения сетевого экрана нужны на сервере. Свою обработку я проверял на платформе 8.5.1.1343 в обоих режимах: в клиент-серверном запросы к магазину отправлял рабочий процесс сервера. Вторая причина в безопасном режиме. Если внешнюю обработку подключили с ним, платформа запрещает исходящие соединения.
Когда магазин ответил, смотрите на код. Код 401 означает неверный идентификатор или пароль ключа доступа, 404 у меня возникал при неверном адресе магазина. Оба случая обработка расшифровывает словами, и оба я проверял прогоном. Код 403 обработка объясняет нехваткой прав ключа на запрошенные данные, но вживую такого ответа я не получал. Вендор к тому же предупреждает, что логин и пароль от панели администратора для работы с API использовать нельзя: аккаунт могут заблокировать.

Рисунок 6. Проверка связи с неверным паролем ключа: код 401 и его расшифровка
Код 429 означает исчерпанный лимит. По документации вендора на магазин приходится 500 запросов к API за 5 минут, окно отсчитывается от первого запроса серии. Сколько запросов уже потрачено, магазин сообщает в заголовке ответа API-Usage-Limit, например 1/500. После превышения доступ закрыт до конца окна, а заголовок Retry-After говорит, через сколько секунд он откроется. Остаток лимита обработка показывает в протоколе запросов.
Заказ подходит под период, но в выборку не попал
Обмен отработал без ошибок, заказ изменён в нужный период, а в 1С его нет.
С заданным updated_since магазин сортирует заказы по возрастанию даты изменения, а при равной дате по возрастанию идентификатора. Первое я проверил запросом, второе взял из статьи вендора. Пусть обмен листает список по страницам через page. Пока он разбирает первую страницу, менеджер меняет один из заказов на ней. Заказ уезжает в конец списка, все следующие сдвигаются на одну позицию вверх, и первый заказ второй страницы оказывается на первой, которую обмен уже забрал. Если обмен после загрузки запоминает, до какого момента дочитал, следующий запуск начнётся позже, и заказ не вернётся, пока его снова не изменят.
Вендор в статье о получении изменившихся данных предлагает листать иначе. Запрашивается всегда первая страница, а сдвигается фильтр: в updated_since подставляется дата изменения последнего заказа пачки, в from_id его идентификатор. Заказы с той же датой изменения и идентификатором не больше from_id магазин не повторяет, а без updated_since параметр from_id не действует. Я прошёл так шесть пачек по пять заказов: 30 заказов, повторов нет.
Моя обработка листает по page. Для ручного просмотра этого хватает: если заказ поменяли во время загрузки, достаточно загрузить период ещё раз. Для обмена, который работает сам по расписанию, я бы выбрал способ вендора.
Что ещё придётся решить, когда заказы поедут в 1С
Когда заказы читаются без потерь, появляются вопросы, на которые у каждой конфигурации и каждого магазина свой ответ:
- как опознать покупателя, который уже есть в базе;
- как сопоставить товар и вариант магазина с номенклатурой и характеристикой;
- что делать, когда уже загруженный заказ изменили на сайте;
- как отразить доставку и пункт выдачи;
- как согласовать статусы и оплату между сайтом и 1С;
- как возвращать на сайт остатки и цены.
Большую часть описанного я разглядывал в обработке «Просмотр заказов интернет-магазина InSales по API: обработка только для чтения (open-source)»: //infostart.ru/1c/tools/2791161/. Если при обмене с InSales вам попадались подводные камни, которых здесь нет, опишите их в комментариях.
Вступайте в нашу телеграмм-группу Инфостарт