Migrating from Stripe Connect (Express) to Lumanu
This guide is for platforms on Stripe Connect Express that pay creators, affiliates, or marketing vendors, and are evaluating a move to Lumanu.
Required ReadingIf you haven't yet, start with Why wallet-based payments?. This guide assumes you know the wallet model and focuses on migration mechanics.
Who this guide is for
You're a good fit for Lumanu if:
- Your platform pays recurring vendors (creators, affiliates, talent, production vendors) rather than one-off invoices.
- You're currently using Express (Stripe-hosted onboarding, platform-initiated transfers) rather than Standard or Custom.
- Your vendors complain about re-onboarding for every new platform, or your support team burns hours on 1099s, bank-detail updates, and failed payouts.
If you're using Connect Standard (creators have full Stripe dashboards) or Connect Custom (you've built the entire onboarding flow yourself), most of this guide applies, but the terminology shifts. Reach out for a tailored walk-through.
The mental model shift
Stripe Connect Express is a federated sub-account model. For every creator on your platform, Stripe provisions a separate connected account. Each account has its own:
- Identity verification state (
details_submitted,charges_enabled,payouts_enabled) - Bank account(s) on file
- Payout schedule (daily/weekly/monthly, set by you or the creator)
- 1099 reporting relationship with your platform specifically
The platform's job is to keep all of these sub-accounts healthy: chase incomplete onboarding, handle account.updated webhooks, retry failed payouts, generate year-end tax forms.
Lumanu is a Master Vendor network. There is no sub-account per creator on your platform. Instead:
- A vendor exists once in the Lumanu network. They verify identity, banking, and tax info with Lumanu, not with you.
- Your platform has a single Workspace (the buyer account) that holds a wallet balance and a list of invited vendors.
- You create Payables (payment obligations) addressed to vendors by email or Lumanu ID. Lumanu handles delivery into the vendor's wallet.
- The vendor withdraws from their wallet on their own schedule, to their own chosen destination.
The most concrete consequence: a vendor who works with five Lumanu platforms onboards once. The verification work your support team currently does (chasing missing W-9s, re-verifying identity after a name change, handling failed micro-deposits) moves out of your platform entirely.
Terminology map
| Stripe Connect (Express) | Lumanu | Notes |
|---|---|---|
| Platform account | Workspace | One workspace per buyer. Your platform is the buyer in the Platform-Mediated flow. |
| Connected account (Express) | Partner / Vendor | No per-platform sub-account. Vendors are network-wide. |
| Account Link (onboarding URL) | Partner invite or vendor_invite_url | Two options: server-side API invite (Lumanu emails the vendor) or a redirect-flow URL from the workspace that mirrors Account Link ergonomics. |
Account capabilities (charges_enabled, payouts_enabled) | Partner status | Fetched via GET /workspace/{id}/partner/{partnerId}. |
| Platform balance | Workspace wallet balance | GET /workspace/{id}/wallet. Wallet has its own account/routing number for funding. |
| Transfer | Payable | A payment obligation to a vendor. Created in draft, approved, then funded. |
| Payout (to connected account's bank) | Wallet withdrawal | Initiated by the vendor, not by your platform. Not in your API surface. |
| Top-up | Funding | Loads the workspace wallet, either by invoice (bank transfer) or from existing balance. |
| Application fee | None | Lumanu uses a different fee model. There's no per-transfer application fee concept. |
| 1099-K / 1099-NEC issued by your platform | Issued by Lumanu | As Master Vendor, Lumanu is the reporting party. Confirm with your tax/legal team. |
API mapping
Onboarding a new vendor
Stripe Connect Express:
// 1. Create the connected account
const account = await stripe.accounts.create({
type: 'express',
country: 'US',
email: '[email protected]',
capabilities: {
transfers: { requested: true },
},
});
// 2. Generate an onboarding link
const accountLink = await stripe.accountLinks.create({
account: account.id,
refresh_url: 'https://yourapp.com/reauth',
return_url: 'https://yourapp.com/return',
type: 'account_onboarding',
});
// 3. Redirect creator to accountLink.url
// 4. Poll / webhook on account.updated for capability completionLumanu has two onboarding paths. Pick the one that matches your UX:
Option A: Server-side invite (Lumanu sends the email):
await fetch(`${LUMANU_BASE}/workspace/${workspaceId}/partner/invite`, {
method: 'POST',
headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
body: JSON.stringify({
invites: [{
payee_email: '[email protected]',
payee_business_name: 'Creator LLC', // optional
}],
}),
});Option B: Redirect flow (Stripe Account Link equivalent):
// Fetch the workspace to get its vendor invite URL
const res = await fetch(`${LUMANU_BASE}/workspace/${workspaceId}`, {
headers: { Authorization: `Bearer ${token}` },
});
const { vendor_invite_url } = await res.json();
// Redirect the creator (or open in a new tab), same UX as Stripe Account Links
// Example URL:
// https://use.lumanu.com/public/invitation/get-paid?invitationId=<workspace-id>
window.location.href = vendor_invite_url;The vendor_invite_url is stable per workspace and can be cached; you don't need to fetch it per creator. If you've configured a branded signup tag (bsp_tag) with Lumanu, the URL reflects that. Either option attaches the vendor to your workspace once they complete (or, if they're already in the Lumanu network, the moment they land).
Both paths are valid. Most platforms use Option A for batch migrations or known-email flows, and Option B for in-product sign-up where the creator is already on your site and you want a one-click redirect.
Checking whether you can pay a vendor
Stripe:
const account = await stripe.accounts.retrieve(accountId);
if (account.capabilities.transfers === 'active' && account.payouts_enabled) {
// safe to transfer
}Lumanu:
// Check partner status on the workspace
const res = await fetch(
`${LUMANU_BASE}/workspace/${workspaceId}/partner/${partnerId}`,
{ headers: { Authorization: `Bearer ${token}` } }
);
const partner = await res.json();
// Inspect partner.status. If the vendor hasn't completed verification,
// you can still create a payable; it will sit until they're verified.You can create payables for unverified vendors. The payable stays in approved status, and funds clear to the wallet once verification completes, so your product flow doesn't have to wait on verification state.
Sending a payment
Stripe:
const transfer = await stripe.transfers.create({
amount: 150000, // $1,500 in cents
currency: 'usd',
destination: connectedAccountId,
description: 'Q2 Campaign Content Creation',
});
// Stripe later auto-payouts to the connected account's bank per scheduleLumanu (three-step: create, approve, fund):
// 1. Create the payable
const create = await fetch(`${LUMANU_BASE}/payable`, {
method: 'POST',
headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
body: JSON.stringify({
workspace_id: workspaceId,
payee_email: '[email protected]',
amount: 150000,
amount_denomination: 'us_cents',
description: 'Q2 Campaign Content Creation',
due_date: '2026-05-01T00:00:00Z',
send_invite: true, // invite on the fly if not yet a partner
line_items: [{ amount: 150000, description: 'Instagram Content Creation' }],
}),
});
const { payable } = await create.json();
// 2. Approve it
await fetch(`${LUMANU_BASE}/payable/${payable.id}/approve`, {
method: 'POST',
headers: { Authorization: `Bearer ${token}` },
});
// 3. Fund from wallet balance (if you've already loaded the workspace)
await fetch(`${LUMANU_BASE}/funding`, {
method: 'POST',
headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
body: JSON.stringify({
workspace_id: workspaceId,
method: 'balance', // or 'invoice' for pay-by-bank-transfer
amount: 150000,
amount_denomination: 'us_cents',
payable_ids: [payable.id],
}),
});The three-step pattern (create → approve → fund) is explicit by design. It separates the obligation from the approval from the payment, which matters for finance workflows with reviewers, budget checks, or batched funding.
For simple flows, you can script all three calls together. For platforms with approval workflows, this maps naturally to human-in-the-loop review.
Funding your wallet (top-ups)
Stripe platforms rarely think about top-ups: charges feed the available balance, and you transfer out of it. Lumanu separates charging from paying, so you load the workspace wallet before (or alongside) payment.
Two methods:
balance: draws from existing wallet balance. Used above. Requires the wallet to already have funds.invoice: Lumanu generates a funding invoice for your AP team. Once they pay it, you match the incoming deposit to the funding. Best for large, scheduled funding runs.
The invoice funding flow has four steps:
// 1. Create the funding with method: 'invoice' (generates a PDF invoice)
const fundingRes = await fetch(`${LUMANU_BASE}/funding`, {
method: 'POST',
headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
body: JSON.stringify({
workspace_id: workspaceId,
method: 'invoice',
amount: 5000000,
amount_denomination: 'us_cents',
description: 'April 2026 creator payouts',
payable_ids: [payable1.id, payable2.id, payable3.id],
}),
});
const { funding } = await fundingRes.json();
// 2. Retrieve the invoice PDF for your AP team
// GET /funding/{id}/pdf-url → returns a URL to the PDF
// 3. AP pays the invoice via bank transfer to the workspace wallet's
// account/routing numbers. The incoming deposit arrives unlinked.
// 4. Match the deposit to the funding
// List unlinked deposits:
const unlinkedRes = await fetch(
`${LUMANU_BASE}/workspace/${workspaceId}/wallet/deposit`,
{ headers: { Authorization: `Bearer ${token}` } }
);
const { deposits } = await unlinkedRes.json();
// Link the matching deposit to the funding:
await fetch(`${LUMANU_BASE}/funding/${funding.id}/link-deposit`, {
method: 'POST',
headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ deposit_id: deposits[0].id }),
});Once a funding is linked to its matching deposit, payables in that funding settle. If they're also waiting on vendor verification, they settle the moment the vendor completes onboarding.
Most platforms automate step 4 by polling unlinked deposits and matching on amount and timing. You can also match manually through a finance UI.
Webhooks
Stripe-side events you probably handle today, and their Lumanu equivalents:
| Stripe event | Lumanu equivalent |
|---|---|
account.updated | Partner status change events |
capability.updated | Partner status change events |
transfer.created | Payable approved event |
transfer.paid | Payable paid event |
payout.paid | Not surfaced. Belongs to the vendor's wallet. |
payout.failed | Not surfaced. Vendor handles withdrawal retries. |
Subscribe via POST /workspace/{id}/webhook-subscription. The smaller event surface is intentional. The events you lose are about the vendor's relationship with their bank, which is no longer your concern.
Flow comparison
Onboarding a creator
Stripe Connect Express:
Platform → create Account → Stripe
Platform → create Account Link → Stripe
Platform → redirect creator to onboarding URL
Creator → submits ID, bank, tax info → Stripe
Stripe → account.updated webhook → Platform
Platform → check capabilities, mark creator ready
Lumanu (Option A, server-side invite):
Platform → POST /partner/invite → Lumanu
Lumanu → emails creator (invite + onboarding)
Creator → onboards to Lumanu network (once, ever)
Platform → optionally poll partner status, or just create payables
Lumanu (Option B, redirect flow, Account Link equivalent):
Platform → GET /workspace/{id} (reads vendor_invite_url)
Platform → redirect creator to vendor_invite_url
Creator → onboards to Lumanu network (once, ever)
Platform → optionally poll partner status, or just create payables
Paying a creator
Stripe Connect Express:
Platform → Transfer → Stripe
Stripe → credits connected account balance
Stripe → auto-payout on schedule → Creator bank
Stripe → payout.paid webhook → Platform
Lumanu:
Platform → POST /payable → Lumanu
Platform → POST /payable/{id}/approve → Lumanu
Platform → POST /funding (balance or invoice) → Lumanu
Lumanu → credits vendor's wallet
Vendor → withdraws on their schedule, their rail
(Platform stops being involved here)
Data migration
You'll need to move three things from Stripe to Lumanu: the list of vendors, their identity/banking info, and any in-flight payments.
Vendors
Export connected accounts from Stripe (GET /v1/accounts), then invite each one to your Lumanu workspace. A script sketch:
const accounts = await stripe.accounts.list({ limit: 100 });
const invites = accounts.data
.filter(a => a.details_submitted) // skip abandoned onboardings
.map(a => ({
payee_email: a.email,
payee_business_name: a.business_profile?.name,
}));
// Lumanu accepts batches in a single call
await fetch(`${LUMANU_BASE}/workspace/${workspaceId}/partner/invite`, {
method: 'POST',
headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ invites }),
});Identity and banking details
Don't try to migrate these. You can't export bank account numbers or full tax info out of Stripe, and even if you could, Lumanu's verification is independent and would redo it anyway. Vendors re-verify with Lumanu once via the invite email. This is a one-time cost, not a recurring one. Future platforms they work with won't require it.
Plan vendor-facing communication that explains:
- They'll receive a Lumanu invite email from your platform
- They need to complete Lumanu verification (takes ~5–10 min for individuals)
- Once verified with Lumanu, they never need to re-verify
Brands that send this communication well ahead of cutover see noticeably higher onboarding completion rates than those relying on the invite email alone.
In-flight payments
Split into three buckets:
- Transfers already completed and paid out: nothing to do; they're settled.
- Transfers completed but not yet paid out (sitting in connected account balance): let Stripe's payout schedule flush these; don't try to reroute.
- Future obligations you haven't transferred yet: create these as Payables in Lumanu from cutover date forward.
Avoid double-paying by locking down Stripe transfer creation at the cutover moment. A feature flag on your transfer code path works well.
Feature parity and gaps
Things Lumanu does that Stripe Connect Express doesn't:
- Cross-platform vendor identity. Creators onboarded once receive payments from any buyer in the network.
- Network-level tax reporting. Lumanu is the reporting party, not your platform.
- Wallet funding by invoice. Lets enterprise AP teams pay by bank transfer on their own schedule rather than via card/ACH debit.
Things Stripe Connect does that Lumanu doesn't:
- Processing customer charges. Stripe Connect combines charge processing with payouts; Lumanu is payouts-only. If you're also using Stripe to accept customer payments, keep that part of Stripe and migrate only the payout side.
- Platform-controlled payout schedules. You no longer set the cadence for payouts from the creator's balance; that's their call. If your product exposes "payout settings" to creators today, you can remove that surface.
- Application fees on transfers. Lumanu uses a different fee structure. Work with your account team on the specifics.
Rollout strategy
A cutover pattern that's worked for similar migrations:
- Week 0: integration. Build the Lumanu integration in sandbox (
https://api.demo.lumanu.link/api/rest). Verify payable creation, funding, and webhook flows end to end. - Week 1: dual-write for new vendors only. New creators signing up after this date onboard through Lumanu. Existing creators remain on Stripe. No existing flows change.
- Week 2–4: vendor communication and invites. Email existing creators explaining the change and send Lumanu invites. Track invite acceptance. Do not yet reroute their payments.
- Week 5+: migrate payment routing for invited creators. For each creator who's completed Lumanu onboarding, flip a per-creator flag that routes future payments to Lumanu instead of Stripe. Do this gradually, not all at once.
- Long tail: residual Stripe cleanup. For creators who never complete Lumanu onboarding (there will be some), decide whether to keep a Stripe lane open or force migration with a deadline. Most platforms pick a cutoff 60–90 days after first invite.
Avoid a hard cutover of all creators in one day. The onboarding completion rate is never 100% immediately, and a partial-migration model means stragglers don't block your timeline.
Gotchas
A few assumptions from Stripe Connect that don't carry over:
- There is no platform-initiated payout. If any of your product copy or internal tooling says "trigger payout now," rephrase it. The equivalent Lumanu action is "fund the payable." The vendor's withdrawal is separate, and not your concern.
- Creator balance is not a concept on your platform. In Stripe, you could query a connected account's balance. In Lumanu, the vendor's wallet balance belongs to the vendor, not to your platform view. You can see what you've paid them; you can't see what's left in their wallet.
- Pick the right onboarding path for your UX. Server-side invites (Option A above) are great for batch migrations where you have a list of known emails. The redirect flow (
vendor_invite_url) matches Stripe Account Link ergonomics and is usually better for in-product sign-up where the creator is already on your site. Mixing both is fine; they lead to the same network identity. - 1099 responsibility moves. Your accounting team needs to know that Lumanu issues 1099s to vendors, not your platform. This changes year-end reporting meaningfully. Loop in finance before cutover, not after.
- Sandbox does not move real money. The sandbox environment (
api.demo.lumanu.link) supports test deposits viaPOST /workspace/{id}/wallet/depositfor simulating funded wallets. Production has no such endpoint. Real funds must arrive.
Resources
- API Reference - Full endpoint details
- Sandbox:
https://api.demo.lumanu.link/api/rest - Production:
https://api.lumanu.com/api/rest
Updated 11 days ago
If you haven't read the foundation page go to "Why wallet-based payments?".