OPTORA · B2B · Поставщик

Инструкция для разработчика 1С

Публичная документация API интеграции OPTORA для оптовых поставщиков. Можно отправить программисту 1С — вход в кабинет не требуется. API-ключ поставщик получает сам в кабинете после авторизации.

Кабинет поставщика

Документ для программиста 1С:Предприятие (или другой учётной системы) поставщика OPTORA. Интеграция необязательна — без неё можно работать через веб-кабинет.

Главный принцип — ваш каталог из 1С: OPTORA не передаёт вам свои товары и не отдаёт каталог для импорта в 1С. Вы сами выгружаете из 1С свою номенклатуру (название, цена, остаток, штрихкод) — эти позиции появляются в каталоге поставщика на OPTORA, и с ними работают магазины. Заказы магазинов 1С забирает через GET /orders/.
Технически: все запросы инициирует ваша система (1С → OPTORA). OPTORA не подключается к вашему серверу. Достаточно исходящего HTTPS и API-ключа из кабинета.

1. Что нужно перед началом

  1. Владелец кабинета поставщика заходит в Интеграция → вкладка «1С», нажимает «Сгенерировать ключ» и «Включить».
  2. Передайте программисту: API-ключ, базовый URL https://optora.kz/supplier-api и эту инструкцию.
  3. В 1С настройте регламентное задание (или несколько) для обмена по HTTPS.
  4. Рекомендуется завести в 1С регистр сведений «Соответствие номенклатуры OPTORA» с полями: код 1С, external_id, штрихкод, ID заказа OPTORA.

2. Архитектура обмена

Каталог — только из 1С в OPTORA. Метода «получить список товаров OPTORA» или «скачать каталог платформы» в API нет. Вы выгружаете то, что продаёте сами; магазины видят именно ваш прайс.

1С: ваша номенклатура POST /products/sync/ Каталог поставщика на OPTORA Магазины заказывают
1С: остатки/цены POST /stock/sync/ OPTORA: склад
Магазин заказал OPTORA: заказ B2B GET /orders/ 1С: заказ покупателя
1С приняла заказ POST /orders/{id}/ack/ OPTORA: confirmed

3. Авторизация

В каждый HTTP-запрос добавляйте один из заголовков:

Authorization: Token <ВАШ_API_КЛЮЧ>
Content-Type: application/json

Также поддерживаются:

Authorization: Bearer <ВАШ_API_КЛЮЧ>
X-Api-Key: <ВАШ_API_КЛЮЧ>

Базовый адрес всех методов: https://optora.kz/supplier-api

HTTP-кодЗначение
401Ключ неверный, интеграция выключена или поставщик неактивен
400Неверный формат JSON или параметры
404Заказ не найден (ack по чужому id)
200Успех (тело содержит "success": true)

4. Шаг 1 — проверка подключения

GET https://optora.kz/supplier-api/ping/
Authorization: Token <ключ>

Пример ответа:

{
  "success": true,
  "supplier": { "id": 1, "name": "ТОО Поставщик" },
  "server_time": "2026-07-18T09:00:00+05:00"
}

Реализуйте этот вызов при первом запуске обмена и при ошибках 401.

5. Шаг 2 — выгрузка вашего каталога из 1С

1С отправляет свою номенклатуру. Каждая строка — товар, который вы хотите продавать магазинам через OPTORA. После успешной выгрузки позиции отображаются в каталоге поставщика (раздел «Мой каталог» в кабинете и в приложении у магазинов).

POST https://optora.kz/supplier-api/products/sync/
Authorization: Token <ключ>
Content-Type: application/json

{
  "items": [
    {
      "external_id": "00-00012345",
      "name": "Молоко 3.2% 1л",
      "barcode": "4870001234567",
      "sku": "MLK-32-1",
      "brand": "Молочный завод",
      "unit": "шт",
      "description": "Пастеризованное",
      "price": 450,
      "stock": 120,
      "min_qty": 1,
      "is_active": true
    }
  ]
}

5.1. Поля позиции каталога

Поле JSONОбяз.Описание
external_id*Код номенклатуры в 1С (GUID, код, артикул — что удобно). Главный ключ для связи.
nameдля новыхНаименование для магазинов
barcode*Штрихкод EAN-13/EAN-8. *Нужен хотя бы один идентификатор: external_id, barcode или sku
sku*Артикул поставщика
brandБренд
unitЕдиница: «шт», «кг», «уп» и т.д. (нормализуется на сервере)
descriptionОписание
priceОптовая цена (число, тенге)
stockОстаток на складе (целое число)
min_qtyМинимальное количество в заказе (по умолчанию 1)
categoryНазвание категории из справочника OPTORA (сопоставляется по имени, регистр не важен). Если не найдено — игнорируется.
is_activefalse — скрыть товар от магазинов

5.2. Обновление уже выгруженных позиций

Порядок поиска существующей позиции (upsert): external_id → barcode → sku.

5.3. Ответ и ограничения

{
  "success": true,
  "created": 10,
  "updated": 240,
  "skipped": 2,
  "total": 252,
  "errors": ["#15: duplicate barcode"]
}
Остатки: при оформлении заказа магазином OPTORA сразу уменьшает остаток. При следующей выгрузке из 1С присылайте актуальный остаток из 1С — он перезапишет значение на OPTORA.

6. Шаг 3 — частое обновление остатков и цен

Лёгкий метод — только для уже существующих товаров. Новые позиции не создаёт.

POST https://optora.kz/supplier-api/stock/sync/
{
  "items": [
    { "external_id": "00-00012345", "stock": 95, "price": 460 },
    { "barcode": "4870001234567", "stock": 0, "is_active": false }
  ]
}

Идентификация: external_id → barcode → sku. Рекомендуемая частота: каждые 5–15 минут.

7. Шаг 4 — получение новых заказов от магазинов

GET https://optora.kz/supplier-api/orders/?status=new&limit=200
Authorization: Token <ключ>

7.1. Параметры запроса

ПараметрПо умолчаниюОписание
statusnewnew, confirmed, assembling, shipped, delivered, cancelled или all
since—ISO-дата/время — только заказы не раньше (для инкрементальной загрузки)
limit2001…1000 заказов за запрос

7.2. Пример ответа

{
  "success": true,
  "count": 1,
  "results": [
    {
      "id": 42,
      "number": "B2B-260718-AB12C",
      "status": "new",
      "store": {
        "id": 7,
        "name": "Магазин №1",
        "phone": "+7 701 000 00 00",
        "address": "г. Караганда, ул. Ленина 1",
        "email": "shop@example.kz"
      },
      "comment": "Доставить до 12:00",
      "delivery_date": "2026-07-19",
      "total_amount": "13500.00",
      "created_at": "2026-07-18T09:50:00+05:00",
      "payment_method": "cash",
      "payment_status": "unpaid",
      "paid_amount": "0.00",
      "is_store_received": false,
      "receiving_status": "",
      "received_at": null,
      "received_total_amount": null,
      "receive_comment": "",
      "items": [
        {
          "item_id": 555,
          "external_id": "00-00012345",
          "barcode": "4870001234567",
          "sku": "MLK-32-1",
          "name": "Молоко 3.2% 1л",
          "price": "450.00",
          "quantity": 30,
          "total": "13500.00",
          "received_quantity": null
        }
      ]
    }
  ]
}

7.3. Поля заказа

ПолеОписание
store.phone, store.address, store.emailКонтакты магазина — для создания/поиска контрагента в 1С
payment_methodСпособ оплаты при оформлении: cash, card, transfer и т.п. (пусто — не выбран)
payment_statusunpaid / paid / частичная — статус оплаты
paid_amountСколько уже оплачено
is_store_receivedtrue — магазин подтвердил приёмку. До этого товар в пути.
receiving_statusПусто (не принято), full, partial или rejected
received_total_amountСумма по факту приёмки (может быть меньше заказа при частичной приёмке)
receive_commentКомментарий магазина к расхождениям
items[].item_idID строки заказа на OPTORA (стабильный ключ строки)
items[].received_quantitynull — приёмки ещё не было; число — сколько магазин фактически принял
Важно: заказы не помечаются прочитанными автоматически. Пока вы не отправите ack, заказ со статусом new будет приходить снова при каждом опросе. Храните в 1С таблицу «уже загруженных заказов OPTORA» (поле id или number).

7.4. Приёмка магазином — расхождения (важно для реализации)

С обязательной приёмкой заказ считается доставленным только после подтверждения магазином. Пока is_store_received = false — товар «в пути», реализацию в 1С проводить рано.

8. Шаг 5 — создание документа в 1С и подтверждение (ack)

Алгоритм на стороне 1С:

  1. Получить заказы GET /orders/?status=new.
  2. Для каждого нового id (которого нет в вашем регистре):
    • Найти номенклатуру по external_id / штрихкоду / sku из строк заказа.
    • Создать «Заказ покупателя» (или ваш тип документа) с контрагентом = магазин (store.name).
    • Записать связь: ID OPTORA ↔ номер документа 1С.
  3. После успешной записи в 1С — подтвердить приём на OPTORA:
POST https://optora.kz/supplier-api/orders/42/ack/
Authorization: Token <ключ>
Content-Type: application/json

{ "status": "confirmed" }

8.1. Допустимые статусы ack

statusКогда отправлять из 1С
confirmedЗаказ принят в работу (по умолчанию)
assemblingНачата сборка на складе
shippedОтгружен / передан экспедитору
deliveredДоставлен магазину
cancelledОтменён — остатки по заказу вернутся на OPTORA

Ответ:

{ "success": true, "order": { "id": 42, "number": "B2B-260718-AB12C", "status": "confirmed" } }

9. Рекомендуемое расписание в 1С

ОперацияМетодЧастота
Проверка связиGET /ping/При старте обмена / при ошибках
Полная выгрузка каталогаPOST /products/sync/1–2 раза в сутки + при изменении номенклатуры
Остатки и ценыPOST /stock/sync/Каждые 5–15 минут
Новые заказыGET /orders/?status=newКаждые 1–5 минут
ПодтверждениеPOST /orders/{id}/ack/Сразу после записи документа в 1С
Статусы отгрузкиPOST /orders/{id}/ack/При смене статуса в 1С (shipped, delivered)
Проверка приёмки (реализация)GET /orders/?status=shippedКаждые 5–15 минут — ловим is_store_received=true

10. Пример алгоритма (псевдокод для 1С)

// Регламентное задание «OPTORA_ОбменЗаказами»
Запрос = Новый HTTPСоединение("admin.optoraapp.kz", 443, , , , 60, Новый ЗащищенноеСоединениеOpenSSL);
Заголовки = Новый Соответствие;
Заголовки.Вставить("Authorization", "Token " + Константы.OptoraApiKey);
Заголовки.Вставить("Content-Type", "application/json");

// 1. Новые заказы
HTTPЗапрос = Новый HTTPЗапрос("/supplier-api/orders/?status=new&limit=200", Заголовки);
Ответ = Запрос.Получить(HTTPЗапрос);
Данные = ПрочитатьJSON(Ответ.ПолучитьТелоКакСтроку());

Для Каждого Заказ Из Данные.results Цикл
    Если УжеЗагружен(Заказ.id) Тогда Продолжить; КонецЕсли;
    Док1С = СоздатьЗаказПокупателя(Заказ);
    Если Док1С.Записан Тогда
        ОтметитьЗагруженным(Заказ.id, Док1С.Ссылка);
        // ack
        Тело = "{""status"":""confirmed""}";
        HTTPAck = Новый HTTPЗапрос("/supplier-api/orders/" + Заказ.id + "/ack/", Заголовки);
        HTTPAck.УстановитьТелоИзСтроки(Тело);
        Запрос.ОтправитьДляОбработки(HTTPAck);
    КонецЕсли;
КонецЦикла;

// 2. Остатки (отдельное регламентное задание, чаще)
МассивОстатков = СформироватьОстаткиИз1С(); // [{external_id, stock, price}, ...]
ТелоОст = ЗаписатьJSON(Новый Структура("items", МассивОстатков));
HTTPStock = Новый HTTPЗапрос("/supplier-api/stock/sync/", Заголовки);
HTTPStock.УстановитьТелоИзСтроки(ТелоОст);
Запрос.ОтправитьДляОбработки(HTTPStock);

11. Изображения товаров

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

13. Частые вопросы

ВопросОтвет
Заказ дублируется при каждом опросеНе отправлен ack или не сохранён id в 1С
Товар не создаётся при stock/syncИспользуйте products/sync для новых позиций
401 UnauthorizedКлюч неверный или интеграция выключена в кабинете
Остаток на OPTORA не совпадает с 1СМагазин уже заказал — выгрузите актуальный остаток из 1С
МойСклад и 1С одновременноМожно. API 1С и МойСклад работают параллельно (вкладка «МойСклад»)

14. Тестирование через curl

# Ping
curl -s -H "Authorization: Token ВАШ_КЛЮЧ" https://optora.kz/supplier-api/ping/

# Остатки
curl -s -X POST https://optora.kz/supplier-api/stock/sync/ \
  -H "Authorization: Token ВАШ_КЛЮЧ" \
  -H "Content-Type: application/json" \
  -d '{"items":[{"external_id":"TEST-001","stock":10,"price":100}]}'

# Заказы
curl -s -H "Authorization: Token ВАШ_КЛЮЧ" \
  "https://optora.kz/supplier-api/orders/?status=new&limit=10"
API-ключ выдаёт владелец кабинета поставщика: войти в кабинет → Интеграция → 1С → «Сгенерировать ключ».