Полная цепочка заказа
Создайте заказ, отгрузите накладную, выставьте и проведите счёт, закройте оплату тем же вызовом. Частичная отгрузка и частичное выставление поддерживаются.
Developer API · бета
Kumpara Developer API подключает интернет-магазины, ERP, бухгалтерские программы и интеграторов маркетплейсов. Поверхность /v1 вызывает то же ядро, что и интерфейс: те же проверки, те же проводки, тот же расчёт налога и удержания.
Developer API сейчас в закрытой бете; общий доступ пока не открыт, дата не называется. Участники беты получают свой базовый адрес и ключи от нас.
Всё перечисленное работает на существующих эндпоинтах — это не планы.
Создайте заказ, отгрузите накладную, выставьте и проведите счёт, закройте оплату тем же вызовом. Частичная отгрузка и частичное выставление поддерживаются.
Поток GET /v1/changes отдаёт тип и идентификатор изменённой записи; детали вы читаете отдельно. Поток не различает интерфейс, мобильное приложение и API.
POST /v1/stock-levels/actions/set записывает результат инвентаризации; разница становится корректирующим движением. Движения читаются из книги только на чтение.
Один вызов превращает проведённый счёт в электронный документ; сценарий выбирается на сервере. Вы синхронизируете входящие, скачиваете XML/PDF и отвечаете на коммерческие счета.
Одного баланса мало: проводки, открытые позиции и сроки задолженности — отдельные эндпоинты. Платежи закрываются на открытые счета, курсовая разница читается отдельно.
Начальные остатки по контрагентам и складу заводятся отдельными эндпоинтами, у каждого есть сторнирующая пара. Книги на добавление — сторно единственный способ исправления.
Каждая запись несёт три заголовка: Authorization, Idempotency-Key, Content-Type.
В приложении: Настройки → API-ключи. Выберите имя, компанию и scope. Открытый ключ показывается один раз.
GET /v1/me возвращает бизнес, компанию, среду и scope ключа.
Сопоставление по ИНН или коду: существующие записи обновляются, отсутствующие создаются.
С approve: true создание и проведение выполняются одной транзакцией: номер, долг клиента и списание склада.
Счёт передаётся при создании платежа: касса, расчёты и распределение пишутся одной транзакцией.
Каждый запрос несёт Authorization: Bearer. Первый вызов покажет, к какому бизнесу и к какой компании
привязан ключ и что ему разрешено:
curl -s "https://api.kumpara.net/v1/me" \
-H "Authorization: Bearer kp_live_a1b2c3d4_…"
{
"data": {
"tenant": { "id": "…", "name": "Örnek Ticaret A.Ş.", "plan": "Pro" },
"company": { "id": "…", "legalName": "Örnek Ticaret A.Ş.", "baseCurrency": "TRY" },
"apiClient": { "prefix": "kp_live_a1b2c3d4", "environment": "live",
"scopes": ["me:read", "contacts:write", "sales:write", "sales:approve"] }
}
}
GET /v1/capabilities сообщит, подключены ли электронные документы, сколько осталось кредитов и какова
базовая валюта компании.
Не нужно искать клиента каждый раз: используйте upsert по ИНН или коду. Существующая запись обновляется, отсутствующая создаётся.
curl -s -X POST "https://api.kumpara.net/v1/contacts/actions/upsert?matchBy=taxNumber" \
-H "Authorization: Bearer kp_live_…" \
-H "Idempotency-Key: contact-4711-2026-09-23" \
-H "Content-Type: application/json" \
-d '{ "name": "Örnek Gıda Ltd. Şti.", "type": "customer", "taxNumber": "1234567890", "preferredCurrency": "TRY" }'
Поле created в ответе говорит, создана запись или обновлена. matchBy принимает только taxNumber
или code.
В строке счёта нет поля суммы. Вы передаёте количество, цену, скидку и ставку НДС; итог строки, удержанный НДС, базовую сумму и номер документа считает сервер.
curl -s -X POST "https://api.kumpara.net/v1/sales-invoices" \
-H "Authorization: Bearer kp_live_…" \
-H "Idempotency-Key: order-88213-invoice" \
-H "Content-Type: application/json" \
-d '{
"contactId": "6f1c…",
"currency": "TRY",
"approve": true,
"lines": [ { "productId": "9a3e…", "quantity": 10, "unitPrice": 250, "vatRate": 20 } ]
}'
approve: true выполняет создание и проведение одной транзакцией. Это денежная мутация, поэтому
ключу нужен sales:approve вместе с sales:write, иначе вернётся 403 insufficient_scope.
curl -s -X POST "https://api.kumpara.net/v1/payments" \
-H "Authorization: Bearer kp_live_…" \
-H "Idempotency-Key: payment-88213" \
-H "Content-Type: application/json" \
-d '{ "contactId": "6f1c…", "cashAccountId": "2b77…", "direction": "incoming",
"amount": 3060, "invoiceType": "sales_invoice", "invoiceId": "c41b…" }'
Касса, расчёты с контрагентом и распределение пишутся одной транзакцией. Для нескольких счетов —
allocations[], для закрытия позже — POST /v1/payments/{id}/actions/allocate.
curl -s "https://api.kumpara.net/v1/changes?since=2026-09-23T06:00:00Z&types=sales_invoice,payment" \
-H "Authorization: Bearer kp_live_…"
В следующем вызове передайте meta.checkpoint как since — граница строгая, одна и та же запись
не придёт дважды. Рекомендуем перекрытие в пять минут: чтение идемпотентно, повтор безвреден.
Ключ передаётся как Authorization: Bearer kp_live_… (или X-Api-Key). Открытое значение не хранится —
Kumpara держит только SHA-256-хеш и префикс. Каждый ключ привязан к одной компании; данные другой
компании вернуться не могут архитектурно. Права ключа не могут превышать роль создавшего его
пользователя.
Права имеют вид {ресурс}:{действие}, их двадцать восемь: read — просмотр, write — создание и
изменение, approve — проведение, отмена и сторно, issue/cancel/incoming — электронные документы.
Недоступный эндпоинт возвращает 403 insufficient_scope и называет недостающее право.
Каждая запись требует Idempotency-Key. Ключ сохраняется внутри той же транзакции, что и запись —
двойной записи нет. Повторный вызов с тем же ключом не выполняет работу заново. Ответ приходит в одной
из двух форм: 409 idempotency_replayed (созданную запись вы читаете через GET) либо 200 с телом
первого ответа и флагом replayed: true. Обе означают «операция уже применена»; ваш клиент должен
считать успехом и ту и другую.
Суммы хранятся как numeric(19,4) и возвращаются в JSON строкой — без ошибок округления. Сумма
никогда не отделяется от валюты.
Каждая финансовая строка несёт собственный снимок курса: originalAmount, originalCurrency,
exchangeRate, baseAmount, baseCurrency. Даже если курс обновится позже, прошлый документ не
изменится. Курс можно передать в exchangeRate; если не передать — применяется 1.
Списки страничатся курсором, offset отсутствует. Ответ несёт meta.nextCursor и meta.hasMore.
Размер страницы — pageSize: по умолчанию 50, максимум 200. Для дельты — параметр запроса updatedAfter
или поток /v1/changes.
Ошибки — RFC 9457 application/problem+json со стабильным полем code. Словарь зафиксирован.
| Статус | Значение | Частые коды |
|---|---|---|
| 400 | Запрос не прочитан | invalid_request, invalid_value |
| 401 | Ключ недействителен | unauthorized |
| 403 | Нет нужного права | insufficient_scope |
| 404 | Записи нет или она не этой компании | not_found |
| 409 | Конфликт | idempotency_replayed, duplicate_code |
| 422 | Нарушено бизнес-правило | validation_failed, currency_not_enabled |
| 429 | Превышен лимит | rate_limit_exceeded |
Чтение и запись — разные корзины. По умолчанию 600 чтений и 120 записей в минуту на ключ; в
каждом ответе есть RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset. При превышении — 429 и
Retry-After.
Каждый ответ несёт X-Request-Id; это же значение видно как requestId в теле ошибки — им и делитесь с
поддержкой. Полный контракт опубликован как OpenAPI 3: https://api.kumpara.net/v1/openapi.json.
Таблица ниже — вся поверхность, работающая сегодня. Полные параметры, тела и схемы ответов — в OpenAPI:
https://api.kumpara.net/v1/docs.
| Область | Основные эндпоинты | Права |
|---|---|---|
| Контекст | GET /v1/me, GET /v1/capabilities |
me:read |
| Карточка контрагента | GET · POST /v1/contacts, PATCH /v1/contacts/{id}, POST /v1/contacts/actions/upsert |
contacts:read · contacts:write |
| Состояние контрагента | GET /v1/contacts/{id}/balance, …/ledger-entries, …/open-items, GET /v1/aging |
contacts:read |
| Начальный остаток | POST /v1/contacts/{id}/actions/set-opening-balance, …/actions/reverse-opening-balance |
contacts:write |
| Товары и варианты | GET · POST /v1/products, POST /v1/products/actions/upsert, POST /v1/products/{id}/variants |
products:read · products:write |
| Склад | GET /v1/stock-levels, POST /v1/stock-levels/actions/set, GET /v1/stock-movements |
stock:read · stock:write |
| Заказы | GET · POST /v1/orders, PUT /v1/orders/{id}, POST /v1/orders/{id}/actions/cancel |
sales:read · sales:write |
| Накладные | GET · POST /v1/delivery-notes, …/actions/ship, …/actions/cancel |
sales:read · sales:write |
| Счета продаж | GET · POST /v1/sales-invoices, …/{id}/actions/approve, …/{id}/actions/cancel |
sales:read · sales:write · sales:approve |
| Счета закупок | GET · POST /v1/purchase-invoices, …/{id}/actions/approve |
purchase:read · purchase:write · purchase:approve |
| Платежи | GET · POST /v1/payments, POST /v1/payments/{id}/actions/allocate |
payments:read · payments:write |
| Касса и банк | GET /v1/cash-accounts, GET /v1/cash-accounts/{id}/ledger-entries |
cash:read |
| Чеки и векселя | GET /v1/cheques |
cheques:read |
| Электронные документы | POST /v1/sales-invoices/{id}/actions/issue-e-document, GET /v1/e-documents, GET /v1/incoming-e-documents |
edocuments:* |
| Справочники | GET /v1/warehouses, GET /v1/categories, GET /v1/reference/{type} |
catalog:read |
| Поток изменений | GET /v1/changes |
changes:read |
Как связывается цепочка документов. В теле накладной есть orderId, в теле счёта — orderId и
deliveryNoteIds[], а строки сопоставляются через orderLineId и deliveryNoteLineId. Остаток не
хранится счётчиком — он выводится из непогашенных счетов, поэтому отменённый счёт снова освобождает
заказ.
Списание склада происходит в одном месте. Отгрузка и проведение счёта не списывают товар дважды:
итоговое списание равно max(Σ отгрузок, Σ проведённых счетов), и каждый документ пишет только свою
разницу.
Мы пишем и о том, чего нет, чтобы вы не строили на неверном допущении.
Сегодня рабочий путь — опрос GET /v1/changes; scope webhooks:manage есть в каталоге, но эндпоинта нет.
Префикс kp_test_ сегодня лишь метка и пишет в реальные данные. Для экспериментов заведите отдельную компанию.
Контроль параллелизма не добавляется наполовину без опорной колонки версии: иллюзия защиты хуже её отсутствия.
На бете клиент сам создаёт для вас узкий ключ; поток с экраном согласия — в планах.
Чтение, ответ и игнорирование входящих работают; сопоставление строк с товарами пока делается в интерфейсе.
Сроки задолженности (GET /v1/aging) работают; P&L, НДС и асинхронные выгрузки пока отсутствуют.
Изоляция реализована в базе данных. Компании разделяет не фильтр в приложении, а собственный механизм безопасности строк PostgreSQL. Запрос API подключается ролью с минимальными правами, а контекст пишется в базу при открытии соединения — даже неверный запрос не вернёт строку другого бизнеса. Разделение компаний добавляется сверху: ключ привязан к одной компании.
Ключ не хранится. Хранятся только SHA-256-хеш и префикс (kp_live_a1b2c3d4). Открытое значение
показывается один раз при создании; восстановить его нельзя — выпускается новый. В логи ключ не пишется,
только префикс. Отзыв действует немедленно.
Повышения прав нет. Права ключа не превышают роль создавшего его пользователя. Создание счёта с
approve: true требует sales:approve вместе с sales:write; при отсутствии запрос отклоняется, а не
сохраняется черновиком.
Каждое действие оставляет след. Любая запись через API попадает в журнал аудита с префиксом ключа в роли
актора (api:kp_live_a1b2c3d4). Интерфейс, мобильное приложение и API пишут в один журнал.
Персональные данные — узкие права. Поля вроде ИНН, IBAN, имени и адреса возвращаются ключам без права
pii:read в замаскированном виде: видны последние четыре символа, а эндпоинт продолжает работать.
Если интеграции это не нужно — не выдавайте его: лучшая защита, когда данные никуда не уходят.
Как хранить ключ. На сервере, в переменной окружения или менеджере секретов; никогда не в исходном коде,
браузере или мобильном приложении. Для каждой интеграции — свой ключ. В обращении в поддержку передавайте
requestId и Idempotency-Key, но никогда сам ключ.
Доступ не зависит от тарифа. Тарифы отличаются лимитами запросов и квотами, их можно настроить. На этапе беты доступ открывается по заявке.
Нет — сервер является единственным авторитетом. Вы передаёте количество, цену, скидку, ставку НДС, код удержания и валюту. Итоги строки, удержанный НДС, базовую сумму и номер документа считает сервер; поля суммы в строке нет.
Нет. Каждая запись требует Idempotency-Key; ключ сохраняется в той же транзакции, что и запись. Повторный вызов с тем же ключом не выполняет работу заново: вы получаете либо 409 idempotency_replayed и читаете созданную запись через GET, либо 200 с телом первого ответа и флагом replayed: true. Обе формы считаются успехом.
Нет, проведённый документ неизменяем. Исправление — отмена плюс новый документ; отмена пишет сторнирующие проводки. В книгах расчётов, кассы и склада нет UPDATE/DELETE. Перед отменой GET /v1/sales-invoices/{id}/cancel-eligibility покажет препятствия.
Да. Поток GET /v1/changes не различает источник: интерфейс, мобильное приложение и API попадают в один поток. Поток отдаёт только тип и идентификатор записи — детали вы читаете отдельным запросом.
Пока нет — говорим прямо. Ключ с префиксом kp_test_ сегодня лишь метка и пишет в ваши реальные данные. Для экспериментов заведите отдельную компанию; изолированная песочница — в планах.
Пока нет. Рабочий путь сегодня — опрос GET /v1/changes: передавайте полученный meta.checkpoint как since в следующем запросе. Вебхуки — в планах.
Каждый ключ привязан к одной компании и видит только её данные. Для нескольких компаний создайте по ключу на компанию. Переключение компании одним ключом — в планах.
Нет. Кредиты расходуются только на электронные документы: каждый исходящий и входящий документ — 1 кредит. Счета, заказы и накладные внутри системы не расходуют кредиты. Баланс — GET /v1/e-credits.
Восстановить нельзя. Kumpara хранит только SHA-256-хеш и префикс; открытое значение показывается один раз при создании. Потеряли — отзовите старый ключ и создайте новый; отзыв действует немедленно.
В бету принимаются платформы интернет-магазинов, ERP и бухгалтерские программы, бухгалтерские бюро и интеграторы маркетплейсов. Участники получают доступ, заблаговременные уведомления об изменениях контракта и прямой канал обратной связи.