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

Интеграция GoDeli с 1С

Версия контракта: v1
Формат: HTTPS + JSON (UTF-8)
Префикс API GoDeli: /api/v1

Документ предназначен для разработчиков 1С и описывает первичную загрузку каталога, изменение цен и остатков, контроль обработки и передачу заказов.

1. Схема и направления обмена

входящие события
1С ── каталог/цены/остатки ─────────────► GoDeli API ─► inbox ─► каталог GoDeli
│ │
│ └─ 202 после сохранения

◄──────────────── заказы ────────────── GoDeli order outbox
исходящий API 1С
  • 1С сама отправляет полный каталог и оперативные изменения. GoDeli её не опрашивает.
  • GoDeli отправляет подтверждённые заказы в HTTP API на стороне 1С.
  • Временная недоступность одной стороны не должна приводить к потере данных: обе стороны используют устойчивые очереди и идемпотентные идентификаторы.
  • При первом подключении и раз в ночь отправляется полный снимок; днём — только изменившиеся цены и остатки.

Одна интеграция v1 соответствует одной торговой точке GoDeli и одному складу 1С.

2. Реквизиты подключения

GoDeli передаёт команде 1С:

ПараметрНазначение
base_urlадрес API GoDeli нужного окружения
integration_idUUID интеграции торговой точки
client_idидентификатор workload-клиента этой интеграции
client_secretсекрет workload-клиента; показывается один раз
token_urlendpoint получения короткоживущего JWT

Команда 1С передаёт GoDeli:

ПараметрНазначение
base_urlадрес HTTP-сервиса 1С
tokenсекрет запросов GoDeli → 1С
order_pathприём заказов, по умолчанию /godeli/v1/orders
timeout_secondsтаймаут, по умолчанию 10 секунд

3. Общие правила запросов 1С → GoDeli

Авторизация

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

Перед запросом 1С получает JWT по client_credentials, как описано в разделе Workload Identity. Постоянные exchange_token не поддерживаются. JWT относится только к указанным tenant, точке и integration_id; его нельзя передавать в URL или писать в логи.

Форматы

  • Дата и время — ISO 8601 с часовым поясом, предпочтительно UTC: 2026-08-21T11:30:00Z.
  • Деньги и количества — JSON number; GoDeli хранит их как decimal.
  • ID из 1С — непрозрачные строки до 128 символов. Рекомендуются стабильные GUID.
  • Отображаемое имя не является идентификатором и может меняться.

Идемпотентность

Каждый пакет получает уникальный event_id. Заголовок Idempotency-Key обязан совпадать с ним. При сетевой ошибке 1С повторяет то же тело с тем же event_id. GoDeli сохранит событие один раз и вернёт duplicate на повторы.

Запрещено использовать один event_id для разных тел: v1 считает это повтором и не сравнивает содержимое.

catalog:6f9619ff-8b86-d011-b42d-00cf4fc964ff
changes:1c-node:000000018452

Асинхронный приём

Новый пакет:

{"event_id":"changes:000000018452","status":"accepted"}

Повтор:

{"event_id":"changes:000000018452","status":"duplicate"}

Оба ответа имеют HTTP 202. Это означает, что пакет надёжно сохранён, но ещё не обязательно применён. После 202 его можно убрать из транспортной очереди 1С, а результат проверить endpoint статуса.

4. Полный снимок каталога

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

Снимок — полное состояние каталога точки, не порция. Категории и товары с внешними ID, отсутствующие в новом снимке, архивируются. Части одного снимка нельзя отправлять отдельными запросами.

Верхний уровень

ПолеТипОбязательноОграничение
event_idstringда1–128, уникален
generated_atdatetimeдавремя формирования в 1С
attribute_definitionsarrayнетдо 5000
categoriesarrayдаполный список
productsarrayдаполный список

Категория

{"id":"category-guid","name":"Напитки"}

id: 1–128 символов; name: 1–255. product.category_id должен ссылаться на категорию этого же снимка.

Дополнительные реквизиты

Названия свойств в магазинах могут отличаться. GoDeli связывает их не по имени, а по стабильному attribute_definitions[].id внутри интеграции.

{
"id":"property-brand-guid",
"code":"BRAND",
"name":"Торговая марка",
"type":"enum",
"canonical_code":"brand",
"unit":null,
"values":[{"id":"brand-acme-guid","code":"ACME","name":"ACME"}]
}
ПолеОбязательноОписание
idдаGUID определения, до 128
codeнетвнутренний код 1С, до 128
nameдаотображаемое имя, до 255
typeдаstring, decimal, integer, boolean, date, enum
unitнетединица, до 32
canonical_codeнетсогласованное системное назначение, до 64
valuesдля enumдопустимые значения

canonical_code не выводится из русского названия. Коды вроде brand, color, size задаются только после согласования. Enum-значение имеет собственный ID.

Скалярное значение товара:

{"attribute_id":"property-fat-guid","value":3.2,"unit":"%"}

Enum-значение:

{"attribute_id":"property-brand-guid","value_id":"brand-acme-guid"}

Каждый attribute_id должен находиться в определениях этого снимка. У записи должно быть value или value_id.

Товар

ПолеОбязательноОписание
idдаGUID номенклатуры, до 128
nameданаименование, до 255
descriptionнетописание
compositionнетсостав
category_idнетID категории
availableнетдоступность, default true
taxнетНДС и предмет расчёта
markingнетмаркировка
attributesнетзначения реквизитов, до 500
option_axesнетоси характеристик, до 20
variantsдаминимум один вариант
allergensнетмассив строк
tagsнетмассив строк

Для полного снимка явно передавайте все поддерживаемые поля, включая пустые. Это исключает неоднозначность между удалённым значением и временно не выгруженным.

НДС и маркировка

"tax":{"vat_rate":"20","vat_included":true,"tax_category":"goods"},
"marking":{"required":true,"group":"dairy","traceable":true}

vat_rate: none, 0, 5, 7, 10, 20, 105/5, 107/7, 110/10, 120/20. tax_category: goods, service, excise, marked_goods, agent_goods. vat_included=true означает, что цена включает НДС. marking.group — согласованный код группы до 64 символов.

Характеристики и варианты

option_axes задаёт ось и допустимые значения, а вариант выбирает ровно одно значение каждой оси.

"option_axes":[{
"id":"property-size-guid",
"code":"SIZE",
"name":"Размер",
"values":[
{"id":"size-m-guid","code":"M","name":"M"},
{"id":"size-l-guid","code":"L","name":"L"}
]
}],
"variants":[{
"id":"characteristic-m-guid",
"name":"M",
"price":1990.00,
"sku":"00001234-M",
"barcodes":["4601234567890"],
"default":true,
"measure_unit":"piece",
"measure_value":1,
"option_values":[
{"axis_id":"property-size-guid","value_id":"size-m-guid"}
],
"option_groups":[]
}]

Правила:

  • минимум один вариант; для товара без характеристик используется стабильный искусственный ID;
  • если осей нет, option_values пуст;
  • price >= 0, measure_value > 0, до 100 штрихкодов;
  • measure_unit: piece, gram, kilogram, milliliter, liter;
  • рекомендуется ровно один default=true.

option_groups описывает модификаторы: группа содержит id, name, required, min_select, max_select, options; опция — id, name, price_delta, необязательный sku, available.

Полный пример

{
"event_id":"catalog:2026-08-21T00:00:00Z",
"generated_at":"2026-08-21T00:00:00Z",
"attribute_definitions":[{
"id":"property-fat-guid","code":"FAT_PERCENTAGE","name":"Жирность",
"type":"decimal","unit":"%","canonical_code":"fat_percentage","values":[]
}],
"categories":[{"id":"category-milk-guid","name":"Молочные продукты"}],
"products":[{
"id":"product-milk-guid",
"name":"Молоко 3,2%",
"description":"Пастеризованное молоко",
"composition":"Молоко цельное",
"category_id":"category-milk-guid",
"available":true,
"tax":{"vat_rate":"10","vat_included":true,"tax_category":"marked_goods"},
"marking":{"required":true,"group":"dairy","traceable":true},
"attributes":[{"attribute_id":"property-fat-guid","value":3.2,"unit":"%"}],
"option_axes":[],
"variants":[{
"id":"product-milk-guid:default","name":"1 л","price":119.90,
"sku":"00001234","barcodes":["4601234567890"],"default":true,
"measure_unit":"liter","measure_value":1,
"option_values":[],"option_groups":[]
}],
"allergens":["milk"],
"tags":["refrigerated"]
}]
}

5. Изменения цен и остатков

POST /api/v1/integrations/1c/{integration_id}/changes

Передаётся итоговое состояние, а не движение регистра. В пакете допускается до 5000 остатков и до 5000 цен.

{
"event_id":"changes:000000018452",
"generated_at":"2026-08-21T14:31:00+03:00",
"stocks":[{
"product_id":"product-milk-guid",
"variant_id":"product-milk-guid:default",
"warehouse_id":"warehouse-guid",
"available_quantity":21
}],
"prices":[{
"product_id":"product-milk-guid",
"variant_id":"product-milk-guid:default",
"price":129.90
}]
}
  • Пара product/variant должна существовать после снимка.
  • Цена неотрицательна.
  • Остаток уже учитывает резерв по согласованному правилу 1С; отрицательное значение GoDeli приводит к нулевой доступности.
  • v1 хранит остаток в целых единицах. Дробный складской учёт требует расширения.
  • warehouse_id зарезервирован: v1 использует один склад на интеграцию.
  • Пакет применяется транзакционно: все строки или ни одна.
  • Первый changes отправляется только после успешного полного снимка.

Быстрые повторные изменения одного SKU рекомендуется объединять и отправлять последнее состояние.

6. Статус события

GET /api/v1/integrations/1c/{integration_id}/events/{event_id}
Authorization: Bearer <access_token>
{
"event_id":"changes:000000018452",
"event_type":"delta",
"status":"applied",
"attempts":1,
"received_at":"2026-08-21T11:31:01Z",
"processed_at":"2026-08-21T11:31:03Z",
"last_error":null
}
СтатусЗначениеДействие 1С
acceptedждёт обработкипроверить позже
processingобрабатываетсяпроверить позже
appliedполностью применёнзавершить контроль
retryGoDeli повторит обработкуразобрать ошибку, если постоянная
failedокончательная ошибкавмешательство оператора

При retry повторно отправлять пакет не нужно: он уже сохранён в GoDeli.

7. Ошибки и очередь 1С

HTTPЗначениеДействие
202сохранено/дубликатконтролировать статус
401неверные реквизитыостановить очередь, обновить токен
404событие не найденопроверить окружение и ID
422неверный контрактисправить данные до повтора
429ограничение частотыповторить с задержкой, учесть Retry-After
5xxвременная ошибкаповторить то же событие

Доменная ошибка:

{"error":{"code":"validation_error","message":"Idempotency-Key must equal event_id"}}

Ошибка структуры JSON возвращает стандартный FastAPI 422 с массивом detail.

Алгоритм очереди 1С:

  1. Сформировать неизменяемое тело и новый event ID.
  2. Сохранить его в регистре/очереди до HTTP-вызова.
  3. При 202 завершить транспортную доставку.
  4. При сети, 429, 5xx повторять то же тело через 5, 15, 30, 60, 120 секунд, затем раз в 5 минут.
  5. При 401/422 прекратить автоматические повторы и создать диагностику.
  6. Проверять статус до applied.

8. Ночная сверка

1С формирует консистентный полный срез, отправляет один snapshot и ждёт applied. Изменения, возникшие во время формирования, сохраняются и отправляются после снимка. Иначе старый снимок может временно перезаписать новую цену.

9. Нагрузка: 15 000 SKU

15 000 SKU подходят для событийной схемы: полная нагрузка возникает ночью, днём передаются только изменения.

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

  • HTTP body на текущем ingress — не более 25 МБ;
  • snapshot нельзя разбивать на независимые запросы;
  • gzip нельзя считать поддержанным без проверки окружения;
  • delta: максимум 5000 остатков + 5000 цен.

До запуска нужно сформировать реальный UTF-8 JSON на 15 000 SKU и измерить его. Если размер приближается к 25 МБ, сначала реализуется составной снимок с snapshot_id, номерами частей и финализацией.

Для delta рекомендуется debounce 1–5 секунд, объединение по product/variant и пакеты по 500–2000 реально изменившихся строк.

10. Заказы GoDeli → 1С

Health check

GET /godeli/v1/health
Authorization: Bearer <1c_api_token>

Любой 2xx означает доступность. Рекомендуемый ответ: {"status":"ok"}.

Приём заказа

POST /godeli/v1/orders
Authorization: Bearer <1c_api_token>
Content-Type: application/json
Idempotency-Key: <godeli_order_uuid>
{
"id":"0191f66e-8525-7e06-9354-0b46311e85c7",
"number":"DL-10482",
"created_at":"2026-08-21T14:42:10+03:00",
"point_id":"0191f61f-b386-79e2-a6aa-80fa80cf01cb",
"type":"delivery",
"status":"confirmed",
"payment_method":"card_online",
"payment_status":"paid",
"currency":"RUB",
"subtotal":"389.70",
"delivery_fee":"99.00",
"total":"488.70",
"customer":{"name":"Иван","phone":"+79990000000"},
"delivery":{"address":"Москва, ул. Примерная, 1","scheduled_for":null},
"comment":"Позвонить за 5 минут",
"items":[{
"product_id":"product-milk-guid",
"variant_id":"product-milk-guid:default",
"name":"Молоко 3,2%",
"quantity":"3",
"unit_price":"129.90",
"line_total":"389.70",
"modifiers":[]
}]
}

Перечисления:

  • type: delivery, pickup;
  • штатный status: confirmed;
  • payment_method: cash, card_offline, card_online, sbp, null;
  • payment_status: pending, paid, refunded, failed.

Деньги и количества — decimal-строки. ID товара, варианта и модификатора — ID 1С из снимка.

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

{"accepted":true,"order_id":"1c-order-document-guid","number":"ЗК-00001234"}

При accepted=true обязателен order_id. Повтор с тем же Idempotency-Key возвращает ранее созданный документ, не создавая новый. UUID GoDeli рекомендуется сделать уникальным в базе 1С в рамках интеграции.

Ответ 1СПоведение GoDeli
2xx, принят и есть order_idзаказ принят
2xx, accepted=falseотклонён
принят без order_idошибка контракта, повтор
4xx, 5xx, таймаутповтор через outbox с тем же UUID

В v1 бандлы в заказе не поддерживаются; обычные позиции и модификаторы поддерживаются.

11. Безопасность

  • Только HTTPS; разные токены для test/prod и для двух направлений.
  • Секреты хранятся защищённо и маскируются в логах.
  • После согласованной ротации старый токен недействителен.
  • Персональные данные заказа не логируются целиком.
  • IP-фильтр допустим как дополнительная мера, но не заменяет Bearer-токен.

12. Приёмка

  1. Snapshot создаёт категории, товары, свойства и варианты.
  2. Повтор с тем же event ID возвращает duplicate без дублей.
  3. Новый snapshot обновляет товар и архивирует отсутствующий.
  4. Одинаковые имена с разными GUID не склеиваются.
  5. Delta меняет цену и остаток нужного варианта.
  6. Delta с неизвестным вариантом не применяется частично и получает retry.
  7. После 5xx 1С повторяет тот же event ID.
  8. Неверный токен даёт 401, неверный JSON — 422.
  9. Реальный snapshot 15 000 SKU укладывается в 25 МБ.
  10. Несколько HTTP-попыток заказа создают один документ 1С.
  11. Недоступность 1С не мешает входящему каталогу и не теряет заказ.

13. Ограничения v1

  • один склад на интеграцию;
  • нет multipart snapshot и дробного остатка;
  • удаление товара выполняется полным snapshot, не delta;
  • нет входящих статусов заказа из 1С;
  • нет заказов с бандлами;
  • устаревшие delta по generated_at автоматически не отбрасываются: очередь 1С должна сохранять причинный порядок.

14. Что согласовать до разработки

  • тестовые URL, integration ID и токены;
  • GUID склада, организации и типа цен;
  • правило расчёта доступного остатка и резерва;
  • НДС, предмет расчёта и группы маркировки;
  • canonical_code важных реквизитов;
  • ID варианта для товара без характеристик;
  • расписание snapshot и допустимую задержку delta;
  • контакты дежурных и передачу диагностического event ID.