Integration API v1.0
Integration API — стабильный REST-фасад для обмена опубликованными бизнес-данными с внешними системами. Он не предоставляет пользовательскую сессию, управление сотрудниками, настройками платформы или неопубликованными сущностями.
Базовый URL
/api/v1/integration-apiАутентификация
Владелец портала выдаёт каждой внешней системе отдельный API-ключ с минимальным набором точных доменных scopes. Каждый запрос передаёт ключ только в заголовке:
X-API-Key: spk_...Ключ привязан к одному порталу. Внешняя система не может расширить его scopes или получить доступ к данным другого ключа либо портала.
Метаданные текущего ключа
GET /api/v1/integration-api/meta
X-API-Key: spk_...Ответ содержит только ресурсы, операции, события и scopes, разрешённые текущему ключу. Используйте этот ответ для определения фактически доступного контракта.
Бизнес-ресурсы
| Resource | Назначение | Read scope | Write scope |
|---|---|---|---|
purchase-requisitions | Заявки на закупку | purchase_requisitions.read | purchase_requisitions.write |
procurement-items | Позиции доступных закупок | purchase_requisitions.read | только чтение |
supplier-rfqs | Запросы цен поставщикам | supplier_documents.read | только чтение |
supplier-quotes | Предложения поставщиков | supplier_documents.read | только чтение |
catalog-items | Номенклатура | catalog.read | catalog.write |
counterparties | Контрагенты | counterparties.read | counterparties.write |
warehouses | Склады | warehouses.read | warehouses.write |
price-lists | Прайс-листы | price_lists.read | price_lists.write |
invoices | Входящие счета | finance.read | finance.write |
В OpenAPI каждый ресурс показан отдельными методами, поэтому разработчику не нужно подставлять строковое значение в общий параметр {resource}.
Для шести изменяемых ресурсов опубликованы:
GET /api/v1/integration-api/:resource
POST /api/v1/integration-api/:resource
GET /api/v1/integration-api/:resource/:id
PATCH /api/v1/integration-api/:resource/:idВ строке :resource выше используется один из кодов: purchase-requisitions, catalog-items, counterparties, warehouses, price-lists или invoices. В Swagger они представлены отдельными paths и типизированными body/response-схемами.
PATCH возвращает актуальное представление записи и поэтому требует одновременно read- и write-scope ресурса. POST создания требует write-scope. Для входящих счетов дополнительно опубликован точный недеструктивный метод:
POST /api/v1/integration-api/invoices/:id/operations/change-statusОн принимает только paymentStatus из enum, показанного в OpenAPI.
Пример создания позиции
POST /api/v1/integration-api/catalog-items
X-API-Key: spk_...
Content-Type: application/json
{
"sku": "PUMP-100",
"name": "Насос циркуляционный",
"brand": "Example"
}Поля, отсутствующие в request-схеме ресурса, отклоняются. Ответ содержит только поля опубликованной response-схемы. Связь с ID внешней системы регистрируется отдельным PUT /links, чтобы для неё всегда проверялся собственный scope.
Позиции закупок, RFQ и предложения
Эти ресурсы опубликованы только для чтения:
GET /api/v1/integration-api/procurement-items
GET /api/v1/integration-api/procurement-items/:id
GET /api/v1/integration-api/supplier-rfqs
GET /api/v1/integration-api/supplier-rfqs/:id
GET /api/v1/integration-api/supplier-quotes
GET /api/v1/integration-api/supplier-quotes/:idОбщие параметры списка: search или q, page от 1, limit от 1 до 100, а также необязательные pipelineId, procurementId, status и updatedSince. Для RFQ и предложений доступен supplierId; для предложений — rfqId.
Позиции требуют purchase_requisitions.read. RFQ и предложения требуют supplier_documents.read. Во всех трёх случаях запись возвращается только тогда, когда её родительская закупка находится в портале ключа и в доступной создателю ключа воронке.
Ответы намеренно не содержат служебные metadata, технические снимки доставки, токены ссылок, внутренние комментарии, адреса получателей и поля управления пользователями. Методы создания, изменения и жизненного цикла для этих ресурсов во внешний контракт не входят.
Этапы обработки заявок
Внешняя система может прочитать доступные владельцу ключа воронки и этапы, а затем идемпотентно переместить конкретную заявку:
GET /api/v1/integration-api/pipelines
GET /api/v1/integration-api/pipelines/:pipelineId/stages
POST /api/v1/integration-api/procurements/:id/operations/move-stageПеремещение требует read- и write-scope заявок, Idempotency-Key и актуальную version либо If-Match. Через внешний контракт нельзя создавать, изменять или удалять воронки и этапы, а также переводить заявку в отменяющее состояние.
Связи внешних идентификаторов
Связь сопоставляет ID внешней системы с опубликованной бизнес-сущностью:
GET /api/v1/integration-api/links?externalSource=source-system&externalId=1001&entityType=catalog_item
X-API-Key: spk_...PUT /api/v1/integration-api/links
X-API-Key: spk_...
Content-Type: application/json
{
"externalSource": "source-system",
"externalId": "1001",
"entityType": "catalog_item",
"entityId": "entity-uuid",
"idempotencyKey": "catalog-1001-link-v1"
}Для чтения нужны external_links.read и read-scope целевого ресурса. Для записи нужны external_links.write и write-scope целевого ресурса.
Связи изолированы по API-ключу: ключ получает и изменяет только записи своего пространства внешних идентификаторов. В webhook payload эти связи не передаются.
Исходящие webhook-подписки
GET /api/v1/integration-api/webhook
POST /api/v1/integration-api/webhook
PUT /api/v1/integration-api/webhook/:id
POST /api/v1/integration-api/webhook/:id/testДля списка нужен webhooks.read. Создание, изменение и тест требуют webhooks.write вместе с read-scope домена события.
Один элемент create-массива создаёт одну подписку на одно событие и один URL:
POST /api/v1/integration-api/webhook
X-API-Key: spk_...
Content-Type: application/json[
{
"name": "Изменение статуса заявки",
"event": "integration_api.procurement.status_changed",
"url": "https://example.com/webhooks/procurements",
"isActive": true
}
]Секрет HMAC возвращается только один раз в create-response в поле secretPlaintext. List-, update- и test-responses этого поля не содержат.
Подписка принадлежит создавшему её ключу. Другой ключ не может получить, изменить или протестировать её. Новые доставки прекращаются при отзыве или истечении ключа, утрате webhooks.write либо read-scope домена события.
Подробный каталог и минимальная схема payload: Исходящие webhook-события.
Генерация документов
Внешняя система может идемпотентно запустить генерацию документа и отдельно получить результат:
POST /api/v1/integration-api/document-generation-jobs
X-API-Key: spk_...
Idempotency-Key: document-request-1001-v1
Content-Type: application/json
{
"procurementId": "entity-uuid",
"kind": "SALES_INVOICE",
"templateId": "template-uuid",
"formats": ["pdf"],
"scope": "all",
"parameters": {
"dueDate": "2026-08-15"
}
}Поле parameters закрытое: неизвестный ключ возвращает 400, а допустимый набор определяется значением kind.
kind | Допустимые поля parameters |
|---|---|
COMMERCIAL_PROPOSAL | sellerProfileId, customerId, customerContactId, title, subject, validUntil, plannedDeliveryDate, currencyCode, vatMode, paymentTermsText, deliveryTermsText, externalComment |
SALES_INVOICE | sellerProfileId, customerId, customerContactId, proposalId, dueDate, currencyCode, vatMode, paymentTermsText, externalComment |
CONTRACT | sellerProfileId, customerId, customerContactId, proposalId, title, subject, validUntil, currencyCode, totalAmount, paymentTermsText, deliveryTermsText, externalComment, assignedToId |
| Транспортные и сопроводительные документы | logisticsObjectIds, routeIds, batchIds, carrierName, carrierInn, driverName, driverPhone, driverLicense, vehicleNumber, vehicleModel, trailerNumber, attorneyName, attorneyPosition, attorneyPassport, attorneyBasis, recipientName, deliveryAddress, comment |
К транспортным и сопроводительным относятся GOODS_WAYBILL, TRANSPORT_WAYBILL, GOODS_TRANSPORT_WAYBILL, POWER_OF_ATTORNEY_RECEIPT, ROUTE_SHEET, ACCEPTANCE_ACT, PICKING_LIST, DELIVERY_REQUEST, PRODUCTION_TRANSFER_WAYBILL и DISCREPANCY_ACT. Все идентификаторы имеют формат UUID, даты — ISO 8601, currencyCode — три заглавные буквы, а vatMode принимает только EXCLUSIVE, INCLUSIVE или NO_VAT. При scope: selected_items массив selectedItemIds обязателен и содержит только позиции указанной закупки.
GET /api/v1/integration-api/document-generation-jobs/:jobId
GET /api/v1/integration-api/generated-documents
GET /api/v1/integration-api/generated-documents/:documentId
POST /api/v1/integration-api/generated-documents/:documentId/download-urlПовтор create-запроса с тем же Idempotency-Key возвращает исходное задание. Короткоживущая ссылка скачивания выдаётся только отдельным запросом и не передаётся в webhook. Для download URL одновременно требуются documents.read и documents.download.
Партии доставки и рейсы
GET /api/v1/integration-api/delivery-batches
GET /api/v1/integration-api/delivery-batches/:id
GET /api/v1/integration-api/delivery-trips
POST /api/v1/integration-api/delivery-trips
GET /api/v1/integration-api/delivery-trips/:id
POST /api/v1/integration-api/delivery-trips/:id/commands/:commandСписки используют cursor pagination. Следующая страница запрашивается с pageInfo.nextCursor.
Опубликованные команды рейса: plan, dispatch, arrive-stop, complete-stop, complete. Изменяющие запросы требуют:
Idempotency-Key;versionв body либоIf-Match: W/"<version>";- любой разрешённый read-scope (
delivery_trips.readилиlogistics.read) и любой разрешённый write-scope (delivery_trips.writeилиlogistics.write); смешанная пара также допустима.
Ответ рейса содержит version, а HTTP-ответ — соответствующий ETag. При устаревшей версии API возвращает 409 Conflict.
Variable API
Variable API использует тот же заголовок X-API-Key, но отдельные маршруты:
GET /api/v1/variables
POST /api/v1/variables/resolveТребуются variables.read и read-scope запрошенного домена. Каталог и значения фильтруются по текущему ключу; поля других доменов не возвращаются.
Лимиты запросов
По умолчанию Integration API допускает 300 запросов в минуту на ключ. Ответы содержат RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset и RateLimit-Policy.
При превышении лимита API возвращает 429 Too Many Requests и Retry-After.
Ошибки
| HTTP | Значение |
|---|---|
400 | Запрос не соответствует опубликованной схеме |
401 | Ключ отсутствует, недействителен или истёк |
403 | Недостаточно scopes либо ресурс недоступен ключу |
404 | Опубликованная сущность не найдена в доступной области |
409 | Конфликт версии, статуса или идемпотентности |
429 | Превышен лимит запросов |