Skip to main content

Changelog

Changes to the merchant-facing API contract and to the documentation that describes it, newest first.

How to read the version numbers. They track the contract, not the prose:

BumpMeans
Major (2.0.0)A breaking change — an endpoint, field, or behavior your integration relies on no longer works the same way.
Minor (1.3.0)Something added or extended — a new endpoint, request field, response field, status, or error code. Existing integrations keep working.
Patch (1.3.1)Clarification or correction to the docs with no change in API behavior.

Entries describe what changed for an integration. Where a change is only visible on gateways with a specific arrangement (platform-billed, open-amount, cashout API), the entry says so — if that does not apply to your gateway, nothing changed for you.


Unreleased​

Postman collection (documentation only)

A downloadable Postman collection with staging and production environments covers every merchant endpoint, chains requests through captured IDs, and signs cashout requests automatically. No API change.

Contract-routed payments are credited (all gateways)

A customer payment that moves tokens through another contract — for example a fee-free ("gas-free") wallet transfer on TRON, or an exchange withdrawal batched with other customers' — carries several token transfers in one transaction. These are now detected automatically like any other payment. Previously they were missed and could not be recovered through Submit transaction inquiry either; inquiry now credits the one transfer sent to the payment's deposit address. No integration change.

Inquiry: an unknown transaction hash returns tx_not_found (all gateways)

Submit transaction inquiry with a hash that isn't on any of the payment's networks now returns 200 with resultCode: tx_not_found, as documented, and consumes an attempt. It previously failed with a server error that did not consume one.

Monthly-billed gateways report both fee payers as PLATFORM (standard gateways on monthly fee billing only)

On a standard gateway switched to monthly fee billing, payments now carry txFeePayer and commissionFeePayer = PLATFORM on the public payment object — the value platform-billed gateways already report — instead of MERCHANT. The fee-payer request fields on Create payment are ignored on these gateways, and the customer never pays a fee on top: both fees show as covered at checkout. This corrects the earlier statement that customer-paid fees still apply under monthly fee billing. What you receive and what you are invoiced are unchanged.

Verify reports the received amount in USD directly (all gateways)

New optional response field on Verify: receivedAmountUsd — the USD value of receivedAmount at the received asset's market price, quantised to cents. Until now the USD equivalent had to be reconstructed from deviationUsd, which needs the quote price your integration doesn't have; this makes wrong-asset receipts (where receivedAssetSymbol ≠ assetSymbol) directly comparable to amountUsd with no math. Additive — existing integrations keep working.


2.1.0 — 2026-08-31​

Wrong-asset deposits now resolve instead of expiring — and the API tells you what arrived (all gateways; visible only when a payer sends the wrong asset)

New optional response fields — additive, existing integrations keep working:

  • Verify: receivedAssetId, receivedAssetSymbol. Normally they duplicate the quoted asset (assetSymbol). When the payer paid in a different asset than they selected (e.g. sent native TRX to a USDT deposit address), the platform can now value that deposit at the received asset's own market price and resolve the payment normally instead of leaving it PENDING until expiry — receivedAmount is then denominated in the received asset, and deviationUsd remains the safe field to branch on (always computed in USD from the actual valuation).
  • Public payment object: paidAssetId, paidAssetSymbol — prefer them over the paid offer's symbol when captioning receivedAmount on your own receipt page.

2.0.0 — 2026-08-31​

Cashout API — one route field, and cashouts that wait instead of failing (cashout API)

Breaking — isQuarantined is gone

isQuarantined was introduced on 2026-08-29 (1.8.0) and is removed on both the request and the response, replaced by route. If you integrated against 1.8.0, change "isQuarantined": true to "route": "AML_HELD" and add an amount — the held pool no longer has a drain-everything shape. Read route instead of isQuarantined on responses. Integrations that never touched the held pool are unaffected: route is optional and defaults to your ordinary balance.

  • Breaking. POST /merchant/settlements returns 200 on a claimed cashout, not 201. A 201-only success check will start failing.
  • Breaking. amount is now always required. Previously it had to be omitted for a held-pool drain. "Withdraw everything" is expressed by reading the pool's figure from balances and passing it.
  • Added. route (GREEN — the default, also null/omitted — AML_HELD, or SMART) picks which balance pays the cashout. SMART screens the destination and lets the verdict choose the pool; the response says which pool it picked (route) and that we picked it (routedBy: "SMART_ROUTE", plus destinationRiskScore). See Fund pools and route.
  • Changed. The held pool is withdrawn in exact amounts, under the same rules as the ordinary pool — same fee, same approval cap, same screening, same dispatch delay. One rulebook for both.
  • Added. 202 Accepted — a parked cashout. Two new statuses: UNDERFUNDED (you asked for more than the pool holds; shortfall says how much more is needed, and it activates itself when the funds arrive) and WAITING_AML_CREDIT (a SMART/AML_HELD cashout whose destination screen could not run because screening credit is exhausted; it resolves once you top up). A parked cashout claims nothing, carries expiresAt (7 days), and is auto-rejected with an email if it is still blocked then. Handle 202 — it is returned only on gateways where Finomesh has enabled parking, but that is a per-gateway switch, not a contract change.
  • Added. POST /merchant/settlements/:id/retry activates a parked cashout immediately instead of waiting for the automatic pass, and POST /merchant/settlements/:id/cancel withdraws one. Both require Idempotency-Key; neither requires 2FA.
  • Added. Error codes insufficient_balance (409 — replaces the generic conflict for an over-request), too_many_parked_cashouts (409), screening_required (409, SMART with no verdict available), below_minimum_settlement (422) and amount_below_network_fee (422). See Cashout Errors.
  • Added. shortfall, shortfallUsd and expiresAt on the settlement object, and UNDERFUNDED / WAITING_AML_CREDIT as ?status= filter values on list. shortfall is computed live on every read and is omitted — never 0 — when the balance cannot be read.

1.8.0 — 2026-08-29​

Cashout API — held (AML) balance is now visible and withdrawable (AML-screened gateways with the cashout API)

  • Added. POST /merchant/settlements accepts isQuarantined (boolean, default false). true requests a quarantine cashout: it drains your entire AML-held balance for the asset to the given address with no operator approval — it starts REQUESTED like any other API cashout, subject only to your approval cap and destination screening. amount must be omitted on that request (422 otherwise).
  • Added. The settlement object (create + status + list) carries isQuarantined so you can tell which pool a settlement came from.
  • Documented. GET /merchant/settlements/balances has always returned the held pool per asset — totalQuarantinedAvailable, totalQuarantinedAvailableUsd, quarantinedPayments, totalQuarantinedReceived, totalQuarantinedPendingAvailable, quarantinedPendingPayments. These fields are now on the balances reference; they are exact complements of the ordinary totalAvailable* figures.
  • Added. POST /payments/{id}/verify returns amlState (HELD / RELEASED / REFUNDED / WITHHELD) and isQuarantined on payments touched by screening, so you can see which payment backs the held balance. Both are omitted on payments never flagged — unchanged shape for everyone else.

1.7.0 — 2026-08-04​

Open-amount payments — below-minimum deposits now settle

  • Changed. On an open-amount payment, the first on-chain deposit settles the payment whatever its size. At or above the gateway minimum it resolves SUCCESS; below the minimum it resolves MISMATCH, with the minimum standing in as the expected amount. Funds are captured and credited either way. Previously a below-minimum deposit was documented as ignored, leaving the payment PENDING for a later, larger one — there is no second chance to top up. See Create payment → Open-amount payments.
  • Changed. deviationUsd on verify now appears for open-amount payments on MISMATCH — the signed shortfall against the minimum (e.g. "-2" for $8 received against a $10 minimum). It remains absent on SUCCESS.
  • Added. expiresAt (RFC 3339) on the public payment object — the payment's authoritative deadline. Drive countdowns from it rather than re-deriving createdAt + timeoutSeconds client-side.

1.6.0 — 2026-08-03​

Platform-billed gateways create open-amount payments only

  • Changed. On a platform-billed gateway, POST /payments (fixed amount) now returns 403. These gateways create open-amount payments only. If you need fixed-amount payments as well, use a separate standard gateway alongside it. See Error codes.
  • Changed. checkAmountDeviation joins txFeePayer, commissionFeePayer, overAcceptableDiff, underAcceptableDiff, and acceptableDiffKind in the set of request fields ignored on a platform-billed gateway — the arrangement fixes them.
  • Changed. Where an arrangement limits the offered assets to specific stable assets, that restriction applies to open-amount payments only. Assets outside it are dropped from the offers, and a create with none remaining is rejected with 422.
  • Clarified. POST /payments/open-amount accepts no assets[] override — offers are always the gateway's enabled-asset list at current prices.

1.5.0 — 2026-07-27​

Open-amount payments and platform-billed gateways

  • Added. POST /payments/open-amount — creates a payment with no fixed amount, where the payer chooses how much to send. For donations, tips, top-ups, and pay-what-you-want flows. Deliberately a separate endpoint, not a flag: there is no amount, and no fee-payer or tolerance fields. The response shape is identical to the fixed-amount create ({ paymentUid, paymentUrl }). Available per gateway by arrangement; otherwise it returns 403. See Create payment.
  • Added. openAmount (boolean) and minAmountUsd (decimal string) on the public payment object. When openAmount is true, each offer's amount / totalValue are 0 placeholders and must not be shown as a figure to send.
  • Added. 403 forbidden on /payments/open-amount when the gateway is not provisioned for open-amount payments — see Error codes.
  • Added. Platform-billed gateways documented on Create payment and Settlement / Cashout: Finomesh covers the network fee and commission on every payment, billed separately rather than deducted per payment.
  • Changed. On verify, open-amount payments carry no expectedAmount, and amount / amountUsd read 0 until the deposit confirms.

1.4.0 — 2026-07-20​

Transaction inquiry

  • Added. POST /payments/{id}/inquiry — submit a customer's transaction hash against a payment that never resolved on its own. The hash is verified on-chain against every deposit address the payment holds; on a match the payment enters the normal crediting pipeline and your webhook fires. A recovery path for "my customer says they paid but the payment is still PENDING", not part of the normal flow — attempts are limited. See Submit transaction inquiry.
  • Note. Inquiry is the one exception to the standard error envelope: its verdicts — including rejections such as wrong_recipient — return 200 OK with a resultCode in data. Only transport and auth failures use the usual error codes. See Error codes and the endpoint's result codes.
  • Added. Inquiry documented as an escalation step in Reconciliation.

1.3.0 — 2026-07-15​

Cashout approval over the API

  • Added. GET /merchant/settlements — list your cashouts with an optional status filter, plus limit / page / after paging. Use ?status=PENDING_APPROVAL to find what is waiting, and pagination.total to count without pulling every row.
  • Added. POST /merchant/settlements/{id}/approve — release a parked cashout entirely over the API (2FA required), instead of approving it in the dashboard.
  • Replaced. The requesterIdentity string added in 1.2.0 is superseded by metadata — a free-form one-level JSON object echoed back on read and shown to the approver key by key. Total size capped at 4 KB; a requester key is shown first.
  • Clarified. REJECTED is a cancellation performed by an operator — approval is the only cashout action you take over the API. See Cashout API.

1.2.0 — 2026-07-14​

Cashout approval cap

  • Added. A per-gateway cashout approval cap (a USD ceiling, set in the dashboard). With a cap set, any API cashout whose USD value is strictly greater than the cap is created as PENDING_APPROVAL instead of REQUESTED: funds are reserved but not dispatched until a team member approves it. Approving moves it to REQUESTED; rejecting returns the funds to your available balance.
  • Added. requesterIdentity (optional, ≤ 128 chars) on create — identifies who or what initiated the cashout, shown to the approver when a request parks. (Replaced by metadata in 1.3.0.)
  • Action required if you set a cap. POST /merchant/settlements gains a fifth status. If your integration switches on status, handle PENDING_APPROVAL (as "pending, not yet dispatched") before enabling the cap. With no cap configured, behavior is unchanged and the status never appears. See Cashout API → Approval cap.
  • Clarified. Idempotency-Key still returns the original settlement id on replay while a request is parked — poll the status or list endpoint rather than re-POSTing.

1.1.0 — 2026-07-08​

Estimate cashout fee

  • Added. POST /merchant/settlements/estimate-fee — a dry run that returns the exact feeLocked and netAmount a real create of the same body would produce, but creates nothing: no settlement, no address-book entry, no balance claimed. Same body as create minus label. Being read-only it needs no Idempotency-Key (it still carries a body to sign). See Estimate cashout fee and Cashout API.
  • Changed. The destination address on the fee quote is now validated for the asset's chain (EVM EIP-55 checksum, TRON/UTXO base58check). A malformed address returns 422 validation_error before any fee is quoted, matching create.
  • Added. Fee-efficiency guidance on Create settlement: every settlement is a separate on-chain transaction paying its own network fee, so one larger cashout costs less than several partial ones.

1.0.0 — 2026-07-07​

Documentation baseline

  • Reorganized the documentation into a developer-journey structure: Get Started, Core Concepts, Accept Payments, Cashout / Settlements, API Reference, Testing, and Resources.
  • Split the Introduction into Overview, Payment Flow, Payment Statuses, and Environments; moved Authentication under API Reference.
  • Added Core Concepts pages: Checkout Modes, Callback vs Webhook, Amount Deviation, Settlement / Cashout.
  • Added a dedicated Cashout / Settlements section (Overview, Enable, Signing Requests, Get Balances, Create Settlement, Get Settlement Status, Cashout Errors).
  • Added Reconciliation under Accept Payments.
  • Added a Testing section (Sandbox Overview, Test Payment Scenarios, Test Webhooks, Test API Mode, Test Cashout).
  • Added Resources: Security Checklist, FAQ, Glossary, Changelog.
  • Split Error Codes and Rate Limits into their own API Reference pages.
  • Standardized request, response, header, parameter, and error tables across the API reference; every error table now has a How to fix column.
  • Made example URLs environment-aware so sandbox and production hosts are never mixed up.
  • Old URLs (/quickstart, /authentication, /guides/*) redirect to their new locations.