Payouts API

Withdraw collected funds to a Moncash number — request a payout, then execute the transfer.

Overview

Payments collected on the platform Moncash account build a withdrawable balance per app. Funds mature after a short holding period, then become available. Paying out is two steps: request a payout, then transfer it (the money-out step your admin approves). Icone Pay tracks one balance per app — which of your own users a payout is for is up to you; attach an idempotencyKey as your reference if you want to reconcile it.

Withdrawals are always capped at your available balance. BYOK Moncash funds land in your own account and are not tracked here.

Enable

The transfer endpoint moves money, so it's off by default. Turn it on in Dashboard → your app → Settings → Payouts (“Payout API”). Requesting and reading payouts works without it; only POST /api/payouts/:id/transfer requires it.

Check Balance

const res = await icone.getBalance();
if (!res.error) {
  console.log(res.balance!.available);  // withdrawable now
  console.log(res.balance!.onHold);     // still maturing
}

Request a Payout

Create a withdrawal to a Moncash number. The amount is validated against the minimum and your available balance, then reserved until the payout is transferred, failed, or cancelled.

const res = await icone.requestPayout({
  amount: 2500,
  receiver: "34123456",        // Moncash number (local or 509-prefixed)
  description: "Seller payout — May",
  idempotencyKey: "payout_may_seller_42", // optional, makes retries safe
});
if (!res.error) console.log(res.payout!.id, res.payout!.status); // → 7 "requested"

A request over your available balance returns 402; a bad amount or number returns 400.

Execute the Transfer

When your admin approves, execute the Moncash transfer. This sends the money and records the debit. Idempotent — a payout already paid just returns paid.

const res = await icone.transferPayout(7);
if (!res.error) console.log(res.payout!.status); // → "paid"
else console.error(res.message);                  // e.g. transfer failed

Returns 403 if the Payout API isn't enabled for the app, and 422 if the transfer can't complete (with the payout's current status in the body).

Listing is paginated — GET /api/payouts?limit=20&offset=0 returns the page plus a total. limit caps at 100 (defaults to 20).

Notifications

When a payout settles, Icone Pay emails the app owner and — if you set a payout webhook URL (Settings → Payouts) — POSTs a signed payout.paid or payout.failed event to it. It uses the same signature scheme and durable retry pipeline as payment webhooks, so verify it exactly as you verify those (see Verifying Webhooks).

{
  "event": "payout.paid",
  "payoutId": 7,
  "status": "paid",
  "amount": 2500,
  "currency": "htg",
  "receiver": "34123456",
  "idempotencyKey": "payout_may_seller_42",
  "moncashTransactionId": "MC-TX-9931",
  "failureReason": null,
  "timestamp": "2026-05-01T12:00:03.000Z"
}

Idempotency

Pass an idempotencyKey when requesting a payout. If the call is retried (a timeout, a network blip) with the same key, Icone Pay returns the original payout instead of creating a second one — so a retry never fires a duplicate transfer. Keys are unique per app.