HTTP-сервисы 1С — это способ сделать у информационной базы собственный REST API. В конфигураторе описывается сервис с корневым URL, внутри — шаблоны URL и HTTP-методы, у каждого метода — функция-обработчик, которая получает HTTPСервисЗапрос и возвращает HTTPСервисОтвет. После публикации базы на веб-сервере сервис доступен по адресу http://сервер/ИмяПубликации/hs/КорневойURL/Шаблон.
В статье соберём рабочий пример: список номенклатуры, продажи по ИНН контрагента и приём заказа методом POST. Потом опубликуем сервис и обратимся к нему из другой базы через HTTPСоединение. Код выложен целиком, с обработкой ошибок, которую я использую в реальных интеграциях.
HTTP-сервисы 1С или веб-сервисы: что выбрать
Платформа поддерживает два вида входящих интеграций:
| HTTP-сервисы (REST) | Веб-сервисы (SOAP) | |
|---|---|---|
| Формат | Любой, обычно JSON | XML по схеме |
| Описание контракта | Своё (документ, OpenAPI вручную) | WSDL генерирует платформа |
| Адресация | Свободные URL, методы GET/POST/PUT/DELETE | Одна точка входа, операции |
| Кому удобно | Сайты, мобильные приложения, сервисы на любых языках | Корпоративные системы с SOAP-стеком |
Для интеграции с сайтом, маркетплейсом, мобильным приложением или собственным сервисом на Python почти всегда выбирают HTTP-сервисы: их проще вызывать и отлаживать.
Создаём HTTP-сервис в конфигураторе
Возьмём типовую структуру: справочники Номенклатура и Контрагенты (с реквизитом ИНН), документ РеализацияТоваров с табличной частью Товары.
- В дереве метаданных: Общие → HTTP-сервисы → Добавить. Имя —
Каталог, корневой URL —catalog. - На вкладке «Шаблоны URL» добавьте шаблон
Товарысо строкой/products. - У шаблона добавьте метод
GET. - В поле «Обработчик» нажмите кнопку открытия — платформа создаст функцию в модуле сервиса. Имя по умолчанию складывается из имени шаблона и метода.
Корневой URL и шаблоны я пишу латиницей в нижнем регистре: так адрес не придётся кодировать, и внешние разработчики не спотыкаются о кириллицу.
Обработчик GET: отдаём JSON
В модуле сервиса держу только разбор запроса и сборку ответа. Работа с данными — в отдельном серверном общем модуле, чтобы её можно было вызывать и тестировать без HTTP.
Функция ТоварыGET(Запрос)
Попытка
Данные = ИнтеграцияКаталогСервер.СписокНоменклатуры();
Возврат ОтветJSON(200, Данные);
Исключение
ЗаписьЖурналаРегистрации("HTTPСервис.Каталог", УровеньЖурналаРегистрации.Ошибка, , ,
ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
Возврат ОтветJSON(500, Новый Структура("error", "Внутренняя ошибка сервиса"));
КонецПопытки;
КонецФункции
// Формирует ответ HTTP-сервиса с телом в формате JSON.
Функция ОтветJSON(КодСостояния, Данные)
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, Данные);
Ответ = Новый HTTPСервисОтвет(КодСостояния);
Ответ.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
Ответ.УстановитьТелоИзСтроки(ЗаписьJSON.Закрыть(), КодировкаТекста.UTF8,
ИспользованиеByteOrderMark.НеИспользовать);
Возврат Ответ;
КонецФункцииЯвно отключаю BOM: часть внешних парсеров JSON спотыкается о маркер в начале тела.
Функция общего модуля ИнтеграцияКаталогСервер:
// Возвращает массив структур с данными номенклатуры для выгрузки во внешние системы.
Функция СписокНоменклатуры() Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Артикул КАК Артикул,
| Номенклатура.Наименование КАК Наименование,
| ПРЕДСТАВЛЕНИЕ(Номенклатура.ВидНоменклатуры) КАК Вид,
| Номенклатура.Описание КАК Описание
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| НЕ Номенклатура.ПометкаУдаления";
Результат = Новый Массив;
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
// Новая структура на каждой итерации — иначе в массиве окажется одна и та же ссылка
Позиция = Новый Структура;
Позиция.Вставить("sku", Выборка.Артикул);
Позиция.Вставить("name", Выборка.Наименование);
Позиция.Вставить("type", Выборка.Вид);
Позиция.Вставить("description", Выборка.Описание);
Результат.Добавить(Позиция);
КонецЦикла;
Возврат Результат;
КонецФункцииЗаписатьJSON сериализует строки, числа, булево, даты, Неопределено, массивы, структуры и соответствия со строковыми ключами. Ссылки на объекты так не запишутся — отдавайте представление, код или Строка(Ссылка.УникальныйИдентификатор()).
Параметры URL и коды состояния
Добавим в сервис шаблон Продажи со строкой /sales/{inn} и методом GET. Сегмент в фигурных скобках — параметр: всё, что придёт после /sales/, окажется в Запрос.ПараметрыURL. Параметры после ? читаются из Запрос.ПараметрыЗапроса.
Функция ПродажиGET(Запрос)
ИНН = Запрос.ПараметрыURL.Получить("inn");
Если Не ЗначениеЗаполнено(ИНН) Тогда
Возврат ОтветJSON(400, Новый Структура("error", "Не указан ИНН контрагента"));
КонецЕсли;
Контрагент = Справочники.Контрагенты.НайтиПоРеквизиту("ИНН", ИНН);
Если Контрагент.Пустая() Тогда
Возврат ОтветJSON(404, Новый Структура("error", "Контрагент не найден"));
КонецЕсли;
// Необязательный параметр строки запроса: /sales/7700000000?from=2026-01-01
ДатаНачала = Дата(1, 1, 1);
СтрокаДаты = Запрос.ПараметрыЗапроса.Получить("from");
Если ЗначениеЗаполнено(СтрокаДаты) Тогда
Попытка
// Ожидаем ГГГГ-ММ-ДД, приводим к виду ГГГГММДД
ДатаНачала = Дата(СтрЗаменить(СтрокаДаты, "-", ""));
Исключение
Возврат ОтветJSON(400, Новый Структура("error", "Параметр from должен быть датой ГГГГ-ММ-ДД"));
КонецПопытки;
КонецЕсли;
Данные = ИнтеграцияКаталогСервер.ПродажиКонтрагента(Контрагент, ДатаНачала);
Возврат ОтветJSON(200, Данные);
КонецФункцииНекорректная дата не должна приводить к 500: ошибка во входных данных — это 400 с понятным текстом. Коды, которых хватает для большинства интеграций:
| Код | Когда возвращать |
|---|---|
| 200 | Всё хорошо, в теле данные |
| 201 | Объект создан (ответ на POST) |
| 400 | Некорректный запрос: нет параметра, битый JSON |
| 401 / 403 | Нет аутентификации / нет прав |
| 404 | Объект не найден |
| 409 | Конфликт, например дубль внешнего номера |
| 500 | Ошибка на стороне 1С, подробности — в журнал регистрации |
Приём данных методом POST
Для приёма заказа добавим шаблон /orders с методом POST. Тело читаем строкой и разбираем ПрочитатьJSON:
Функция ЗаказыPOST(Запрос)
ТелоЗапроса = Запрос.ПолучитьТелоКакСтроку();
Попытка
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(ТелоЗапроса);
ДанныеЗаказа = ПрочитатьJSON(ЧтениеJSON);
ЧтениеJSON.Закрыть();
Исключение
Возврат ОтветJSON(400, Новый Структура("error", "Тело запроса не является корректным JSON"));
КонецПопытки;
Если ТипЗнч(ДанныеЗаказа) <> Тип("Структура") Или Не ДанныеЗаказа.Свойство("externalId") Тогда
Возврат ОтветJSON(400, Новый Структура("error", "Не передан externalId"));
КонецЕсли;
Попытка
НомерЗаказа = ИнтеграцияКаталогСервер.СоздатьЗаказ(ДанныеЗаказа);
Исключение
ЗаписьЖурналаРегистрации("HTTPСервис.Каталог", УровеньЖурналаРегистрации.Ошибка, , ,
ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
Возврат ОтветJSON(500, Новый Структура("error", "Не удалось создать заказ"));
КонецПопытки;
Возврат ОтветJSON(201, Новый Структура("number", НомерЗаказа));
КонецФункцииПрочитатьJSON без второго параметра возвращает структуры. Если ключи могут быть не валидными идентификаторами 1С (с дефисами, цифрой в начале), передайте вторым параметром Истина и работайте с соответствием. Внешний идентификатор (externalId) нужен для идемпотентности: при повторной отправке того же заказа сервис должен найти существующий документ, а не создать дубль.
Публикация HTTP-сервиса на веб-сервере
Без публикации сервис не доступен снаружи. В конфигураторе: Администрирование → Публикация на веб-сервере. На закладке «HTTP сервисы» включите «Публиковать HTTP сервисы по умолчанию» или отметьте нужные сервисы по отдельности. В файле default.vrd публикации это выглядит так:
<point xmlns="http://v8.1c.ru/8.2/virtual-resource-system"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
base="/erp"
ib="Srvr="srv1c";Ref="erp";">
<httpServices publishByDefault="true"/>
</point>Проверка из командной строки:
curl -u integration:Secret123 http://srv/erp/hs/catalog/products
curl -u integration:Secret123 "http://srv/erp/hs/catalog/sales/7700000000?from=2026-01-01"Для интеграций заведите в базе отдельного пользователя с ролью, где есть только нужные права, и используйте HTTPS. Публикацию на Linux через Apache и утилиту webinst я разбирал в статье про установку сервера 1С на Ubuntu; настройку веб-доступа под ключ делаю в рамках услуги веб-доступ к 1С.
Обращение к HTTP-сервису из 1С
Для исходящих вызовов используются три объекта: HTTPСоединение (сервер, порт, учётные данные, таймаут, защищённое соединение), HTTPЗапрос (адрес ресурса, заголовки, тело) и HTTPОтвет (код, заголовки, тело ответа). Вызывать лучше на сервере: в веб-клиенте HTTPСоединение недоступно, а пароли не стоит держать на клиенте.
&НаСервереБезКонтекста
Функция ПолучитьТоварыИзУчетнойБазы(Пользователь, Пароль)
Таймаут = 30;
Соединение = Новый HTTPСоединение("erp.example.local", 443, Пользователь, Пароль, , Таймаут,
Новый ЗащищенноеСоединениеOpenSSL);
HTTPЗапрос = Новый HTTPЗапрос("/erp/hs/catalog/products");
HTTPЗапрос.Заголовки.Вставить("Accept", "application/json");
Ответ = Соединение.Получить(HTTPЗапрос);
ТелоОтвета = Ответ.ПолучитьТелоКакСтроку();
Если Ответ.КодСостояния <> 200 Тогда
ВызватьИсключение СтрШаблон("Сервис вернул код %1: %2", Ответ.КодСостояния, ТелоОтвета);
КонецЕсли;
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(ТелоОтвета);
Товары = ПрочитатьJSON(ЧтениеJSON);
ЧтениеJSON.Закрыть();
Возврат Товары;
КонецФункцииОтправка заказа методом POST:
&НаСервереБезКонтекста
Функция ОтправитьЗаказ(Соединение, ДанныеЗаказа)
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, ДанныеЗаказа);
HTTPЗапрос = Новый HTTPЗапрос("/erp/hs/catalog/orders");
HTTPЗапрос.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
HTTPЗапрос.УстановитьТелоИзСтроки(ЗаписьJSON.Закрыть(), КодировкаТекста.UTF8,
ИспользованиеByteOrderMark.НеИспользовать);
Ответ = Соединение.ОтправитьДляОбработки(HTTPЗапрос);
Возврат Ответ.КодСостояния = 201;
КонецФункцииBasic-аутентификацию можно передать параметрами Пользователь и Пароль конструктора HTTPСоединение — собирать заголовок Authorization вручную через Base64Строка не обязательно. Для универсальных методов есть ВызватьHTTPМетод("PATCH", HTTPЗапрос).
Типичные ошибки при разработке HTTP-сервисов
- Одна структура на весь массив. Структура создаётся до цикла, в цикле заполняется и добавляется в массив. В JSON получится N копий последней строки. Создавайте структуру внутри цикла.
- 404 на правильный адрес. Сервис не отмечен при публикации, база не переопубликована после добавления сервиса или ошибка в регистре корневого URL.
- Кракозябры в ответе. Не указана кодировка в
Content-Typeили вУстановитьТелоИзСтроки. - Ссылка в
ЗаписатьJSON. Ошибка сериализации: в структуре оказаласьСправочникСсылка. Отдавайте строки. - Исключение без обработки. Клиент получает 500 с HTML-страницей ошибки платформы. Ловите исключения, пишите их в журнал регистрации и возвращайте JSON с понятным текстом.
- Тяжёлые операции в обработчике. Если создание объекта занимает минуты, внешний клиент отвалится по таймауту. Принимайте данные, кладите в очередь (регистр сведений) и обрабатывайте фоновым заданием.
- Отсутствие идемпотентности. Повторная отправка создаёт дубли. Ищите объект по внешнему идентификатору.
HTTP-сервис — это контракт. Зафиксируйте адреса, форматы, коды ответов и правила повторной отправки до начала разработки, и интеграция переживёт обновления обеих сторон.
Когда обменов становится больше двух-трёх, отдельные HTTP-сервисы удобно дополнить очередью и мониторингом. Проектирую и делаю такие связки в рамках интеграции 1С по API и обмена между базами 1С.
Итог
- HTTP-сервис состоит из корневого URL, шаблонов и методов; обработчик получает
HTTPСервисЗапроси возвращаетHTTPСервисОтвет. - Параметры шаблона читаются из
ПараметрыURL, строки запроса — изПараметрыЗапроса, тело —ПолучитьТелоКакСтроку(). - Отдавайте JSON с правильным
Content-Type, осмысленными кодами состояния и без ссылок в данных. - Сервис начинает работать только после публикации базы с включёнными HTTP-сервисами; адрес —
/ИмяПубликации/hs/КорневойURL/Шаблон. - Исходящие вызовы делайте на сервере через
HTTPСоединение, с таймаутом, HTTPS и проверкой кода ответа.




