Payroll

Крипто-payroll для подрядчиков и распределённых команд

Каждый в реестре указывает актив, сеть и адрес. Расчётный период — это один ордер на человека, котировка по сумме «на руки», оплата из вашего казначейства и сверка по вашему же идентификатору сотрудника.

  • На выплатуодин ордер, один депозит
  • Сумма на рукикотировка через amount_to
  • Защита от двойной выплатыIdempotency-Key на выплату
  • Казначействоостаётся вашим до оплаты каждой выплаты

Собрано на/v1/validate-address/v1/partner/quotes/v1/partner/orders

Расчётный период — это один ордер на человека, посчитанный по сумме, которую он должен получить. Каждый в реестре указывает свой актив, сеть и адрес; вы оплачиваете каждую выплату из казначейства; API конвертирует и доставляет. Ничего не предоплачивается, ничего не смешивается в общий котёл, и деньги остаются вашими до момента отправки каждой выплаты.

  • Котировка через amount_to: сумма в расчётном листке равна сумме, которая придёт.
  • Idempotency-ключ на выплату — повторный запуск не платит никому дважды.
  • Сбой у одного (например, сумма ниже минимума провайдера) не останавливает весь расчёт.
  • Планировщика в API нет: когда запускать расчёт, решает ваш cron.

Расчётный период по шагам

  1. Реестр

    На каждого: сумма на руки, актив выплаты, сеть, адрес. Проверяйте адрес через GET /v1/validate-address при добавлении и ещё раз перед расчётом — опечатка, найденная в день выплаты, дорого стоит.

  2. Котировка каждой строки по сумме на руки

    from_asset — актив вашего казначейства, to_asset — актив сотрудника, amount_to — то, что ему причитается. Предложение отвечает суммой FromAmount, то есть стоимостью расчёта, ещё до того, как сдвинулась хоть одна монета.

  3. Ордер на каждого

    client_order_id — ваша пара период + сотрудник, и Idempotency-Key строится из неё же. Перезапуск наполовину выполненного расчёта вернёт уже созданные ордера как есть, а не удвоит их.

  4. Оплата выплат

    Каждый ордер возвращает свой DepositAddress и точную сумму AmountFrom. Казначейство отправляет на каждый — это та часть, которую API не может сделать за вас, потому что он никогда не держит ваши средства.

  5. Закрытие расчёта

    Опрашивайте ордера до финального статуса. DONE даёт AmountToReceived и TxID для расчётного листка; всё остальное — строка на повтор с новой котировкой.

Оплачивайте сразу. Предложение живёт пять минут, а депозитное окно провайдера обычно 30–60 минут. Котировка → ордер → оплата должны быть одной автоматической последовательностью; расчёт, посчитанный в понедельник и оплаченный во вторник, — это набор ордеров в TIME_EXPIRED.

Цикл расчёта

const BASE = "https://api.swapzilla.io";
const head = { "X-API-Key": process.env.SWAPZILLA_KEY, "Content-Type": "application/json" };

async function payout(run, person) {
  const q = new URLSearchParams({
    from_asset: "USDT", from_network: "TRC20",
    to_asset: person.asset, to_network: person.network,
    amount_to: String(person.net), rate_type: "fixed",
  });
  const { offers } = await fetch(`${BASE}/v1/partner/quotes?${q}`, { headers: head })
    .then((r) => r.json());
  if (!offers?.length) throw new Error(`нет предложения для ${person.id}`);

  const order = await fetch(`${BASE}/v1/partner/orders`, {
    method: "POST",
    headers: { ...head, "Idempotency-Key": `${run}:${person.id}` },  // тот же ключ при повторе
    body: JSON.stringify({
      offer_id: offers[0].ID,
      to_address: person.address,
      refund_address: process.env.TREASURY_ADDRESS,                 // неудачи возвращаются домой
      client_order_id: `${run}:${person.id}`,
      expected_to_amount: person.net,
    }),
  }).then((r) => r.json());

  return order;      // DepositAddress + AmountFrom — то, что отправляет казначейство
}

// Пяти параллельных строк достаточно: провайдеры троттлят всплески, а расчёт
// зарплаты — не гонка. Оборачивайте каждую строку, чтобы один сбой был одним
// несостоявшимся расчётным листком, а не сорванным расчётом целиком.

Учёт по расчёту

Вопрос финансистаГде ответ
Сколько нам стоил этот расчёт?Сумма AmountFrom по всем ордерам расчёта — известна до оплаты.
Получил ли подрядчик деньги?Статус его ордера; в DONE лежат AmountToReceived и TxID.
К какому листку относится ордер?client_order_id — заданная вами пара период:сотрудник.
Покажи весь расчётGET /v1/partner/orders?page=1&limit=100 с фильтрацией по префиксу периода на вашей стороне.
У кого-то застряло — к кому идти?К провайдеру, называя ProviderOrderID; сначала POST /orders/{id}/refresh — вдруг статус уже сдвинулся.

Честные ограничения

Не входитЧто это значит для расчёта
Одна оплата на весь расчётУ каждого ордера свой депозитный адрес, поэтому казначейство отправляет по одной транзакции на выплату. Комиссии сети закладывайте соответственно.
Планировщик«Платить первого числа» в API нет. Расчёт запускает ваш планировщик, API его исполняет.
Выплаты в фиатеТолько крипта в крипту. Зарплата, согласованная в евро, переводится вашим источником курса до котировки.
Договоры, счета, налоговые формыЭто не payroll-платформа: SwapZilla перемещает и конвертирует стоимость, документооборот остаётся в вашей системе.
KYC, AML и проверка получателей по санкционным спискамAPI этого не делает. Всё, что требует ваш комплаенс, приходит извне.

Кто так платит

  • Студии и агентства с удалёнными подрядчиками в десятке стран, где каждый предпочитает свой актив и свою сеть.
  • Продуктовые команды, платящие в стейблкоинах из одного казначейского актива, без кошелька под каждую сеть.
  • DAO и опенсорс-фонды, где каждая выплата должна прослеживаться до конкретного TxID.
  • Все, кто перерос таблицу и горячий кошелёк, но не хочет отдавать фонд оплаты труда кастодиану.

Вопросы

Можно оплатить весь расчёт одной транзакцией?

Нет. У каждого ордера свой депозитный адрес у провайдера, поэтому оплата — одна транзакция на выплату. Это прямое следствие некастодиальности: пополняемого баланса в SwapZilla нет, а значит, и раздавать не из чего.

Как не заплатить дважды при повторе?

Передавайте Idempotency-Key, собранный из периода и сотрудника — например 2026-08:emp-114, — и используйте его при каждом повторе этой выплаты. Повторный запрос вернёт тот же ордер, а не создаст второй.

Можно платить каждому в своей монете?

Да, в этом и смысл. Актив и сеть выплаты задаются в каждом ордере, поэтому один расчёт может закрыть USDT в Tron, BTC и ETH из одного казначейского актива — конвертацию делает провайдер.

Что если одна выплата не прошла?

Не проходит только она. Обычные причины — сумма ниже MinFromAmount провайдера или отключённый актив; и то, и другое возвращается как 400 при создании ордера, до движения денег. Пересчитайте эту строку или заплатите в другом активе.

Держит ли SwapZilla фонд оплаты труда между расчётом и выплатой?

Никогда. Средства уходят из вашего казначейства только когда вы сами отправляете их на депозитный адрес конкретного ордера, а провайдер выплачивает подрядчику напрямую. Ни остатка, ни эскроу, ни страницы баланса.

Это SolarStaff или Deel для крипты?

Не как продукт: те — payroll-платформы с договорами, счетами и комплаенсом. Это платёжный рельс под такой платформой: котировка, конвертация и доставка средств на личный кошелёк каждого, тогда как реестр, документы и график остаются в вашей системе.

Что ещё собирают на этом же ключе

Как получить ключ

Зарегистрируйтесь в партнёрском кабинете — партнёрский id и api_key для заголовка X-API-Key выпускаются сразу. Ключ становится рабочим после активации: напишите в @swapzilla_support_bot и коротко опишите интеграцию. Все эндпоинты, поля и статусы — в документации partner API.