API TradeSYNC
Подключайте свой сайт, аналитику и внешние сервисы к товарному учёту. Получайте товары, остатки, документы и чеки, работайте со справочниками и рассчитывайте скидки.
Адрес API — BASE_URL
Для всех запросов к API используйте:
https://online.tradesync.by/api/v1
BASE_URL — это общая начальная часть адреса всех методов API. К ней нужно дописать путь метода из таблицы. Например, для получения товаров полный адрес будет:
GET https://online.tradesync.by/api/v1/products?limit=100
Authorization: Bearer YOUR_API_TOKEN
Проверка подключения: https://online.tradesync.by/api/v1/health. Подразделения: https://online.tradesync.by/api/v1/stores.
https://online.tradesync.by. Базовый адрес методов v1: https://online.tradesync.by/api/v1. Используйте токен, выданный для вашего аккаунта. Адрес https://tradesync.by/api/ — эта страница документации, а не адрес для API-запросов.Ниже запись {BASE_URL}/products означает: замените {BASE_URL} целиком, вместе с фигурными скобками, на адрес своего API без завершающего слеша. Не добавляйте /api/v1 повторно. YOUR_API_TOKEN замените выданным токеном.
Где запросить токен
Запросить токен можно через чат в личном кабинете.
Выданные ключи доступны в личном кабинете: Настройки → API. Ключ скрыт по умолчанию: его можно показать или скопировать отдельной кнопкой. Здесь же отображаются права, срок действия, последний запрос, индивидуальные лимиты и статистика авторизованных запросов и ошибок по дням, методам и ключам. Доступность вкладки на сервере аккаунта уточните у поддержки.
Период статистики — не более 366 дней. Статистика сохраняется после удаления ключа, если принадлежность запросов аккаунту известна. Просроченные и отозванные ключи нельзя использовать или раскрыть.
Укажите организацию и аккаунт TradeSYNC, назначение интеграции, нужные данные, необходимость создания записей и ожидаемую частоту запросов. Администратор создаст токен для вашего аккаунта и сообщит адрес API, права, срок действия и действующие лимиты.
POST /discounts/evaluate требуется право read. Для создания товаров, групп, единиц измерения и контрагентов требуется право write. Отозванный, просроченный ключ или ключ заблокированного/удалённого аккаунта не проходит авторизацию. Для интеграции только на чтение запрашивайте токен read. Храните токен на сервере: не размещайте его в публичном JavaScript, ссылках и репозиториях.Быстрый старт
API принимает HTTPS-запросы и возвращает JSON. Базовый путь — /api/v1 на сервере вашего аккаунта. Для основного сервера BASE_URL — https://online.tradesync.by/api/v1. Этот же адрес используется во всех примерах ниже.
GET {BASE_URL}/health
Authorization: Bearer YOUR_API_TOKEN
BASE_URL — полный адрес с окончанием /api/v1. YOUR_API_TOKEN замените выданным токеном. Пример ответа проверки:
{ "data": { "status": "ok", "accountId": 123 } }
Получение товаров:
GET {BASE_URL}/products?limit=100&offset=0&order=name
Authorization: Bearer YOUR_API_TOKEN
Для POST передавайте Content-Type: application/json и JSON-тело. Пример создания товара:
POST {BASE_URL}/products
Authorization: Bearer YOUR_API_TOKEN
Content-Type: application/json
{ "name": "Кофе зерновой", "barcode": "4812345678901" }
Успех: HTTP 201 и { "data": { "id": 120 } }. Числа и названия в примерах условные.
Лимиты и пагинация
Секундный и минутный лимиты действуют одновременно. Это значения по умолчанию: администратор может изменить общие настройки или назначить токену индивидуальные ограничения. Уточняйте действующие значения при получении доступа.
При превышении лимита API возвращает HTTP 429 и код RATE_LIMITED. Подождите количество секунд из заголовка Retry-After, затем повторите запрос. Ограничивайте параллелизм и распределяйте загрузку во времени.
limit— размер страницы, по умолчанию 100, минимум 1, максимум 1000.offset— число пропущенных записей, по умолчанию 0, максимум 100000.order=nameилиorder=-id— сортировка справочников по поддерживаемому полю; минус означает убывание.search— поиск в поддерживающих его методах.
Документы и чеки сортируются по дате по убыванию с устойчивым порядком по ID. Позиции документов и чеков также имеют пагинацию limit/offset и объект meta. Только результат POST /discounts/evaluate возвращается массивом без meta.
Некорректные значения пагинации, массивы вместо одиночных query-параметров и неверные даты отклоняются с HTTP 400. Максимальный offset — 100000, длина search — 200 символов. Размер JSON-тела — не более 256 KiB.
Заголовки лимитера: X-RateLimit-Limit — секундный лимит; X-RateLimit-Remaining — оставшиеся запросы секундного окна; для повторной попытки после 429 ориентируйтесь на Retry-After.
Методы API v1
Все пути ниже дополняют BASE_URL. Вместо {id} передавайте ID записи. Все методы требуют API-токен.
Справочники и остатки
| Метод и путь | Назначение / параметры | Поля в data |
|---|---|---|
GET/health |
Проверка подключения | status, accountId |
GET/products |
Список товаров; search, group_id, barcode | id, name, sku, barcode, groupId, unitId, vatPercent, markupPercent, discountsDisabled, typeCode, description, country, weight |
GET/products/{id} |
Товар по ID | Поля товара |
POST/products |
Создать товар; обязательно name | id созданного товара |
GET/product-groups |
Группы товаров; search | id, name, parentId |
GET/product-groups/{id} |
Группа по ID | id, name, parentId |
POST/product-groups |
Создать группу; name, parent | id созданной группы |
GET/units |
Единицы измерения; search | id, name, unitCode, conversionFactor, isWeightBased |
GET/units/{id} |
Единица по ID | Поля единицы измерения |
POST/units |
Создать единицу; обязательно name | id созданной единицы |
GET/counterparties |
Контрагенты; search | id, shortName, fullName, taxNumber, legalAddress, postalAddress, email, phone, postalCode |
GET/counterparties/{id} |
Контрагент по ID | Поля контрагента |
POST/counterparties |
Создать контрагента; short_name или full_name | id созданного контрагента |
GET/stores |
Склады и подразделения; search | id, name, isDefault, address, isActive, parentId |
GET/stores/{id} |
Подразделение по ID | Поля подразделения |
GET/pricelists |
Прайсы; store_id, goods_id | id, productId, retailPrice, quantity, departmentId, supplierId, supplierPrice |
GET/stocks |
Остатки; store_id, goods_id | id, productId, departmentId, quantity, supplierPrice, retailPrice, vatPercent, supplierId |
Параметр запроса store_id и поле ответа departmentId обозначают подразделение. В ответе подразделения: address — адрес, parentId — родитель, isActive — активность, isDefault — признак по умолчанию. В единицах измерения unitCode — целочисленный код или null, name — название; conversionFactor — коэффициент пересчёта.
GET /departments и GET /departments/{id} — альтернативные адреса /stores и /stores/{id} с теми же полями ответа.
Документы — чтение
| Метод и путь | Назначение / параметры | Поля в data |
|---|---|---|
GET/documents/{type} |
Список документов | id, number, issuedAt, externalNumber, departmentId, counterpartyId, isDraft, status, lineCount |
GET/documents/{type}/{id} |
Документ по ID | Поля списка и typeCode |
GET/documents/{type}/{id}/positions |
Позиции документа | id, productId, productName и финансовые поля выбранного типа; пагинация через limit и offset |
Значения {type}:
supply— приходные накладные.demand— расходные накладные (отпуск).salesorder— заказы покупателей.invoiceout— счета.move— перемещения.inventory— инвентаризации.repricing— переоценки.
Фильтры списка: from, to, store_id, agent_id, is_draft=true|false, search по номеру. Для перемещения store_id — подразделение-отправитель. Параметр agent_id применим к документам с контрагентом.
В заголовке issuedAt — дата, externalNumber — номер документа контрагента, lineCount — число строк, counterpartyId — контрагент. Состав позиции зависит от типа: у заказов есть orderedQuantity и issuedQuantity, у переоценок — старые и новые цены. Внутренние служебные поля и произвольные столбцы БД не возвращаются. Публичные методы создания и проведения документов не предусмотрены.
Даты фильтров: YYYY-MM-DD либо ISO 8601 с часовым поясом. Если to задан датой без времени, включается весь этот день; диапазон должен быть корректным и упорядоченным.
Поля позиций по типам документов
Каждая позиция содержит id, productId, productName и только перечисленные ниже бизнес-поля выбранного типа. Значения цен, сумм, процентов и количества могут быть числами либо десятичными строками. supplierId — ID поставщика; поля *Percent — проценты; *Price — цены; *Amount — суммы. recordedQuantity — учётный остаток инвентаризации, previous*/new* — значения до/после переоценки.
| Тип документа | Дополнительные поля позиции |
|---|---|
supply |
quantity, supplierPrice, supplierAmount, vatPercent, vatAmount, markupPercent, markupAmount, amountIncludingVat, amountIncludingMarkup, retailPrice, retailAmount, discountPercent, supplierVatPercent, supplierVatAmount, description, conversionFactor |
demand |
quantity, supplierId, supplierPrice, supplierAmount, supplierVatPercent, supplierVatAmount, discountPercent, discountAmount, retailPrice, customerPrice, vatPercent, vatAmount, markupPercent, markupAmount, amountIncludingVat, amountIncludingMarkup, retailAmount, description, discountSource, discountRuleId, discountRuleName, discountCardId, discountCardNumber |
salesorder |
orderedQuantity, issuedQuantity, retailPrice, retailAmount, supplierAmount, supplierPrice, markupAmount, discountPercent, discountAmount, discountSource, discountRuleId, discountRuleName, discountCardId, discountCardNumber |
invoiceout |
quantity, supplierId, supplierPrice, supplierAmount, supplierVatPercent, supplierVatAmount, discountPercent, discountAmount, retailPrice, customerPrice, vatPercent, vatAmount, markupPercent, markupAmount, amountIncludingVat, amountIncludingMarkup, retailAmount, warranty |
move |
quantity, vatPercent, vatAmount, amountIncludingVat, retailPrice, retailAmount, supplierId, description, supplierPrice |
inventory |
quantity, supplierPrice, supplierAmount, supplierId, retailPrice, retailAmount, supplierVatPercent, supplierVatAmount, vatPercent, vatAmount, recordedQuantity, description, recordedRetailAmount, recordedSupplierAmount |
repricing |
quantity, previousSupplierPrice, newSupplierPrice, previousSupplierVatPercent, newSupplierVatPercent, previousVatPercent, newVatPercent, previousRetailPrice, newRetailPrice, supplierAmount, retailAmount, supplierVatAmount, vatAmount, supplierId |
Чеки и отчёты
| Метод и путь | Назначение / параметры | Поля в data |
|---|---|---|
GET/checks |
Чеки; from, to, store_id, cashier_id, type=sale или return, annulled, search | id, number, issuedAt, departmentId, cashierId, totalAmount, discountAmount, isReturn, isAnnulled, isCanceled, discountCardNumber, discountCardPercent |
GET/checks/{id} |
Чек по ID | Поля чека |
GET/checks/{id}/positions |
Позиции чека; limit, offset | id, productId, productName, quantity, unitPrice, netUnitPrice, grossAmount, netAmount, discountAmount, discountPercent, discountSource, discountRuleId, discountRuleName |
GET/checks/shifts |
Агрегация чеков по дню и подразделению | day, departmentId, receiptCount, totalAmount, discountAmount |
GET/reports/retail-sales |
Продажи по дням | day, receiptCount, totalAmount, discountAmount |
totalAmount — итог чека, discountAmount — сумма скидки. В позиции unitPrice и grossAmount — значения до скидки, netUnitPrice и netAmount — после неё. Для смен и отчёта доступны те же фильтры чеков. /checks/shifts группирует чеки по дню и подразделению, а не возвращает отдельные фискальные смены. Из агрегатов исключены отменённые, аннулированные и отложенные чеки; суммы возвратов вычитаются. receiptCount — число включённых чеков, в том числе возвратов.
Скидки
| Метод и путь | Назначение / параметры | Поля в data |
|---|---|---|
GET/discounts/rules |
Правила скидок; search | id, name, ruleType, requiresCard, purchaseInterval, startDate, endDate, startTime, endTime, isActive |
GET/discounts/cards |
Дисконтные карты; search | id, number, discountValue, expiresAt, phone, isActive, typeCode, holderName |
GET/discounts/cards/{id} |
Карта с привязками | Поля карты и productIds, groupIds, departmentIds (массивы ID), ranges (диапазоны выбранного типа карты) |
POST/discounts/evaluate |
Рассчитать скидку по корзине; positions обязателен | productId, quantity, unitPrice, discountPercent, discountedQuantity, discountSource, discountRuleId, discountRuleName, netUnitPrice, netAmount, discountAmount |
В ranges возвращаются id, minAmount, maxAmount, discountPercent, cardTypeId. Это диапазоны только выбранного типа карты. Пример расчёта корзины:
POST {BASE_URL}/discounts/evaluate
Content-Type: application/json
Authorization: Bearer YOUR_API_TOKEN
{
"store_id": 1,
"discount_card_id": null,
"positions": [{ "goods_id": 120, "quantity": 2, "price": 18.5 }]
}
Расчёт требует право read и возвращает массив строк, не создавая чек. Массив positions должен содержать от 1 до 1000 строк; товары, подразделение и карта должны принадлежать аккаунту ключа. Количество должно быть положительным, цена — неотрицательной. Неактивная или просроченная карта отклоняется. Для правил и карт с ограничением по подразделениям укажите store_id.
discountedQuantity — число единиц, к которым применяется скидка. netUnitPrice — цена этих единиц после скидки; остальные единицы учитываются по unitPrice. netAmount — итог всей строки, discountAmount — скидка по всей строке. Это важно для правила каждой N-й покупки: скидка не обязательно действует на всё количество. Цены и суммы расчёта округляются до двух знаков.
Формат ответов и ошибки
Публичные поля ответа имеют имена camelCase. Имена полей ответа и входных параметров могут отличаться: используйте параметры запроса и JSON-тела POST, указанные в описании соответствующего метода.
Успешное чтение возвращает HTTP 200. Объект находится в data, список — в массиве data. У списков с пагинацией есть meta:
{
"data": [{ "id": 1, "name": "Основной склад", "isDefault": true,
"address": "г. Минск", "isActive": true, "parentId": null }],
"meta": { "total": 1, "limit": 100, "offset": 0 }
}
meta.total — количество записей с учётом фильтров, meta.limit — размер страницы, meta.offset — смещение. Пустой список возвращается как []. Незаполненные поля могут содержать null. Десятичные значения из БД могут приходить строками — учитывайте это при обработке цен и количества.
{ "error": { "code": "RATE_LIMITED", "message": "Превышен лимит запросов. Повторите позже." } }
| HTTP / код ошибки | Причина | Что делать |
|---|---|---|
400VALIDATION_ERROR |
Некорректные или отсутствующие обязательные данные | Проверьте JSON-тело, ID, даты и query-параметры |
401UNAUTHORIZED |
Нет токена, токен недействителен, отозван или истёк | Проверьте Authorization и обратитесь в поддержку |
403FORBIDDEN |
Недостаточно прав для чтения, расчёта скидок или создания записей | Запросите необходимые права |
404NOT_FOUND |
Запись или тип документа не найден | Проверьте ID, тип и аккаунт токена |
409CONFLICT |
Конфликт с существующей записью | Проверьте уникальные значения; не повторяйте создание без проверки |
413PAYLOAD_TOO_LARGE |
JSON-тело превышает 256 KiB | Уменьшите размер запроса |
415UNSUPPORTED_MEDIA_TYPE |
Неверный Content-Type | Передайте application/json |
503UNAVAILABLE / TEMPORARILY_UNAVAILABLE |
Сервис временно занят или недоступен | Повторите чтение позже с задержкой; создание сначала проверьте на дубли |
429RATE_LIMITED |
Превышен лимит | Повторите после Retry-After |
500INTERNAL |
Ошибка обработки на сервере | Передайте поддержке метод, время и код ошибки без токена |
Для POST-запросов на создание записи не повторяйте запрос автоматически после сетевого тайм-аута: сначала проверьте, не была ли запись создана, чтобы избежать дублей.
Обсудим вашу интеграцию
Напишите, какую систему хотите подключить и какие данные передавать. Поможем уточнить методы, доступ и подходящий режим обмена.
REST API v1 · описание обновлено 4 октября 2026 г.