Guides

How to add stablecoin payments to your app with a wallet API

To add stablecoin payments to an app, give each user a wallet through a payments API, verify them once, and wire deposits and payouts to local rails.

Caio Barbosa

Founder & CO-CEO

Forbes Under 30. One of the leading voices in Fintech & Crypto in Brazil. Writes weekly about stablecoins, payments, and the future of financial infrastructure in Latin America.

Cover image for Lumx blog article: How to add stablecoin payments to your app with a wallet API
Cover image for Lumx blog article: How to add stablecoin payments to your app with a wallet API

Adding stablecoin payments to an app means connecting your backend to a payments API, verifying each user once, and giving each user a wallet. Local-currency deposits convert into stablecoin in that wallet, payouts convert it back to local currency on a bank rail, and webhooks keep the app's screens in sync with what happened.

This guide is for a team that already has an app and users and wants them to receive, keep and send money across borders without building a banking stack. Wallet products are compared in the wallet options post, and the generic engineering checklist is the seven-step integration guide. This one covers the product shape, built on what a stablecoin API is: who owns what, which screens exist, and which events drive them.

What your app needs before the first payment

Three things, and none of them is a blockchain: a backend that can hold a secret API key and receive webhooks, a list of the money movements the app needs, and a decision about who the legal customer is. The answer is each user, as the next section explains.

The key that creates customers and moves money lives on a server you control, never inside the app binary or a web bundle.

Flows come in two directions: a user pays in local currency and the balance appears in their wallet as stablecoin, or the wallet pays a bank account in local currency or sends stablecoin to another wallet.

On Lumx, the first release needs a sandbox key and a webhook endpoint configured in the dashboard. Sandbox moves no real money.

Give every user a wallet, not the app

The model that holds up under compliance review is one wallet per user: each user is a customer of the payments provider, verified once. The app orchestrates and the money sits where the user can be seen.

That also settles the app's role. The app is not the party holding user money: it creates customers, asks for quotes and displays state, while funds stay in each user's own wallet and are never pooled. Identity checks attach to each user as the provider's customer, not to your app. This is Lumx's nested-payments rule, and it is operational context, not legal advice about your own obligations.

The alternative looks simpler and breaks: one platform wallet receives everything and the app keeps a ledger of who is owed what, which fails the first time a bank asks who the person behind a payment is. Providers that move money for third parties have to see every payer and payee, so pooling funds for users the provider never verified needs the provider's written approval as a nested structure. At Lumx that approval comes from compliance (compliance@lumx.io), and a third party can fund a user's deposit only when it fits the expected flow of funds.

The wallet is custodial: the provider holds the keys, which is why a payout can clear when no human is online to sign it. What custody costs a business is in what a custodial wallet is, and the structures larger institutions use are in how to structure custodial wallets.

On Lumx, creating a customer provisions a wallet on every supported blockchain (Ethereum, Polygon, Base, Tron and Stellar, where Stellar serves only BRL to USDC on-ramps), holding USDC or USDT depending on the network, and the wallet is enabled once the customer is approved. Verification runs through Sumsub, transaction monitoring through Chainalysis, and company verification is handled in the API. The platform earns through a partner fee in basis points, a flat amount or both, collected to a wallet address you name. See the custodial wallets product page.

How does a user's money move through the app?

Every flow is one of four stages. Each has one API call to start it and a few webhook events to follow it, and the app should draw its screens from the events, not from what the user last tapped.

Where a user's money is at each stage, and what the app should show.

Stage

The app calls

Webhook events to follow

What the user sees

Onboarding

Create the customer, request the terms link

customer.created, customer.under_verification, customer.approved, customer.rfi, customer.final_rejection

Verification progress, or a request for one more document

Deposit

Create an on-ramp for an exact amount

onramp.awaiting_funds, onramp.transferring_fiat, onramp.trading, onramp.transferring_stablecoin, onramp.success, onramp.failed, onramp.expired

Payment instructions, then a credited balance

Move

Create a transfer to a customer or an address

transfer.transferring_stablecoin, transfer.success, transfer.failed

Sent, then confirmed

Pay out

Register a destination, create an off-ramp

offramp.transferring_stablecoin, offramp.trading, offramp.transferring_fiat, offramp.success, offramp.failed

A rate, a progress line, then received

The table is the contract between your app and the provider: 15 money events across three flows, plus verification. Map each event to a state once, and the screens follow.

On Lumx these are the documented event names. Use the webhook-id header to deduplicate. Webhooks are signed with HMAC-SHA256, the docs recommend rejecting messages older than five minutes, and a non-2xx response is retried with exponential backoff.

Onboard the user before any screen that moves money

A user who has not been approved has no usable wallet, so onboarding is a gate in your navigation: the deposit screen does not render until the customer is approved.

The sequence is short. Create the customer with the currencies the user needs, then the user accepts the provider's terms through a link. An individual goes through a hosted flow with an ID and a liveness check, and KYC (know your customer, the verification of an individual) covers the person. For a company, KYB (know your business, the verification of a company and its owners) asks for formation documents and for the people who own and control it. A request for information, an RFI (request for information, a compliance hold that asks for a document before a transaction clears), pauses the process until the user supplies the missing item. What KYB is explains what a company should prepare.

Handle four outcomes: approved, under verification, a request for more information, and a final rejection. Give the third a screen that says what is missing.

Limits shape the product too. These defaults apply to every customer, in every country, and each transaction type (on-ramp, off-ramp, transfer) counts against its own:

Default transaction limits by verification level, in USD.

Limit

KYC Standard

KYB Standard

Per transaction

$7,500

$50,000

Daily

$15,000

$100,000

Monthly

$15,000

$100,000

On Lumx, the terms link comes from one call and expires after 24 hours, so generate a new one if the user returns late. The KYB target is one business day. Wallets appear on the customer record only after approval, so subscribe to the approval event instead of polling the create response. Higher limits need an Enhanced review.

Deposits: from local currency to stablecoin in the wallet

The user pays in their own currency, and the provider converts it to stablecoin and credits the wallet. For Brazil that rail is Pix (Brazil's instant payment system, run by the Central Bank), for Mexico it is SPEI (Mexico's interbank transfer system, run by Banxico), and a USD deposit arrives by ACH or wire.

For a one-off payment, create an on-ramp for the exact amount and show the payment details it returns, such as a Pix code or wire instructions. For repeat deposits, a standing rule on the account converts every matching deposit with no per-deposit call. What an on-ramp is covers the concept.

An on-ramp has a payment window, and a user who pays after it closes has paid late. The expired event tells your app to retire the instructions, and a late deposit does not convert: the funds go back to the sender on the same rail.

On Lumx, the receiving account is a virtual account in the customer's name, requested in the same call that creates the customer. Request the account for each currency before you collect or pay in it. BRL, MXN, EUR and GBP accounts activate right after approval, and USD can take up to one business day because the banking partner reviews it first. A floating-rate Pix or SPEI on-ramp expires after one day, other rails after seven. Rails and settlement times are on the coverage page; the product view is global payments. Account currencies are BRL, MXN, COP, USD, EUR and GBP, and a COP account shows the banking partner as holder unless the customer is Colombian.

I recommend shipping deposits alone before any payout, and holding the payout screen until you have watched a few real deposits move through every state. Deposits only need the app to display instructions and react to events, so they test onboarding, the event handlers and the ledger at the lowest cost if something is wrong. A payout adds a recipient, a rate and a bank on the other side, and mistakes there cost money.

Payouts: from the wallet to a local bank account

A payout starts with a destination: the recipient's bank details plus the relationship between your user and the recipient. Register it once and let the user pick from saved recipients. The relationship travels with the payment, so the receiving banks know whether the user is paying themselves, a supplier or an employee.

The app then asks for a rate and the user confirms it. A floating rate is an estimate for display. A locked rate fixes the conversion for a short window. Put the rate, the amount the recipient receives and a countdown next to the confirm button.

A payout bigger than the wallet balance fails with an insufficient-balance error, so check the balance before you offer the button. A payout that fails after it started arrives as a failed event, so change ledger state only on events. For cut-offs and settlement windows by rail, see payout limits and cut-offs, and for the concept behind the call, what an off-ramp is.

On Lumx, the lock lasts 30 seconds, 1 minute or 5 minutes, and the 30-second lock carries no fee. A payout is one off-ramp call that debits the user's wallet and sends local currency to the saved destination. Every payout carries a purpose code, such as professional services or trade, which the banks on the rail use for screening, and a mismatch can hold the payment or trigger an RFI. A transfer to another Lumx customer or to an external wallet address is a separate call on the same wallet.

A mobile fintech app: keep the key off the phone

On iOS and Android there is one rule: the phone never talks to the payments API directly. The app reads state from your backend and renders it.

That rule shapes four screens. Onboarding opens the hosted verification flow and needs a way back into the app. Deposit shows the payment details and waits for the balance to change. Payout shows the quote with its countdown and sends one confirm to the backend. Push notifications follow events.

Send an idempotency key with every write from the backend, so a double tap or a retry after a timeout cannot create two payments, and treat the balance on the screen as a cached copy of the wallet, refreshed on events.

On Lumx, the terms-of-service redirect accepts only an http or https address, so a custom scheme such as myapp:// fails validation. Point it at a web page of yours that opens the app with a universal link or an app link. A repeated idempotency key with the same body returns the cached response, and the same key with a different body returns a conflict. If the app is Brazilian and sends money abroad, the rules are in international transfers from a Brazilian app.

When adding stablecoin payments to your app is the wrong move

First, if your users will never be verified. An app that collects money from people the provider cannot see and redistributes it is nesting, which the wallet-per-user design exists to prevent. A card processor or local acquirer fits better.

Second, if the user must hold the keys. A custodial provider can freeze a balance when compliance requires it, so a product that promises self-custody should not be built on this model.

Third, if your payments never cross a border or a currency, because a local rail connection solves that with fewer parts.

What this looks like in the Lumx API, call by call

Lumx is stablecoin payments infrastructure for businesses that move money between Latin America and the rest of the world: one API to collect, hold, convert, and pay out in BRL, MXN, COP, USD, EUR, and GBP or in USDC and USDT, over local rails such as PIX, SPEI, PSE, Bre-B, ACH, FEDWIRE, SEPA, and Faster Payments, with SWIFT and on-behalf-of payments and collections (POBO and COBO) in USD, EUR, and GBP, plus named virtual accounts, custodial wallets, and KYB/KYC built in.

From an empty project to a first payout, the app makes five write calls. Create the customer with the accounts the user needs. Request the terms-of-service link. Create the on-ramp for the first deposit. Register the destination. Create the off-ramp. A company also uploads documents. None of them has the app signing anything, because the wallet is custodial.

Everything after the first call arrives as an event, and success is the moment to show the credited balance or the received payout. In sandbox, the last digit of a customer's tax ID drives the outcome: 2 simulates a request for information, 3 a final rejection, 1 a customer that never starts, and any other digit an approval. A simulated deposit exercises a standing conversion rule end to end. An API integration typically takes two to three weeks until go-live, and your team can also use the Lumx dashboard next to the API.

The spec and a docs server for coding agents are in the OpenAPI and MCP guide.

Methodology and sources

Product behavior was read from the Lumx documentation on November 1, 2026: Stablecoin Wallets, Customers, Accounts, Webhooks, Idempotency, Transaction Limits, Nested Payments and Coverage.

Verified on November 1, 2026. Operational context, not legal, tax, or investment advice.

Cover photo: Danil Shostak on Unsplash.

  • How do I add stablecoin payments to my app?

    Connect your backend to a payments API, create each user as a verified customer with a wallet, and let deposits and payouts run through that wallet while webhooks update your screens. On Lumx, creating the customer provisions the wallet and the local-currency account, and five write calls take you from an empty project to a first payout.

  • Should each user have a wallet, or should the app have one?

    Each user should have a wallet. A single app wallet that pools money for users the provider has not verified breaks the provider's visibility rules and tends to fail compliance review. On Lumx, every user is a customer with a wallet of their own, and the platform earns through a partner fee collected to a wallet address you choose.

  • What happens when a deposit or a payout fails?

    Each failure has its own event, so the app reacts to the event and not to a timeout. An on-ramp can end as failed or expired, and a deposit that arrives after expiry is returned to the sender on the same rail. A payout bigger than the wallet balance fails with an insufficient-balance error. On Lumx these are the onramp.failed, onramp.expired and offramp.failed events, and the webhook-id header deduplicates repeats.

  • How do I test stablecoin payments before going live?

    Run the whole path from customer to payout in a sandbox with test stablecoins, so no real money moves. On Lumx, a tax ID ending in 2 simulates a request for information, one ending in 3 a final rejection, and any digit other than 1, 2 or 3 an approval, and a simulated deposit tests a standing conversion rule.

  • How long does it take and what does it cost?

    Timing depends on how many flows and currencies the first release has. On Lumx, an API integration typically takes two to three weeks until go-live, and pricing is a monthly platform fee plus usage-based per-transaction fees, transparent FX on locked quotes, no pre-funding; no published plans. No pre-funding means you do not park capital in settlement accounts before a transaction, even though a wallet can hold a USDC balance.

Stay up to date with what Lumx is developing.

Sign up to receive them by email.

Share on socials:

how-to-add-stablecoin-payments-to-your-app

A

how-to-add-stablecoin-payments-to-your-app

How to add stablecoin payments to your app with a wallet API

Copy link

Copied!

how-to-add-stablecoin-payments-to-your-app

TALK TO OUR TEAM

Ready to transform your business with stablecoins?

Discover how our infrastructure can seamlessly integrate stablecoins into your financial operations quickly, securely, and efficiently.

Guides

In this page

©2026. All rights reserved.

Lumx US OP LLC ("Lumx") is a financial technology and payments infrastructure company. Lumx US OP LLC is a Money Service Business (MSB) registered with the Financial Crimes Enforcement Network (FinCEN) (MSB #31000316459619). Lumx is not a state-licensed money transmitter and does not, in its own capacity, engage in the provision of regulated money transmission services. All such regulated activities are conducted exclusively through, and under the licenses of, duly authorized financial-institution partners.


Lumx is not a bank, financial institution, payment institution, or custodian of client funds. Certain services made available through the Platform may be provided by duly authorized and regulated third-party partners, in accordance with applicable laws and regulations.

Please refer to Lumx’s Terms of Use and Privacy Notice for further information regarding the conditions governing the use of the Platform and the processing of your personal data.