Skip to main content
This documents the Revenue Split feature: attaching optional instructions to a single deposit so that, once that specific deposit succeeds, part of it is automatically routed to another destination — either an internal Yativo account’s wallet (a “sub-account”) or one of your saved payout beneficiaries (bank account / crypto address). There is no standing, account-level configuration. You decide per deposit, on the deposit-creation call itself, whether to split it at all, and if so, how much and to whom. Two deposits from the same account can use two completely different destinations, or no split at all — nothing carries over between them. Two ways to size the split:
  • split_type: "percentage" (default) — split off a percentage of the deposit’s credited amount, capped by the platform’s max_split_percentage (§1).
  • split_type: "fixed" — split off a fixed amount in the deposit’s own currency, via fixed_amount. Must be less than or equal to the deposit’s net credited amount — if it isn’t, deposit creation is rejected up front (§2 errors) rather than letting the deposit succeed with a split that can never actually clear.
All sample payloads below are anonymized for safe sharing.

Environments

  • Sandbox API: https://smtp.yativo.com
  • Production API: https://api.yativo.com

Authentication

Every endpoint needs an authenticated request, and the account must have passed KYC. Server-to-server requests use your team’s API key and secret:
The Yativo dashboard sends the signed-in user’s Authorization: Bearer <ACCESS_TOKEN> instead. Since 15 October 2026, bearer tokens are only accepted from the dashboard, and the legacy POST /api/v1/auth/login (account_id + app_secret) flow is deprecated. Don’t send a bearer token together with the key pair. See Authentication.

How It Works

  1. You create a deposit as usual (POST /api/v1/wallet/deposits/new), and attach an optional revenue_split object to that same request body.
  2. If present, it’s validated immediately (destination ownership, percentage range/cap) — an invalid revenue_split payload rejects the whole deposit-creation call before anything is created.
  3. The deposit proceeds through its normal payment flow (checkout URL, wire instructions, etc. — unchanged). Splitting never happens at creation time.
  4. Once — and only once — that specific deposit’s status flips to success (confirmed by the payment provider), the requested percentage is:
    • transferred instantly to another Yativo account’s wallet (destination_type: internal_wallet), or
    • paid out to one of your saved beneficiaries (destination_type: beneficiary) — through the exact same payout pipeline as POST /api/v1/wallet/payout, so normal processing times for that beneficiary’s rail apply.
  5. The attempt (successful, failed, or skipped) is recorded and visible via GET /api/v1/revenue-split/executions.
You keep the remainder of the deposit in your own wallet as usual — a split only ever moves the percentage you requested for that one deposit, never the whole amount, and never anything from any other deposit.

Important constraints

  • Opt-in, per deposit. Omit revenue_split entirely and nothing changes about that deposit — 100% of it lands in your wallet as normal. There’s nothing to “turn off” elsewhere; just don’t send it.
  • No FX conversion. A beneficiary split pays out in the same currency the deposit is credited in. If your beneficiary’s rail requires a different settlement currency, use the regular manual withdrawal flow instead for that leg.
  • The beneficiary must belong to you. beneficiary_payment_method_id must reference a payment method already saved under your own account (from POST /api/v1/beneficiary/form/create or the withdrawal beneficiary endpoints).
  • The sub-account must be a different Yativo account. An internal_wallet split’s destination_user_id cannot be your own user_id — it’s another Yativo platform account, not one of your own Customer records.
  • Percentage is capped platform-wide. An admin sets a maximum split_percentage any single deposit is allowed to request (default 100%). GET /api/v1/revenue-split/settings tells you the current cap.
  • Only deposits you actively create can be split. This only applies to deposits created through POST /api/v1/wallet/deposits/new (the endpoint documented below). Funds that arrive passively into a standing virtual account or crypto wallet address — i.e. you never called an API to create that specific incoming payment — have no revenue_split to attach and are never split.
  • Idempotent and safe on retries. A given deposit only ever triggers its split once — repeated webhook deliveries or status re-saves for the same deposit will not double-split it.

Response Envelope

Every endpoint returns one of two shapes. Non-paginated success/error:
Paginated list (executions):
Gotcha — HTTP status on success is always 200. The status_code field inside the JSON body is decorative (may show 201, etc.); branch on the status field (“success” vs “failed”), not the raw HTTP status, to detect success. Error responses do use a real, meaningful HTTP status.
Gotcha — decimal fields are strings. split_percentage, source_amount, fixed_amount, split_amount, payout_fee_amount, net_payout_amount are MySQL decimal columns and are serialized as strings (e.g. "5.00"), not JSON numbers. Run them through parseFloat() / Number() before doing arithmetic.

1) Check Platform Settings

Read-only. Tells you whether the feature is enabled, and the maximum percentage any single deposit’s split can request.

Endpoint

Sample Response

eligible_currencies: null means every currency is eligible. If it’s an array (e.g. ["USD", "EUR"]), a revenue_split on a deposit in any other currency is silently never executed (the deposit itself still succeeds normally).

2) Create a Deposit With a Revenue Split

Endpoint

This is the normal deposit-creation endpoint — gateway, amount, currency, customer_id, return_url, and any gateway-specific fields all work exactly as they do without a split. revenue_split is the only new, fully optional field.

Request Body — Split to an Internal Sub-Account

Request Body — Split to an External Beneficiary

Request Body — Fixed Amount Instead of a Percentage

fixed_amount is in the deposit’s own currency (ARS here) and must be <= the deposit’s net credited amount (calc.credited_amount — the amount after deposit fees, not the raw amount you sent). Requesting a fixed amount larger than that always fails deposit creation with a 400 (§2 errors) — it can never be satisfied by retrying.

Request Body — No Split (unchanged, existing behavior)

revenue_split fields

Sample Response

Identical to a normal deposit-creation response, plus an echoed revenue_split block confirming what was captured:
Redirect the payer to deposit_url (or show the returned wire/QR/reference instructions) so they can actually complete payment, same as always.

Errors

Sent back as a normal deposit-creation error — the deposit is not created at all if revenue_split fails validation: After that field-level validation passes, the split is also previewed against the deposit’s actual computed credited amount before the deposit is created (simulating the eventual payout’s fees and the destination gateway’s min/max limits), so a split that could never clear isn’t allowed to exist as a “pending forever” liability:

3) Wait for the Deposit to Complete

Creating the deposit never credits your wallet, and never executes the split, by itself. Every payin rail is asynchronous: the deposit is created pending/processing, and only flips to success once the payment provider confirms funds landed — which Yativo receives via that provider’s own webhook. The split fires at that exact success transition, the same moment your own wallet gets credited. Poll for the transition:
status is one of pending, processing, success, failed, cancelled, expired. The instant it flips to success, check §4 below — the resulting split execution is already there.

4) List Split Execution History

Paginated audit log of every split that’s run (or was skipped) on your deposits, most recent first. Use this to reconcile “where did the rest of my deposit go” or to confirm a specific deposit’s split actually landed.

Endpoint

Sample Response

source_deposit_id matches the id from the deposit-creation response (deposit_data.id) — that’s how you tie an execution back to the deposit that triggered it. source_amount is the deposit’s credited amount the percentage was applied to; split_amount is what actually moved.

status values


End-to-End Example (JavaScript)


Quick Reference


Admin

Platform admins manage the global guardrails and oversee every business’s split executions from the admin panel:
  • Default Settings — /admin/revenue-split-settings — enable/disable the feature globally, set the max split percentage any deposit can request, minimum deposit amount, and eligible currencies.
  • Executions — /admin/revenue-split-executions — the full audit trail across every business, filterable by status and business.