Что такое API журнала двойной записи для маркетплейсов?
API журнала двойной записи фиксирует движение денежных средств на маркетплейсе в виде сбалансированных неизменяемых проводок, чтобы вы всегда знали, кто, кому и за что должен.
Маркетплейс может демонстрировать отличные показатели в таблице заказов orders, но при этом ошибаться в расчетах с деньгами. В заказе указано: „Оплачено“. В панели продавца отображается баланс. Однако ни одна запись в этой таблице не доказывает, сколько именно наличных средств находится у платформы, сколько она должна каждому из продавцов, какая доля платежа является комиссионным доходом или какой объем НДС подлежит уплате. API журнала двойной записи создан для того, чтобы корректно отражать эти финансовые последствия, обрабатывая каждую сбалансированную транзакцию отдельно.
Простыми словами, API журнала двойной записи — это программируемая бухгалтерская система. Ваше приложение отправляет в нее финансовое событие (например, успешное удержание платежа или одобренную выплату), а журнал записывает это событие в виде проводки с равными дебетами и кредитами по именованным счетам. Он не переводит деньги сам. Он фиксирует реальное положение дел с деньгами, которые переместились в другом месте.
Что в данном контексте означает «журнал двойной записи»
Журнал — это история изменений по счетам, а не таблица, хранящая текущий баланс. Работающий журнал опирается на три взаимосвязанные концепции:
- Счет (Account): именованная финансовая позиция, такая как дебиторская задолженность платежного процессора, кредиторская задолженность перед продавцом, комиссионный доход или НДС к уплате.
- Транзакция (Transaction/journal): одно атомарное финансовое событие, содержащее несколько сбалансированных строк.
- Запись (Entry/posting): отдельная дебетовая или кредитовая строка внутри этой транзакции.
Инвариант, на котором держится вся архитектура, прост: общая сумма дебетов равна общей сумме кредитов для каждой транзакции и каждой валюты. API журналов обычно отклоняют несбалансированную запись еще до того, как она попадет в хранилище. В документации Modern Treasury транзакция журнала определяется как операция, затрагивающая два или более счета с как минимум одним дебетом и одним кредитом равной общей суммы, причем проведенная транзакция считается неизменяемой.
Двойная запись не означает ровно две строки. Одна продажа на маркетплейсе часто требует одного дебета и нескольких кредитов. Именно этот момент люди понимают неправильно чаще всего.
Зачем маркетплейсу нужен журнал, а не просто таблица платежей
Маркетплейс одновременно поддерживает множество финансовых взаимоотношений. Покупатель платит. Процессор производит расчет. Платформа может временно удерживать средства. Продавец зарабатывает свою часть. Платформа оставляет себе комиссию. Возникает обязательство по налогам. Может удерживаться резерв. Позже выплата переводит деньги наружу, а возвраты или чарджбеки частично обращают эти операции вспять.
Таблица payments может рассказать о коммерческом статусе заказа. Но она не способна достоверно показать:
- какой объем дебиторской задолженности процессора или наличных средств у вас есть
- сколько вы должны каждому продавцу
- какой доход принадлежит платформе
- сколько НДС подлежит уплате и в какой стране
- какие суммы зарезервированы на случай возвратов или споров
- уменьшила ли выплата задолженность перед правильным продавцом
- совпадают ли расчеты процессора с ожиданиями платформы
В руководстве Nordlet по API журналов двойной записи для учета на маркетплейсах эта граница проведена четко: таблицы приложения описывают состояние продукта, а журнал фиксирует финансовые последствия этого состояния. Там же приводится мысль, которую стоит повторить: отчеты платежных процессоров являются исходными данными для сверки, а не полноценной бухгалтерией по методу двойной записи.
Пример продажи на маркетплейсе
Допустим, покупатель платит €100, продавцу причитается €85, а комиссия платформы составляет €15. Для наглядности опустим НДС и комиссии процессора.
| Счет | Дебет | Кредит | Обоснование |
|---|---|---|---|
| Дебиторская задолженность платежного процессора | €100 | Процессор должен платформе удержанный платеж | |
| Кредиторская задолженность перед продавцом | €85 | Платформа должна продавцу | |
| Комиссионный доход | €15 | Платформа заработала комиссию | |
| Итого | €100 | €100 | Баланс сошелся |
Важная классификация здесь заключается в том, что сумма €85, которую должны продавцу, является обязательством (liability), а не доходом платформы. Согласно концептуальной основе МСФО, обязательство — это существующая обязанность передать экономический ресурс. Маркетплейс не должен отражать всю выручку от продажи продавца как собственный доход только потому, что покупатель заплатил через него. Выступаете ли вы в роли агента, принципала или налогоплательщика, обязанного у налог (deemed supplier), меняет порядок учета, но механизм журнала остается прежним.
Когда продавец получает право на выплату, никакой новый доход не признается. Вы погашаете обязательство:
| Счет | Дебет | Кредит |
|---|---|---|
| Кредиторская задолженность перед продавцом | €85 | |
| Банковский или расчетный счет для выплат | €85 | |
| Итого | €85 | €85 |
Если процессор удерживает комиссию в размере €3 перед проведением расчетов, движение денежных средств превращается в проводку из трех строк: €7 на банковский счет, €3 на расходы по обработке платежей и €100 с дебиторской задолженности процессора. Каждое изменение позиции имеет источник и назначение.
Как работает API: пошаговый разбор
1. Ваше приложение обнаруживает бизнес-событие. Происходит удержание платежа, выполнение заказа, одобрение выплаты, оформление возврата, открытие чарджбека или поступление расчетов. Ваша база данных по-прежнему отвечает за операционное состояние. Журнал фиксирует финансовый эффект.
2. Вы отправляете структурированный запрос. Обычно он содержит тип события, сумму и валюту, ID заказа или платежа, идентификаторы покупателя и продавца, комиссию, налоговые данные, задействованные счета, даты совершения и проведения (effective and posting dates), ключ идемпотентности, а также метаданные, ссылающиеся на записи процессора и продукта. Пример публичного API Nordlet демонстрирует концептуальный запрос на продажу с указанием ID продавца, типа продажи, суммы, валюты, а также страны и ставки НДС.
3. API выполняет валидацию. Он проверяет, что дебет и кредит сходятся, счета существуют и допускают проводки, валюта поддерживается, сумма использует точную работу с наименьшими денежными единицами (minor-unit handling), ключ идемпотентности не используется повторно для другого результата, период открыт и присутствуют необходимые метаданные. Неуспешная проверка не оставляет в системе частичных проводок.
4. Проведение происходит атомарно. Транзакция записывается целиком как единое целое. Возникновение ситуации, когда дебет записан, а соответствующий кредитный сбой произошел, исключено. Для маркетплейса частичное разделение может создать видимость баланса продавца без соответствующих денежных средств или отразить комиссию без обязательств перед продавцом.
5. Балансы и отчеты формируются на основе журнала. После проведения вы можете читать остатки по счетам, ожидаемые и доступные балансы продавцов, пробный баланс (trial balance), операции по главной книге, сводки по НДС и историю на прошлую дату. Баланс продавца должен собираться заново из проводок, а не считываться из изменяемого поля.
6. Вебхуки уведомляют ваш продукт. События вроде sale_invoice.paid, проведенного журнала, доступности выплаты или исключения при сверке отправляются вам. Обрабатывайте их идемпотентно. Вебхук — это уведомление, а не разрешение применить финансовое событие во второй раз. В соглашениях об API подробно описаны области видимости (scopes), ключи идемпотентности, структура ошибок и подпись вебхуков.
Балансы продавцов — это не просто одно число
Большинство маркетплейсов сталкиваются с проблемами, когда начинают трактовать баланс продавца как единую цифру. Деньги должны находиться в определенных состояниях:
| Состояние | Значение |
|---|---|
| Ожидает (Pending) | Продавец может иметь право на средства, но условия их высвобождения еще не выполнены |
| Доступно (Available) | Средства готовы к выплате |
| Зарезервировано (Reserved) | Удержано на случай возвратов, отмен или споров |
| Выплачено (Paid out) | Обязательство погашено путем перевода |
| Отрицательное (Negative) | Возвраты, чарджбеки или комиссии превышают доступные средства |
Модели процессоров отражают этот подход. Раздельная логика счетов и переводов Stripe позволяет платформе пополнять собственный счет, а затем переводить части средств на связанные счета, причем комиссии, возвраты и чарджбеки ложатся на баланс платформы. Модель маркетплейса Adyen различает счета балансов пользователей, удерживающие средства до выплаты, и счет обязательственного баланса (liable balance account), способный поглощать отрицательные остатки от возвратов или чарджбеков. Это полезные входящие данные для вашего журнала, но они не заменяют вашу полную бухгалтерскую модель.
Выплаты и заработок продавцов происходят в разное время
Продавец может заработать деньги в понедельник, а получить их в следующий понедельник. За это время заказ успевает выполниться, удерживается резерв, формируется пакет выплат, процессор производит расчет за вычетом комиссий, и поступает банковский перевод. Журнал должен фиксировать каждый этап, а не просто перезаписывать заказ финальным статусом „оплачено“. Именно это позволяет объяснить временные расхождения между активностью по заказам, правами продавца, расчетами, инициацией выплаты и поступлением средств в банк.
Возвраты и чарджбеки: отменяйте, а не перезаписывайте
Возвраты и чарджбеки — это новые события, привязанные к исходному платежу. В неизменяемом журнале вы исправляете ошибки с помощью сторнирующей проводки с последующей корректирующей, поэтому оригинал остается видимым для аудита. Modern Treasury рассматривает проведенные транзакции как неизменяемые и поддерживает ключи идемпотентности во избежание дублирования объектов при повторных попытках.
Возврат обычно уменьшает наличные средства или дебиторскую задолженность покупателя, сторнирует кредиторскую задолженность перед продавцом, может частично отменять комиссию в зависимости от политики платформы, корректирует налоги и может задействовать резерв на возвраты. Чарджбек уменьшает денежные средства или дебиторскую задолженность процессора, может возобновить задолженность продавца или платформы, фиксирует расходы по спору и комиссию процессора, а также переводит средства через резервный счет.
Сверка: увязка журнала с реальными деньгами
Журнал может быть внутренне сбалансированным и при этом ошибаться в отношении реального мира. Сверка сопоставляет внутренние записи с внешними доказательствами: отчетами процессора о расчетах, выписками из банков, файлами выплат, записями о возвратах и спорах.
Рабочий цикл выглядит следующим образом:
- Импорт пакета расчетов или банковской выписки.
- Сопоставление каждой строки с заказом, платежом, возвратом, комиссией, выплатой или спором.
- Сравнение ожидаемой валовой суммы, удержаний, резервов и чистой суммы.
- Проведение подтвержденных движений в журнал.
- Направление несопоставленных элементов на специальный транзитный счет (suspense account).
- Расследование исключений.
- Закрытие периода.
Материалы по сверке от Nordlet описывают именно этот процесс: импорт пакетов расчетов, сопоставление строк списаний и возвратов, а также направление несопоставленных поступлений на транзитный счет вместо того, чтобы угадывать назначение счета-фактуры. Важны две проверки, и ни одна из них не заменяет другую: валидация методом двойной записи проверяет, сходится ли каждая проводка, а сверка проверяет, согласуется ли она с процессором, банком и бизнес-событием.
Архитектурные нюансы, от которых зависит успех
Идемпотентность. Привязывайте ключ к стабильному событию, например payment_captured:pi_123. Повторная попытка возвращает исходный результат, а не второй журнал.
Атомарность. Все строки одного события проводятся одновременно, либо не проводятся вообще.
Неизменяемость и сторнирование. Проведенная история не редактируется через обычные обновления. Исправления создают связанные записи, сохраняющие первоначальную сумму, дату, классификацию, причину и автора.
Точность в работе с деньгами. Никакой двоичной плавающей запятой. Используйте целочисленные наименьшие денежные единицы или точные десятичные дроби, явное указание валюты и детерминированное правило округления для разделения сумм. Если разделить €100 между продавцами и комиссиями без такого правила, потерянный цент разрушит ваш баланс.
Даты совершения и проведения (Effective vs posting dates). Момент оплаты покупателем, момент заработка продавца, момент расчетов банка и момент проведения записи — это разные даты. Их смешивание делает отчетность за период и налоговые сроки недостоверными.
Мультивалютность. Дебет и кредит должны сходиться внутри конкретной валюты. Конвертация требует явного события курса с указанием счетов для комиссии, округления и возможных курсовых разниц. Наличие поля currency не превращает журнал в форекс-движок.
Чего API журнала делать не будет
Он не определит ваш план счетов за вас. Вам по-прежнему придется самостоятельно решать, выступаете ли вы принципалом или агентом, когда именно зарабатывается комиссия, какая из сторон несет комиссии процессора, как возвраты влияют на комиссию, а также как рассчитывается и отчитывается НДС. Рекомендации Nordlet сводятся к тому, чтобы сначала составить карту денежных потоков, набросать план счетов, привлечь бухгалтера для его проверки, а затем внедрить один полный цикл от заказа до выплаты и сверки перед началом масштабирования.
Он не решит налоговые вопросы. НДС зависит от местонахождения покупателя и продавца, типа продукта, статуса регистрации и правил для лиц, обязанных у налог (deemed-supplier rules); руководство по НДС в ЕС описывает, что движок вычисляет автоматически, а что отмечает для проверки человеком. Налоговый функционал Nordlet ориентирован на ЕС и ЕЭЗ, поэтому он не распространяется на налог с продаж в США или электронное выставление счетов в Латинской Америке. Он также не устраняет операционную неопределенность: истекло ли окно возврата, стоит ли заблокировать выплату, является ли платеж мошенническим. Это ваши решения. Журнал лишь фиксирует их финансовый результат.
Место Nordlet в системе
Nordlet — это бухгалтерский API, созданный для платформ и маркетплейсов, с неизменяемым журналом двойной записи, выплатами, поддержкой НДС в ЕС, REST-эндпоинтами, типизированными SDK и вебхуками, доступными через единый интерфейс. Его отличительная особенность заключается во внедрении бухгалтерии прямо внутрь вашего продукта, а не в использовании стороннего чекаута. На момент написания статьи продукт находится на стадии раннего доступа с песочницей для партнеров по проектированию, поэтому воспринимайте его как яркий пример категории и перед принятием окончательного решения обязательно оценивайте его производственную зрелость, время безотказной работы и юрисдикционный охват для вашего собственного кейса.
Для разработчиков маркетплейсов и платформ полезной ментальной моделью является разделение между перемещением денег и финансовой истиной. Ваш процессор перемещает деньги. API журнала двойной записи фиксирует, кто кому должен, что вы заработали, какие налоги и резервы вы удерживаете и сходятся ли данные внешнего мира с вашей бухгалтерией.
FAQ
Является ли API журнала двойной записи платежным процессором?
Нет. Процессор авторизует, удерживает, проводит расчеты и иногда выплачивает средства. API журнала фиксирует бухгалтерские последствия этих событий. Большинство маркетплейсов используют оба инструмента: процессор вроде Stripe или Adyen для перемещения денег и журнал для бухгалтерии.
Могу ли я просто использовать панель управления процессора в качестве главной книги?
Вы можете попробовать, но в конечном итоге это приведет к провалу аудита. Отчеты процессора показывают списания, комиссии, переводы и расчеты, но они обычно не отражают ваши полные обязательства перед продавцами, налоговые обязательства, расходы, не связанные с процессором, или бухгалтерские корректировки. Рассматривайте их как входящие данные для сверки.
Означает ли сбалансированный журнал, что моя бухгалтерия в порядке?
Только то, что ваши проводки удовлетворяют правилу дебета и кредита. Идеально сбалансированная транзакция все равно может быть проведена не на тот счет, не тому продавцу или с неверным налоговым учетом. Баланс необходи、м, но недостаточен. Остальное проверяется в процессе сверки.
Если журнал неизменяем, как исправить ошибки?
Вы проводите сторнирующую проводку, а затем исправленную. Оригинал остается видимым, и в этом вся суть. Неизменяемость защищает аудиторский след, но она не запирает ваши ошибки внутри системы.
Делает ли бухгалтерский API мое приложение автоматически соответствующим требованиям законов (compliant)?
Нет. Он обеспечивает бухгалтерскую структуру и формирует пригодные к использованию отчеты. Юридическое соответствие по-прежнему зависит от вашей юрисдикции, роли по договору, налогового режима, платежных правил, процедур KYC и AML, а также обязательств по отчетности.