Перейти к основному содержимому

Протокол интеграции 1С v1

Документ определяет внешний контракт версии v1 для двустороннего обмена между GoDeli и 1С. Транспортный протокол — HTTPS, формат тела запроса — JSON в кодировке UTF-8. В версии v1 экземпляр интеграции связывает одну торговую точку GoDeli с одним складом 1С.

Формулировки «должен» и «не должен» обозначают обязательные требования контракта. «Рекомендуется» обозначает требование, от которого допустимо отклониться при сохранении совместимости с описанным протоколом.

Термины​

ТерминОпределение
событиеидемпотентная единица входящего обмена с уникальным event_id
полный снимокполное состояние набора сущностей на момент generated_at
часть снимкаодин пакет составного товарного снимка
вариантединица продажи товара, включая характеристику номенклатуры 1С
внешняя ссылкастабильный идентификатор сущности в информационной базе 1С

Модель обмена​

Обмен от 1С к GoDeli состоит из четырёх логически независимых потоков:

  1. catalog-structure — полное дерево категорий;
  2. attribute-definitions — полный справочник атрибутов;
  3. catalog-snapshot — полный снимок товаров и вариантов, передаваемый частями;
  4. changes — оперативные цены и остатки.

Категории не определяют состав атрибутов. Определения атрибутов передаются отдельным потоком, а товар содержит значения со ссылками на стабильные attribute_id. Потоки не связываются общим идентификатором выгрузки и не требуют указания версий друг друга.

Рекомендуемый порядок первичной или ночной выгрузки: структура, справочник атрибутов, все части товарного снимка, затем оперативные изменения. Получение статуса applied перед отправкой следующего пакета не требуется. Ответ 202 Accepted подтверждает сохранение события в очереди GoDeli; обработка событий и разрешение зависимостей выполняются асинхронно.

Очередь изолирована от прикладного API GoDeli. Принятое событие не теряется при перезапуске обработчика или временной недоступности каталога. Доставка из очереди в каталог выполняется повторно до получения результата, а применение команды в каталоге идемпотентно по паре integration_id/event_id (для составного товарного снимка — по integration_id/snapshot_id). Поэтому сбой соединения после фактического применения не приводит к повторному изменению данных.

Авторизация и идемпотентность​

Во всех запросах 1С к GoDeli используется короткоживущий JWT, полученный по Workload Identity:

Authorization: Bearer <access_token>
Content-Type: application/json
Idempotency-Key: <event_id>

Значение Idempotency-Key должно совпадать с event_id в теле запроса. После транспортной ошибки 1С должна повторить запрос с неизменённым телом и тем же идентификатором. POST-методы возвращают 202 Accepted после сохранения события в персистентном входящем журнале:

{"event_id":"structure:event:42","status":"accepted"}

Повтор ранее сохранённого события возвращает status: "duplicate". Код 202 подтверждает приём, но не подтверждает применение данных к каталогу.

Дата и время передаются в формате ISO 8601 с обязательным указанием часового пояса. Поле generated_at обозначает момент формирования состояния данных в 1С, а не момент выполнения HTTP-запроса. Внешние идентификаторы представляют собой стабильные непрозрачные строки длиной до 128 символов; рекомендуется использовать GUID 1С. Отображаемое наименование не должно использоваться как идентификатор.

Дерево категорий​

POST /api/v1/integrations/1c/{integration_id}/catalog-structure
{
"event_id": "structure:event:2026-08-31",
"version_id": "structure:2026-08-31",
"generated_at": "2026-08-31T00:00:00Z",
"categories": [
{
"id": "category-root-guid",
"parent_id": null,
"code": "CATALOG",
"name": "Каталог",
"sort_order": 0,
"active": true
},
{
"id": "category-fruit-guid",
"parent_id": "category-root-guid",
"code": "FRUIT",
"name": "Фрукты",
"sort_order": 10,
"active": true
}
]
}

Запрос содержит полную версию дерева категорий. Поле version_id идентифицирует версию структуры и должно изменяться при формировании нового полного снимка. Дублирующиеся ID, ссылка на отсутствующего родителя и циклическая зависимость приводят к ответу 422 Unprocessable Entity. Порядок категорий в массиве не определяет порядок обхода дерева.

Справочник атрибутов​

POST /api/v1/integrations/1c/{integration_id}/attribute-definitions
{
"event_id": "attributes:event:2026-08-31",
"version_id": "attributes:2026-08-31",
"generated_at": "2026-08-31T00:00:00Z",
"definitions": [
{
"id": "attribute-brand-guid",
"code": "BRAND",
"name": "Производитель",
"type": "enum",
"unit": null,
"canonical_code": "brand",
"values": [
{"id": "brand-farm-guid", "code": "FARM", "name": "Ферма"}
]
},
{
"id": "attribute-country-guid",
"code": "COUNTRY",
"name": "Страна происхождения",
"type": "string",
"unit": null,
"canonical_code": "country_of_origin",
"values": []
}
]
}

Поле type принимает значения string, decimal, integer, boolean, date или enum. Один запрос может содержать не более 5000 определений. Для атрибута типа enum товар должен передавать value_id; для остальных типов используется поле value. Наименования атрибутов в разных информационных базах могут различаться. Сопоставление выполняется в области конкретной интеграции по стабильному внешнему ID, а не по наименованию.

Товарный снимок частями​

POST /api/v1/integrations/1c/{integration_id}/catalog-snapshot

Каждая часть обязана содержать:

ПолеОписание
event_idуникальный ID конкретной части
snapshot_idобщий ID всех частей
part_numberномер части от 1
total_partsобщее количество частей, 1–1000
generated_atвремя среза
productsтовары этой части

Одиночная выгрузка также должна содержать part_number: 1 и total_parts: 1. Поля structure_version_id и attribute_definitions_version_id контрактом не предусмотрены. Категории и определения атрибутов не включаются в товарный снимок. Формат без реквизитов разбиения на части не поддерживается.

Части допускается передавать в произвольном порядке. Значения snapshot_id, total_parts и generated_at должны совпадать во всех частях одного снимка. Каждая часть должна иметь отдельный event_id. Сочетание snapshot_id и part_number уникально в пределах интеграции. Каждый товар должен присутствовать ровно в одной части. GoDeli начинает применение товарного снимка только после получения полного набора частей.

Пример весового товара​

{
"event_id": "catalog:night-42:0002",
"snapshot_id": "catalog:night-42",
"part_number": 2,
"total_parts": 15,
"generated_at": "2026-08-31T00:05:00Z",
"products": [
{
"id": "product-apple-guid",
"name": "Яблоки",
"category_id": "category-fruit-guid",
"available": true,
"tax": {
"vat_rate": "10",
"vat_included": true,
"tax_category": "goods"
},
"marking": {
"required": false,
"group": null,
"traceable": false
},
"attributes": [
{"attribute_id": "attribute-brand-guid", "value_id": "brand-farm-guid"},
{"attribute_id": "attribute-country-guid", "value": "Россия"}
],
"option_axes": [],
"variants": [
{
"id": "apple-weight-guid",
"name": "Весовой",
"price": 249.90,
"sku": "APPLE-WEIGHT",
"default": true,
"measure_unit": "kilogram",
"measure_value": 1.000,
"weight": {
"minimum": 0.100,
"maximum": 5.000,
"step": 0.100,
"default": 1.000,
"allowed_deviation_percent": 10
}
}
],
"allergens": [],
"tags": ["fresh"]
}
]
}

Для весового варианта цена указывается за один килограмм, measure_unit должен иметь значение kilogram, а measure_value — 1. Значения minimum, maximum, step и default должны быть положительными; дополнительно выполняется условие minimum <= default <= maximum. Поддерживаемая точность — до 0,001 кг. Отсутствие объекта weight обозначает штучный или мерный невесовой вариант.

Товар должен содержать не менее одного варианта. Для номенклатуры без характеристик 1С должна формировать один вариант со стабильным идентификатором. При наличии характеристик option_axes определяет измерения матрицы вариантов, а option_values каждого варианта должно содержать ровно одно значение для каждого измерения.

Ставки НДС: none, 0, 5, 7, 10, 20, 105/5, 107/7, 110/10, 120/20. Категории предмета расчёта: goods, service, excise, marked_goods, agent_goods.

Оперативные изменения​

POST /api/v1/integrations/1c/{integration_id}/changes
{
"event_id": "changes:000000018452",
"generated_at": "2026-08-31T14:31:00+03:00",
"stocks": [
{
"product_id": "product-apple-guid",
"variant_id": "apple-weight-guid",
"warehouse_id": "warehouse-guid",
"available_quantity": 12.750
}
],
"prices": [
{
"product_id": "product-apple-guid",
"variant_id": "apple-weight-guid",
"price": 259.90
}
]
}

Метод передаёт фактическое состояние на момент generated_at, а не движения регистра накопления. Одно событие может содержать не более 5000 записей остатков и 5000 записей цен. Для весового варианта available_quantity указывается в килограммах с точностью до 0,001. Для штучного варианта значение задаётся в единицах продажи.

Статус события​

GET /api/v1/integrations/1c/{integration_id}/events/{event_id}

Метод возвращает один из статусов: accepted, waiting, processing, applied, applied_with_warnings, retry, failed. Поле waiting_reason содержит машиночитаемое или диагностическое описание отсутствующей зависимости. Статусы waiting и retry не требуют повторной отправки POST-запроса: событие находится в персистентной очереди GoDeli.

Для составного товарного снимка все его части переходят в итоговый статус только после атомарного применения объединённого снимка. До получения полного набора частей уже принятые части имеют статус waiting. Статус failed является терминальным и означает ошибку контракта либо данных, которую должен устранить интегратор; retry означает временную инфраструктурную ошибку, обрабатываемую GoDeli автоматически.

Ошибки и нагрузка​

HTTPДействие 1С
202событие сохранено; результат применения доступен через метод статуса
401обновить JWT или проверить workload client
404проверить окружение и идентификаторы
422устранить ошибку валидации; неизменённый запрос повторять не следует
429повторить с задержкой и учесть Retry-After
5xx или сетьповторить неизменённое событие с тем же ID

Для каталога объёмом 15 000 SKU рекомендуемый размер части составляет 500–2000 товаров; типичная выгрузка содержит 8–30 частей. Размер тела одного запроса не должен превышать 25 МБ. Оперативные изменения рекомендуется агрегировать по паре product_id/variant_id в течение окна 1–5 секунд, сохраняя последнее состояние.

Опциональный запуск полной выгрузки​

Основным режимом является инициируемая 1С выгрузка по расписанию. В качестве необязательного расширения 1С может предоставить следующий метод:

POST /godeli/v1/exports/full
Authorization: Bearer <1c_api_token>
Idempotency-Key: <request_id>

GoDeli отправит:

{
"request_id": "0191f66e-8525-7e06-9354-0b46311e85c7",
"requested_at": "2026-08-31T12:00:00Z",
"scopes": [
"catalog_structure",
"attribute_definitions",
"catalog_snapshot"
]
}

Получив запрос, 1С должна зарегистрировать задания выгрузки в собственной персистентной очереди и вернуть {"accepted":true,"request_id":"..."} без ожидания завершения экспорта. Повтор запроса с тем же request_id не должен создавать дополнительный набор заданий. Реализация метода не является обязательной и не влияет на плановую выгрузку, инициируемую 1С.

Заказы GoDeli → 1С​

Для приёма заказов 1С предоставляет идемпотентный метод POST /godeli/v1/orders. UUID заказа передаётся в Idempotency-Key. Повторный запрос с тем же UUID должен возвращать реквизиты ранее созданного документа без создания дубликата.

Пример запроса GoDeli в HTTP-сервис 1С:

POST https://onec.example.ru/godeli/v1/orders HTTP/1.1
Authorization: Bearer <1c_api_token>
Idempotency-Key: 01a05f80-1234-7890-abcd-1234567890ab
Content-Type: application/json
{
"id": "01a05f80-1234-7890-abcd-1234567890ab",
"number": "GD-1042",
"created_at": "2026-09-02T12:30:00+03:00",
"point_id": "01a05f59-8cbb-74e1-9d95-778f603f1fe4",
"type": "delivery",
"status": "confirmed",
"payment_method": "card_online",
"payment_status": "paid",
"currency": "RUB",
"subtotal": "610.77",
"delivery_fee": "150.00",
"total": "760.77",
"customer": {
"name": "Иван",
"phone": "+79990000000"
},
"delivery": {
"address": "г. Черкесск, ул. Ленина, 10",
"scheduled_for": null
},
"comment": "Позвонить перед доставкой",
"items": [
{
"product_id": "product-milk-guid",
"variant_id": "milk-1l-guid",
"name": "Молоко 1 л",
"quantity": "2",
"is_weighted": false,
"measure_unit": "piece",
"weight_state": "not_applicable",
"unit_price": "129.95",
"line_total": "259.90",
"modifiers": []
},
{
"product_id": "product-apple-guid",
"variant_id": "apple-weight-guid",
"name": "Яблоки",
"quantity": "1.350",
"is_weighted": true,
"measure_unit": "kilogram",
"weight_state": "estimated",
"unit_price": "259.90",
"line_total": "350.87",
"modifiers": []
}
]
}

Денежные величины и количество передаются десятичными строками, без потери точности при разборе JSON. product_id и variant_id содержат внешние идентификаторы, ранее переданные 1С в товарном снимке.

Для весовой позиции quantity содержит массу в единице measure_unit:

{
"product_id": "product-apple-guid",
"variant_id": "apple-weight-guid",
"name": "Яблоки",
"quantity": "1.350",
"is_weighted": true,
"measure_unit": "kilogram",
"weight_state": "estimated",
"unit_price": "259.90",
"line_total": "350.87",
"modifiers": []
}

Поле weight_state принимает значение estimated для предварительного веса, actual для веса, зафиксированного после комплектации, и not_applicable для невесовой позиции.

Успешный ответ 1С:

HTTP/1.1 200 OK
Content-Type: application/json
{
"accepted": true,
"order_id": "1c-order-document-guid",
"number": "ЗК-00001234"
}

order_id обязателен при accepted=true и должен однозначно идентифицировать созданный документ в 1С. Любой ответ не-2xx, тайм-аут, accepted=false либо успешный ответ без order_id считается неуспешной доставкой и повторяется GoDeli. Поэтому обработчик 1С обязан обеспечивать идемпотентность по значению Idempotency-Key.

Ограничения v1​

  • один склад на интеграцию;
  • дерево и справочник атрибутов передаются целиком;
  • удаление товара выполняется применением полного товарного снимка;
  • входящих статусов заказа из 1С пока нет;
  • бандлы в заказах пока не поддерживаются.