Mural Pay
Global accounts. Real-time payments. One API.
What it is
Mural Pay is a business-first global payments platform built on stablecoins. Companies, fintechs, and banks open Global Stablecoin Accounts (GSAs) through a single API, fund them in fiat or stablecoins, and pay out to bank accounts in local currency or to wallets in stablecoins. It's aimed at cross-border B2B operations — paying contractors and vendors — with built-in compliance and bulk runs of many payments per request. Founded by Palantir alumni, it has processed $200M+ in stablecoin payment volume.
How it works
- Register an end-user (the 'Organization') via the API and pass them through hosted KYB/KYC; an Account is auto-provisioned on approval.
- Fund the account (payin) in fiat via ACH/Wire (USD), SEPA (EUR), or local rails (e.g. PSE/Nequi for COP) — auto-converted to USDC/USDT — or deposit stablecoins directly.
- Create a payout request: FIAT payouts settle to a recipient's bank in local currency; BLOCKCHAIN payouts send stablecoins to a wallet. Batch up to 350 payouts in one request.
- Execute the payout (with a separate transfer-api-key for client-custodial, or a signed payload for end-user-custodial); exchange rates lock at execution.
- Track balance changes and payout state via webhooks and the transactions API.
Differentiators
- Bulk contractor/vendor payouts at scale — up to 350 payouts per request, with optional per-recipient developer fees withheld automatically.
- Last-mile coverage across LatAm corridors (COP, ARS, MXN, BRL, CLP, PEN, BOB, CRC) plus USD/EUR/ZAR, with KYB/KYC built in.
- Two custody models (client-custodial vs. end-user-custodial with browser-SDK signing) let platforms choose who controls funds.
- A single API spanning payins, payouts, invoicing, and virtual stablecoin accounts — not just one of those.
Business model
FX spread on stablecoin ⇄ local-currency conversion + per-payout fees; platforms can also layer their own developer fees on top.
Depends on
- Local banking + payout partners (last-mile in each currency)
- Stablecoin liquidity (USDC/USDT)
- Supported chains (Ethereum, Polygon, Base, Celo)
- Wallet/key infrastructure (Turnkey) for custodial signing
Risks
- Emerging-market FX volatility + local-rail liquidity in LatAm corridors.
- Compliance/licensing burden as a regulated money-movement provider across many jurisdictions.
- Early stage relative to Bridge/BVNK — single $5.6M seed (2022); must show it can scale volume and corridors.
Architecture & mechanics
Payout flow & last-mile settlement
A payout is two objects in sequence: a PayoutRequest you create, then an execution that commits it. This split exists because cross-border FX is time-sensitive — Mural quotes a rate but only locks it when you execute, so the platform isn't exposed to rate drift between request and send.
- FIAT payouts settle to a recipient's local bank account (COP, MXN, BRL, ARS, etc.) — Mural converts the account's USDC/USDT to local currency and pushes it over domestic rails.
- BLOCKCHAIN payouts send stablecoins straight to a wallet on Ethereum/Polygon/Base/Celo.
- Status lifecycle: AWAITING_EXECUTION → PENDING → EXECUTED (or FAILED/CANCELED), surfaced via webhooks.
- Some corridors require supporting documents (invoices, contracts) attached to the payout for compliance.
Bulk-payout architecture
The payouts[] array is the core scale primitive: one request can carry up to ~350 individual payouts, each with its own recipient, amount, currency, and rail. This collapses a contractor/vendor run into a single API call and a single execution.
- Each line item is independently routed (different recipients, currencies, FIAT vs. BLOCKCHAIN) but shares one sourceAccountId.
- Per-recipient developer fees can be withheld automatically from each payout and remitted back to the platform — a built-in monetization hook.
- One execution step commits the whole batch, so the FX rate is locked across the run at execution time.
Compliance & custody (KYB/KYC)
Compliance is a gate, not an afterthought: no Account exists until its Organization clears verification. Mural offers hosted KYC links so platforms can pass their end-users through without handling the documents themselves.
- Individual KYC: name, DOB, address, government ID, tax ID. Business KYB: legal name, entity type, formation docs, tax ID, UBO documentation.
- Account auto-provisions only on approval — KYB/KYC is the prerequisite for both funding and payouts.
- Two custody models: client-custodial (Mural/platform holds keys, execute with transfer-api-key) vs. end-user-custodial (end-user key signs via the Browser SDK, backed by Turnkey).
- Operational guardrails: IP allowlists (CIDR), a separate transfer key for fund movement, and a full-parity Sandbox.
FX & emerging-market risk
Mural's value is concentrated in the last mile of LatAm and other emerging-market corridors — exactly where it carries the most risk. The stablecoin leg is fast and global; the local-currency leg depends on banking partners and local liquidity that can be thin or volatile.
- FX spread on stablecoin ⇄ local currency is the main revenue line, but local-currency volatility (ARS, COP) compresses or threatens margins.
- Last-mile reach depends on local banking partners per currency — a partner outage degrades a whole corridor.
- Regulatory regimes for money movement differ sharply by country, raising licensing and compliance cost as corridors expand.
- At a single $5.6M seed, Mural is earlier-stage than Bridge/BVNK; distribution and corridor depth, not the rail itself, are the battleground.
How it's built
Architecture
Mural sits between stablecoin rails and local banking systems. The core object is the Account (a Global Stablecoin Account) provisioned automatically once an Organization clears KYB/KYC. Accounts hold USDC/USDT (on Ethereum/Polygon/Base/Celo) and expose payin methods (digital wallet, USD ACH/Wire, EUR SEPA, COP PSE/Nequi). Outflows are PayoutRequests — each FIAT (to a bank, last-mile in local currency) or BLOCKCHAIN (to a wallet). Custody is configurable: client-custodial (Mural holds keys; you execute with a transfer-api-key) or end-user-custodial (the end user's key signs the payout via Mural's Browser SDK, powered by Turnkey). Money movement is two-phase: create the request (locks nothing, status AWAITING_EXECUTION) then execute (locks the FX rate). Balance/credit/debit events stream back via webhooks.
Integration shape
REST API authenticated with a Bearer API key, plus an On-Behalf-Of header naming the target Organization. A separate transfer-api-key gates payout execution/cancellation so a leaked read key can't move funds. A Sandbox mirrors production (auto-approves KYC, auto-completes payouts without real settlement). IP allowlists (CIDR) can restrict access. For end-user custody, the Browser SDK signs the payout payload client-side.
API surface
POST /api/organizations- Register an end-user (individual/business); then drive KYB/KYC via the kyc-link. Approval auto-provisions an Account.
GET /api/accounts- List/fetch Global Stablecoin Accounts — wallet addresses, balances, and payin (deposit) instructions per rail.
POST /api/payins/payin- Initiate a deposit; fiat (ACH/Wire/SEPA/PSE) auto-converts to USDC/USDT. Pair with /payins/exchange-rate for quotes.
POST /api/payouts/payout- Create a payout request with a sourceAccountId and a payouts[] array (FIAT or BLOCKCHAIN) — up to 350 per request.
POST /api/payouts/payout/{id}/execute- Execute a created request (transfer-api-key for client-custodial; signed payload for end-user-custodial). Locks the FX rate.
POST /api/payouts/fees/token-to-fiat- Quote fees + FX before executing (also fiat-to-token); rates lock only at execution.
POST /api/webhooks- Subscribe to account credit/debit + payout status events (AWAITING_EXECUTION → PENDING → EXECUTED/FAILED).
Minimal integration
Create a bulk fiat payout request (USDC → local-currency bank payouts) via REST.
const res = await fetch('https://api.muralpay.com/api/payouts/payout', {
method: 'POST',
headers: {
'Authorization': `Bearer ${MURAL_API_KEY}`,
'Content-Type': 'application/json',
'On-Behalf-Of': ORGANIZATION_ID, // which Organization is paying
},
body: JSON.stringify({
sourceAccountId: SOURCE_ACCOUNT_ID, // a Global Stablecoin Account
memo: 'May contractor run',
payouts: [ // up to 350 per request
{
amount: { tokenSymbol: 'USDC', tokenAmount: 100 },
payoutDetails: {
type: 'fiat',
bankName: 'Bancolombia',
fiatAndRailDetails: {
type: 'cop', // pay out in Colombian pesos
accountType: 'CHECKING',
bankAccountNumber: '1234567890',
},
},
recipientInfo: {
type: 'individual',
firstName: 'Javier',
lastName: 'Gomez',
email: 'javier@example.com',
},
},
],
}),
});
const { id } = await res.json(); // status: AWAITING_EXECUTION
// Phase 2: execute to lock FX + send (client-custodial model)
await fetch(`https://api.muralpay.com/api/payouts/payout/${id}/execute`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${MURAL_API_KEY}`,
'transfer-api-key': MURAL_TRANSFER_KEY, // separate key gates fund movement
},
});Build notes
- Two-phase by design: creating a payout reserves nothing and the FX rate locks only at /execute — quotes can expire, so execute promptly or re-quote.
- Keep the transfer-api-key out of any read-only path; it's the only thing standing between a leaked Bearer key and moved money.
- Build against the Sandbox first — it auto-approves KYC and auto-completes payouts so you can test the full lifecycle without real settlement.
- Treat webhooks as the source of truth for payout state (AWAITING_EXECUTION → PENDING → EXECUTED/FAILED/CANCELED), not the synchronous create response.
- [verify against live docs — endpoint host (api. vs app.), exact 350-payout cap, and the full local-currency list evolve]