Seller onboarding in Stripe Connect involves creating a connected account, collecting identity and business information, and handling verification requirements. This guide covers the complete onboarding lifecycle including progressive onboarding, requirement deadlines, handling failures, and monitoring onboarding status with webhooks for all three account types.
Complete Seller Onboarding Lifecycle with Stripe Connect
Seller onboarding is the most critical part of a marketplace integration. Stripe requires identity verification, business information, and banking details before a seller can accept payments. The onboarding requirements vary by country and business type. This guide covers progressive onboarding — letting sellers start accepting payments quickly while collecting remaining requirements over time.
Prerequisites
- Stripe account with Connect enabled
- Node.js 18 or later installed
- Stripe Node.js SDK: npm install stripe
- Express.js: npm install express
- A database to store seller account IDs and onboarding status
Step-by-step guide
Create a connected account with pre-filled data
Create a connected account with pre-filled data
Pre-fill as much seller information as possible when creating the account. This reduces friction during onboarding and speeds up verification.
1const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);23async function createSellerAccount(sellerData) {4 const account = await stripe.accounts.create({5 type: 'express',6 country: sellerData.country,7 email: sellerData.email,8 capabilities: {9 card_payments: { requested: true },10 transfers: { requested: true },11 },12 business_type: 'individual',13 individual: {14 first_name: sellerData.firstName,15 last_name: sellerData.lastName,16 email: sellerData.email,17 },18 business_profile: {19 url: sellerData.websiteUrl,20 mcc: '5734', // Computer software stores21 },22 metadata: {23 platform_user_id: sellerData.userId,24 },25 });26 return account;27}Expected result: A connected account is created with pre-filled data, reducing the number of fields the seller needs to complete.
Implement progressive onboarding
Implement progressive onboarding
Stripe has two types of requirements: currently_due (needed now) and eventually_due (needed later). Progressive onboarding lets sellers start accepting payments after meeting currently_due requirements.
1async function checkOnboardingStatus(accountId) {2 const account = await stripe.accounts.retrieve(accountId);34 const status = {5 chargesEnabled: account.charges_enabled,6 payoutsEnabled: account.payouts_enabled,7 currentlyDue: account.requirements.currently_due,8 eventuallyDue: account.requirements.eventually_due,9 pastDue: account.requirements.past_due,10 currentDeadline: account.requirements.current_deadline,11 errors: account.requirements.errors,12 };1314 if (status.currentlyDue.length === 0 && status.chargesEnabled) {15 status.phase = 'complete';16 } else if (status.pastDue.length > 0) {17 status.phase = 'restricted'; // Action needed urgently18 } else if (status.currentlyDue.length > 0) {19 status.phase = 'in_progress';20 }2122 return status;23}Expected result: Returns a status object showing the onboarding phase and any outstanding requirements.
Handle requirement deadlines
Handle requirement deadlines
Stripe sets deadlines for requirements. If not met, the account may be restricted. Monitor current_deadline and send reminders to sellers.
1async function checkDeadlines(accountId) {2 const account = await stripe.accounts.retrieve(accountId);3 const deadline = account.requirements.current_deadline;45 if (deadline) {6 const deadlineDate = new Date(deadline * 1000);7 const daysLeft = Math.ceil((deadlineDate - Date.now()) / (1000 * 60 * 60 * 24));89 console.log(`Deadline: ${deadlineDate.toISOString()}`);10 console.log(`Days remaining: ${daysLeft}`);11 console.log('Requirements due:', account.requirements.currently_due);1213 if (daysLeft <= 7) {14 // Send urgent reminder to seller15 console.log('URGENT: Send reminder to seller!');16 }17 } else {18 console.log('No active deadline.');19 }20}Expected result: Console shows the deadline date, days remaining, and outstanding requirements.
Handle verification failures
Handle verification failures
When Stripe rejects a verification document or finds issues, the requirements.errors array contains the specific reasons. Generate a new Account Link so the seller can resubmit.
1async function handleVerificationFailure(accountId) {2 const account = await stripe.accounts.retrieve(accountId);3 const errors = account.requirements.errors;45 if (errors && errors.length > 0) {6 errors.forEach((error) => {7 console.log(`Requirement: ${error.requirement}`);8 console.log(`Reason: ${error.reason}`);9 console.log(`Code: ${error.code}`);10 });1112 // Generate a new onboarding link for the seller to fix issues13 const accountLink = await stripe.accountLinks.create({14 account: accountId,15 refresh_url: `https://yourplatform.com/onboarding/refresh?acct=${accountId}`,16 return_url: `https://yourplatform.com/onboarding/complete?acct=${accountId}`,17 type: 'account_onboarding',18 });1920 return { errors, fixUrl: accountLink.url };21 }2223 return { errors: [], fixUrl: null };24}Expected result: Returns verification errors with human-readable reasons and a URL for the seller to resubmit.
Set up webhook monitoring for onboarding events
Set up webhook monitoring for onboarding events
The account.updated webhook fires whenever a connected account's status changes. Use it to track onboarding progress and notify sellers.
1const express = require('express');2const app = express();34app.post('/webhook', express.raw({ type: 'application/json' }), async (req, res) => {5 const sig = req.headers['stripe-signature'];6 let event;7 try {8 event = stripe.webhooks.constructEvent(9 req.body,10 sig,11 process.env.STRIPE_WEBHOOK_SECRET12 );13 } catch (err) {14 return res.status(400).send(`Webhook Error: ${err.message}`);15 }1617 if (event.type === 'account.updated') {18 const account = event.data.object;19 const accountId = account.id;2021 if (account.charges_enabled && account.payouts_enabled) {22 console.log(`${accountId}: Fully onboarded`);23 // Update DB, notify seller24 } else if (account.requirements.past_due.length > 0) {25 console.log(`${accountId}: Has overdue requirements`);26 // Send urgent notification27 } else if (account.requirements.errors.length > 0) {28 console.log(`${accountId}: Verification failed`);29 // Notify seller to resubmit30 }31 }3233 res.json({ received: true });34});Expected result: Webhook handler processes account updates and takes appropriate action based on the onboarding state.
Complete working example
1const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);2const express = require('express');3const app = express();45app.use(express.json());67app.post('/api/sellers/onboard', async (req, res) => {8 try {9 const { email, firstName, lastName, country } = req.body;10 const account = await stripe.accounts.create({11 type: 'express',12 country: country || 'US',13 email,14 capabilities: { card_payments: { requested: true }, transfers: { requested: true } },15 individual: { first_name: firstName, last_name: lastName, email },16 });1718 const link = await stripe.accountLinks.create({19 account: account.id,20 refresh_url: `https://yourplatform.com/onboarding/refresh?acct=${account.id}`,21 return_url: `https://yourplatform.com/onboarding/complete?acct=${account.id}`,22 type: 'account_onboarding',23 });2425 res.json({ accountId: account.id, onboardingUrl: link.url });26 } catch (err) {27 res.status(400).json({ error: err.message });28 }29});3031app.get('/api/sellers/:accountId/status', async (req, res) => {32 try {33 const account = await stripe.accounts.retrieve(req.params.accountId);34 res.json({35 chargesEnabled: account.charges_enabled,36 payoutsEnabled: account.payouts_enabled,37 currentlyDue: account.requirements.currently_due,38 pastDue: account.requirements.past_due,39 deadline: account.requirements.current_deadline,40 errors: account.requirements.errors,41 });42 } catch (err) {43 res.status(400).json({ error: err.message });44 }45});4647app.post('/api/sellers/:accountId/fix', async (req, res) => {48 try {49 const link = await stripe.accountLinks.create({50 account: req.params.accountId,51 refresh_url: `https://yourplatform.com/onboarding/refresh?acct=${req.params.accountId}`,52 return_url: `https://yourplatform.com/onboarding/complete?acct=${req.params.accountId}`,53 type: 'account_onboarding',54 });55 res.json({ url: link.url });56 } catch (err) {57 res.status(400).json({ error: err.message });58 }59});6061app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {62 const sig = req.headers['stripe-signature'];63 let event;64 try {65 event = stripe.webhooks.constructEvent(66 req.body, sig, process.env.STRIPE_WEBHOOK_SECRET67 );68 } catch (err) {69 return res.status(400).send(`Webhook Error: ${err.message}`);70 }71 if (event.type === 'account.updated') {72 const acct = event.data.object;73 console.log(`${acct.id}: charges=${acct.charges_enabled} payouts=${acct.payouts_enabled}`);74 console.log(' Due:', acct.requirements.currently_due);75 }76 res.json({ received: true });77});7879app.listen(3000, () => console.log('Onboarding server on port 3000'));Common mistakes when onboarding sellers with Stripe Connect
Why it's a problem: Not monitoring requirements.eventually_due
How to avoid: Eventually_due requirements become currently_due over time. Track them proactively to avoid account restrictions.
Why it's a problem: Ignoring current_deadline on requirements
How to avoid: If requirements are not met by the deadline, Stripe may disable charges or payouts. Send reminders before deadlines.
Why it's a problem: Not handling verification errors gracefully
How to avoid: When verification fails, show the seller a clear message about what went wrong and provide a link to resubmit.
Why it's a problem: Relying only on return_url to determine onboarding completion
How to avoid: The return URL just means the seller left the form. Use webhooks and charges_enabled as the source of truth.
Best practices
- Pre-fill as much seller data as possible to reduce onboarding drop-off
- Use account.updated webhooks as the authoritative source for onboarding status
- Send reminder emails to sellers with upcoming requirement deadlines
- Store requirement errors in your database for support troubleshooting
- Implement a seller dashboard that shows their onboarding progress and any action items
- Test all onboarding scenarios in test mode including verification failures
- For complex multi-seller onboarding, consider working with RapidDev to build a robust onboarding pipeline
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
I need to build a complete seller onboarding system with Stripe Connect. How do I handle progressive onboarding, requirement deadlines, verification failures, and webhook monitoring? Show me Node.js code.
Help me implement seller onboarding for my marketplace using Stripe Connect Express accounts. I need account creation with pre-filled data, onboarding link generation, status checking, deadline monitoring, and webhook handlers.
Frequently asked questions
What is progressive onboarding in Stripe Connect?
Progressive onboarding lets sellers start accepting payments after meeting a minimum set of requirements (currently_due). Additional requirements (eventually_due) are collected over time, with deadlines set by Stripe.
How do I know which requirements a seller must complete?
Use the accounts.retrieve API to check requirements.currently_due for immediate needs and requirements.eventually_due for future needs. The exact requirements depend on country, business type, and capabilities.
What happens if a seller misses a requirement deadline?
Stripe may disable charges, payouts, or both on the account. The seller must complete the overdue requirements before functionality is restored.
Can I collect verification documents myself instead of using Account Links?
Yes, with Custom accounts you can collect documents via your own UI and upload them via the API. With Express accounts, Stripe's hosted onboarding handles document collection.
How long does Stripe take to verify seller documents?
Automated checks (SSN, address) complete in seconds to minutes. Manual document reviews (ID, proof of address) typically take 1-3 business days.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation