Skip to main content
This guide covers the two core money-movement flows:
  • Payin (deposits/collections) — collect funds from a payer in a local currency and credit the resulting balance to one of your wallets.
  • Payout (withdrawals) — send funds from your wallet to a beneficiary in a supported destination country/currency.
Both are driven by a payment method catalog: each method is tied to a country + currency and carries its own limits, required fields and fees.

Authentication

Every endpoint below 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. The only exception is the hosted-checkout channel endpoints (/api/payin/channels, /api/payin/checkout), which back the hosted payin page and are called with a deposit_id rather than user credentials. All responses use the standard envelope: { "status": "success" | "failed", "status_code": ..., "message": "...", "data": { ... } }. On failure, data.error holds the reason.

Idempotency

Send an Idempotency-Key header (any unique string, such as a UUID) on every POST, PUT, PATCH or DELETE so retries are safe:
  • Repeating a request with the same key and the same body within 60 minutes returns the original response; nothing is executed twice.
  • Reusing a key with a different body returns 409 Idempotency key reuse detected with a different request payload.
  • Sending the same key while the first request is still running returns 409 A matching request is already being processed.
  • Responses with a 5xx status aren’t stored, so you can retry them with the same key.
If you don’t send a key, Yativo derives one from the request body. Two identical requests within 60 minutes are then treated as a retry and the second gets the first one’s response. To send two genuinely separate payouts with the same details, give each its own Idempotency-Key.

Rate limits

Each account can make up to 50 read requests (GET) per second and, separately, 20 write requests (POST/PUT/PATCH/DELETE) per second. Polling payout or deposit status doesn’t use up your write allowance. Over the limit you get 429 Too Many Requests; wait for the number of seconds in the Retry-After header. Some endpoints have their own lower limit, which their guides list. Enterprise plans aren’t subject to the general limit.

Payin (Deposits)

Card and bank-transfer collection that settles as USDC or EURC is Onramp, a standalone product. Use POST /v1/onramp — it is not listed as a payin method and cannot be created with POST /v1/wallet/deposits/new.

1. Discover payin methods

Returns the payin methods available to your account. Each method includes its id (used as gateway when creating a deposit), currency, base_currency (the wallet currencies you may credit), and minimum_deposit / maximum_deposit limits. Filter the countries/currency helpers to build a country → currency → method picker.

2. (Optional) Get a quote

Generate a locked quote and pass its quote_id when creating the deposit to fix the amount/rate. Quotes expire; regenerate when expired.

3. Create a deposit

A method may declare extra required fields (required_extra_data.form_fields) — e.g. payer phone/document details — which are validated on submission. Read them from the method record and include them in the body. The response echoes a fee/settlement breakdown and, depending on the method, one of:
  • deposit_url — a hosted checkout link where the payer selects a channel and sees wire instructions (see step 4); or
  • wire instructions returned inline (bank name, account number, reference, etc.) for a direct bank-transfer method.

4. Hosted checkout channel selection

For methods that use the hosted page, the payer’s channel/network is chosen against the deposit:
GET channels lists the active channels (bank transfer, mobile money, …) and, where relevant, their networks, filtered by country/currency/amount. POST checkout finalises the deposit with the payer’s choice:

5. Deposit completion

Deposits complete asynchronously when the payer’s funds settle. Rely on webhooks for the authoritative status change (see the Webhook Guide) — the credited wallet balance is updated automatically once the payin is confirmed. On sandbox you can settle a pending deposit (or fail it) without waiting for a provider, and credit a test wallet directly. See Testing on sandbox.

Get a deposit

Returns one of your deposits. depositId is the deposit’s id (deposit_data.id in the create response, payload.id in deposit.* webhooks) or its deposit_id reference. The object is the same as an item from GET /api/v1/wallet/deposits, including status and depositGateway (as deposit_gateway). Use it to confirm a deposit before you fulfil an order: after a deposit.updated webhook, or when the payer comes back to your return_url. The query string on return_url is not proof of payment. Team members need the Deposits → view permission.

Payout (Withdrawals)

A payout sends funds to a beneficiary using one of that beneficiary’s saved payout methods. Set the beneficiary up once, then reference its payout method on each payout.

1. Discover payout methods

Filter by country and currency. Each method includes the id you will use as gateway_id when saving a beneficiary payout method, plus the fields that method requires.

Helpers for NGN and mobile-money destinations

  • GET /banks/ngn lists Nigerian banks as { "code", "name", "logo" }. Use code as the bank code in an NGN beneficiary’s payment_data.
  • POST /banks/ngn/lookup with { "account_number": "0123456789", "bank_code": "058" } returns { "account_number", "account_name" } for that account, so you can show the account holder’s name before saving the beneficiary. account_number must be 10 digits. An account that can’t be verified returns 422 Unable to verify this bank account.
  • GET /payout/providers lists mobile-money providers (default) or banks (mobile_money=false) for a destination country (ISO 3166-1 alpha-2), as { "code", "name" }.
If the list can’t be loaded right now these return 502; retry later.

2. Create a beneficiary

Manage beneficiaries with GET /api/v1/beneficiaries/list, GET/PUT/DELETE /api/v1/beneficiaries/{id}, and PUT /api/v1/beneficiaries/{id}/archive · /unarchive.

3. Add a payout method to the beneficiary

gateway_id is the payout method from step 1; payment_data carries that method’s required destination fields. The created record’s id is the beneficiary_details_id used to run a payout. List them with GET /api/v1/beneficiaries/payment-methods/all. You can only read, update or delete your own payout methods, and a payout can only use one of them: any other id returns 404 (Record not found) or Invalid payment method configuration.

4. Send a single payout

The standard payout endpoint is:
  • Sandbox: https://smtp.yativo.com/api/v1/payout/simple
  • Production: https://api.yativo.com/api/v1/payout/simple
Fix the exchange rate and fees via POST /api/v1/exchange-rate or POST /api/v1/sendmoney/quote, then submit:

Direct payload (without quote / direct send)

If you are not using a quote, provide the amount directly:
The payout debits your wallet (including fees) and submits the transfer. The response returns the created payout with its id and status.

Wallet payout: choose send or receive amount

By default amount is what you send from your debit_wallet. Fees are added on top, and the customer receives amount converted at the payout rate. To set the exact amount the customer receives in the payout currency, add "amount_type": "receive":
Every payout goes through compliance checks before it is sent. When you include an invoice, it is reviewed alongside the payout, so make sure its total and beneficiary match the payout. A payout that needs a closer look stays pending until the review is finished. In receive mode, the send amount and fees are calculated from the requested receive amount, and your wallet is debited for both. Minimum and maximum limits still apply. Every response includes send_amount (in the wallet currency), customer_receive_amount (in the payout currency), and debit_amount (the total debited, fees included). Receive mode also works with payout quotes. See Payouts by Receive Amount.

5. Send a batch payout

Each item takes amount (required, at least 1), beneficiary_details_id (required), and optional beneficiary_id and reference (up to 140 characters, same rules as on a single payout). Each item is processed independently; the response reports per-item results and errors so a single bad row doesn’t fail the whole batch.

6. Look up payouts

Payouts also settle asynchronously — subscribe to payout webhook events for the authoritative final status. On sandbox you can mark a pending payout successful or failed (a failure refunds the debit). Pending payouts under $50 USD are also auto-completed every five minutes. See Testing on sandbox.

Fees & custom pricing

Fees are resolved per method from your plan tier, and a custom pricing override (when configured for your account on a given method) always takes priority over the default tier pricing — for both payin and payout. The fee breakdown is returned when you create a deposit, and debited alongside the amount on a payout.

Errors

Validation and business errors return a non-2xx status in the standard envelope, with the reason in data.error (or, for validation errors, a map of field names to messages):
Common cases: unknown/blocked method, amount outside the method’s min/max limits, a wallet currency you don’t hold, a beneficiary/payout method that isn’t yours, or insufficient wallet balance for a payout.