Skip to main content

Create Settlement

POST /merchant/settlements requests a settlement of an exact amount to a destination address. It returns immediately with a REQUESTED settlement; the on-chain payout is dispatched after your gateway's configured delay.

The HTTP status code is the outcome — branch on it, not on the message:

CodeMeaning
200Claimed. REQUESTED, or PENDING_APPROVAL when it needs sign-off.
202Parked. Accepted, nothing claimed yet — UNDERFUNDED (waiting for funds) or WAITING_AML_CREDIT. It continues on its own; see Parked cashouts.
409Refused. See Cashout Errors.

If you have set a cashout approval cap, a request above the cap instead returns a PENDING_APPROVAL settlement that waits for someone on your team to approve it in the dashboard before it is dispatched.

Example​

BODY='{"assetId":"<asset-uuid>","amount":"250.00","address":"T...","label":"payouts","metadata":{"requester":"ops-team-alice","orderId":"1234"}}'
TS=$(date +%s)
SIG=$(printf '%s.%s' "$TS" "$BODY" | openssl dgst -sha256 -hmac "$SIGNING_SECRET" | awk '{print $2}')
curl -X POST https://api-staging.finomesh.com/api/v1/merchant/settlements \
-H "X-Api-Key: $FINOMESH_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-H "X-Timestamp: $TS" -H "X-Signature: $SIG" \
-d "$BODY"

Key rules​

  • amount is always required and must be > 0. There is no "withdraw everything" shape — to cash out the lot, read the pool's figure from Get Balances and pass it.
  • Asking for more than you have is not an error condition. Depending on a per-gateway setting Finomesh controls, an over-request either parks (202, UNDERFUNDED, see below) or is refused with 409 insufficient_balance. Parking is off unless you ask for it — but handle 202 either way.
  • route picks which balance pays — GREEN (default), AML_HELD, or SMART. See Fund pools.
  • Idempotency-Key is required. Reuse the same key to safely retry without creating a second settlement. The same key with a different body returns 409 idempotency_conflict.
  • address is validated for the asset's chain (EVM EIP-55 checksum, TRON/UTXO base58check) and stored in your address book on first use, tagged API. A repeat address is reused, not rejected.
  • metadata (optional) is a free-form, one-level JSON object for your own tracking — attach whatever you need (e.g. {"requester":"ops-team-alice","orderId":"1234"}). It is echoed back on read and shown to the approver, key by key, when a request parks at the approval cap. Keys are not validated; total size is capped at 4 KB. A conventional requester key (who initiated the cashout) is shown first to the approver.
  • The response starts REQUESTED (so txHash / blockchainUrl are empty), or PENDING_APPROVAL when the amount exceeds your approval cap or the destination screen did not pass (see Destination screening), or one of the two parked statuses on a 202. netAmount = amount − feeLocked is what lands at the destination. On a monthly-billed gateway a token cashout carries feeCollection: "INVOICED" with feeLocked: "0" and netAmount equal to amount — the destination receives exactly what you requested and the settlement fee bills monthly.

Approval cap​

If your gateway has a cashout approval cap (a USD ceiling you configure in the dashboard), any API cashout whose USD value is strictly greater than the cap is created as PENDING_APPROVAL instead of REQUESTED. It reserves the funds but is not dispatched until it is approved — from the dashboard settlement list or over the API (list the waiting cashouts, then approve; 2FA required). Approving it moves it to REQUESTED and starts the normal dispatch delay. Approval is the only merchant action: a parked cashout you don't approve stays reserved until you do (cancelling one is an operator/support action, not a merchant reject). With no cap configured, every API cashout dispatches without approval, exactly as before.

Fund pools — the route field​

On AML-screened gateways your balance sits in two pools, and route says which one pays. It is a single enum; omitting it means GREEN.

routePays from
GREEN (default)Your ordinary settle-able balance — totalAvailable.
AML_HELDThe held pool — deposits our screening flagged, excluded from totalAvailable and reported as totalQuarantinedAvailable on Get Balances.
SMARTThe destination decides. We screen the address once at create: clean draws from green, over-threshold draws from the held pool. The response tells you which we picked (route) and that we picked it (routedBy: "SMART_ROUTE").
{"assetId":"<asset-uuid>","address":"T...","amount":"120.00","route":"AML_HELD"}

Both pools follow the same rules: an exact required amount, the same fee, the same approval cap, the same destination screening, the same dispatch delay, and the same over-request behavior. A held-pool cashout needs no operator approval — it starts REQUESTED like any other, and only your own gates can park it in PENDING_APPROVAL, released with the usual approve call. Once it settles, the payments it drew on read amlState: "RELEASED" on verify.

SMART never guesses: with no verdict available it is refused (409 screening_required), or — when the cause is an exhausted screening credit — parked as WAITING_AML_CREDIT until you top up. Full contract: Cashout Endpoints → Fund pools and route.

Parked cashouts​

A 202 means we accepted the request but claimed nothing — no funds reserved, no fee locked. It is a standing instruction that carries itself out when its blocker clears:

statusWaiting forClears when
UNDERFUNDEDFunds. shortfall on every read says how much more the routed pool needs.The balance covers it — checked about once a minute, then it dispatches normally.
WAITING_AML_CREDITScreening credit, on a SMART or AML_HELD cashout whose destination screen could not run.You top up your AML credit; we retry the screen on the same schedule.
  • You do not have to do anything. The same request activates itself — same amount, same address, same metadata. Never re-send it; that creates a second cashout.
  • Both carry expiresAt, 7 days out. Still blocked at that point and it is auto-rejected, and we email you — a parked cashout never lingers silently.
  • Retry (POST /:id/retry) checks the balance immediately instead of waiting for the next pass — optional, for right after you top up. Cancel (POST /:id/cancel) withdraws the request; you can do this yourself precisely because nothing is claimed.
  • A request that could never activate is refused up front instead of parked — below your settlement minimum, or below its own network fee. So is one over the per-gateway limit on simultaneously parked cashouts (409 too_many_parked_cashouts).

Destination screening​

If your gateway has AML screening enabled, the destination address of every cashout is screened against the same risk provider that screens your deposits, at the same per-check price from your screening credit. The result is stamped on the settlement (destinationRiskScore, destinationScreenedAt) and decides how the request proceeds:

  • Passed — the cashout continues as normal (REQUESTED).
  • Failed (the address scores above your gateway's withdrawal risk threshold) — an API cashout is created as PENDING_APPROVAL instead of being rejected, so your integration never hard-fails on a screening verdict. Review it and approve it explicitly if you still want to pay that address.
  • Screening unavailable (provider outage or no verdict yet) — the cashout also parks as PENDING_APPROVAL. It is never silently let through unscreened.

A screen is billed once per address per screening-cache window — repeat cashouts to the same address within the window reuse the verdict for free. Gateways without AML screening are unaffected. The withdrawal risk threshold defaults to your deposit screening threshold; ask your operator to tune it per gateway.

Fee efficiency​

Prefer one larger cashout over many small ones

Every settlement is a separate on-chain transaction that pays its own network fee. On fee-based chains — notably TRON, where each transfer burns energy/bandwidth — splitting a withdrawal into several partial cashouts makes you pay that per-transaction fee every time, so the total network cost is higher than withdrawing the same funds in a single settlement.

Where practical, cash out your full available balance in one request rather than dribbling it out in repeated partial withdrawals. Estimate the fee first if you want to compare.

Track it to a terminal state with Get Settlement Status, or rely on the settlement webhook.

Reference​