txn_… id
when you submit it. Nothing moves before submit.
This is the conceptual guide. For parameters and schemas see
Create pre-transaction,
Submit transaction,
Get transaction and
List transactions.
Before you start
The flow
1
Price it
Generate quote returns a
qut_… id. The
ten-minute clock starts now and runs through submit.2
Check it
Create pre-transaction checks
the quote, recipient, wallet and KYC together. It creates nothing and moves nothing.
3
Attach an invoice (only if required)
Upload invoice returns
file_… ids.4
Submit
Submit transaction creates the
txn_… and moves the money. This is the only call that does.5
Track it
Webhooks tell you something changed;
Get transaction tells you what.
Step by step
The example sends 100 USDC from a customer’s wallet on BaseSepolia to a VND bank account in Vietnam. Every call carriesApi-Key and Api-Version: 2026-09.1.
Check it with a pre-transaction
source.amount and destination.amount to the user here for a final
confirmation. Pre-transaction is safe to repeat for the same quote.
Submit
200 with the transaction object. Store txnId. For a
wallet-funded transfer Endl sends from the wallet during this call, so the first
status you see is often already IN_PROGRESS:
recipientData and depositData. See
Get transaction.
Picking endlTransactionMode
The mode must match the quote: a
USDC → VND quote is STABLE_COIN_TO_FIAT.
Funding
You never send funds to a deposit address on this surface. You name the source, and Endl moves the money server-side when you submit. That is whatsettlement: "SERVER_SIDE" on the pre-transaction means.
The wallet must hold enough. The debit is
source.amount from the quote, fees
included. Check it with Get wallet balance
first. On sandbox, new EVM wallets arrive with 100 test USDC and 100 test USDT on
their network.Statuses
A transaction carriesstatus for where it is and subStatus for the step inside
it. Decide on status, but always read subStatus when the status is IN_REVIEW:
a failure or refund can show up there first.
Webhooks
The event’s
data.id is the txn_… id and its payload carries status,
sourceCurrency and destinationCurrency. Nothing is sent for IN_REVIEW or
PENDING_TRAVEL_RULE, and a fast transfer can finish during submit without a
separate updated event. On every event, call Get transaction for the full state,
and poll it for transfers that go quiet. See Webhooks for signing
and delivery.
Purpose codes, invoices and listing
Purpose codes. Every transfer exceptTOP_UP needs transferPurpose and
transferPurposeCode. Take the code from
List purpose codes; pass
relation=SELF when the customer pays themselves.
Invoices. When a purpose code or recipient has invoiceMandatory: true, upload the
invoice before submit and pass the ids in invoiceFileIdList. Upload takes
multipart/form-data with part name file, 1–5 files, 2 MB each.
Listing. List transactions is a
POST because the filters travel in the body.
The response is
{ "txns": [ … ], "totalCount": 42 }; totalCount counts every
match, not just this page.
Errors and retries
Errors use the envelope described in Errors: branch onerrors[0].code, not the top-level message.
If submit times out, do not resubmit straight away. List transactions with
sortBy: "createdOn,desc" and look for your quoteId. If it is there, the submit
went through; track it. If not, get a fresh quote and start again.
Common pitfalls
400 ERRTXN_1002 on a stablecoin payout
400 ERRTXN_1002 on a stablecoin payout
Wallet-funded modes need
walletId on both pre-transaction and submit. Do not send
fromAddress; it is not a field on this surface.My retry failed even though the first submit failed
My retry failed even though the first submit failed
Quotes are single-use, and the first attempt consumed this one. Generate a fresh
quote for every attempt.
The transaction sits in IN_REVIEW and no webhook arrived
The transaction sits in IN_REVIEW and no webhook arrived
No event is sent for
IN_REVIEW. Read subStatus: TRANSACTION_REJECTED or
TRANSACTION_REFUNDED there is the outcome.Amounts on the transaction are strings
Amounts on the transaction are strings
sourceAmount, destinationAmount, fxRate and chargesTotal are decimal
strings on the transaction object. Parse them as decimals, not floats.403 on submit for a customer who can quote
403 on submit for a customer who can quote
KYC depth follows the route. A Bridge-routed transfer needs the full Bridge check
even when a stablecoin → stablecoin transfer works with Sumsub alone.