/stripe-guides

How to onboard sellers with Stripe Connect?

Learn how to onboard sellers to your platform using Stripe Connect Express with this step-by-step tutorial covering setup, onboarding, payments, and compliance.

Matt Graham, CEO of Rapid Developers

Book a call with an Expert

Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.

Book a free consultation

How to onboard sellers with Stripe Connect?

How to Onboard Sellers with Stripe Connect: A Comprehensive Tutorial

 

Introduction

 

Stripe Connect is a powerful platform that allows you to build a marketplace, SaaS platform, or crowdfunding site where you can facilitate payments between customers and service providers or sellers. This tutorial will guide you through the process of onboarding sellers to your platform using Stripe Connect.

 

Step 1: Set Up Your Stripe Account

 

Before you can onboard sellers, you need to have a Stripe account set up as a platform.

  • Sign up for a Stripe account at https://stripe.com/
  • Verify your email and complete the initial setup
  • Navigate to the "Connect" section in your Stripe Dashboard
  • Configure your platform settings and business details

 

Step 2: Choose the Right Connect Account Type

 

Stripe Connect offers three types of accounts:

  • Standard: Sellers create and manage their own Stripe accounts
  • Express: Streamlined onboarding with Stripe-hosted pages
  • Custom: Full control over the onboarding experience, but requires more compliance work

For this tutorial, we'll focus on Express accounts as they offer a good balance between simplicity and customization.

 

Step 3: Install the Stripe Library

 

You'll need to install the Stripe library in your application. Here's how to do it in different environments:

For Node.js:


npm install stripe

For PHP:


composer require stripe/stripe-php

For Python:


pip install stripe

For Ruby:


gem install stripe

 

Step 4: Initialize the Stripe Client

 

In your application code, initialize the Stripe client with your secret key:

Node.js:


const stripe = require('stripe')('sk_test_YOUR_SECRET_KEY');

PHP:


\Stripe\Stripe::setApiKey('sk_test_YOUR_SECRET_KEY');

Python:


import stripe
stripe.api_key = 'sk_test_YOUR_SECRET\_KEY'

Ruby:


require 'stripe'
Stripe.api_key = 'sk_test_YOUR_SECRET\_KEY'

 

Step 5: Create an Express Account Link

 

To start the onboarding process, you first need to create a Connect account for your seller, then generate an account link that directs them to the Stripe-hosted onboarding flow:

Node.js:


async function createSellerAccount(sellerId) {
  // First, create a Connect Express account
  const account = await stripe.accounts.create({
    type: 'express',
    metadata: {
      seller\_id: sellerId
    }
  });
  
  // Store the account ID in your database
  // saveAccountIdToDatabase(sellerId, account.id);
  
  // Then, create an account link for onboarding
  const accountLink = await stripe.accountLinks.create({
    account: account.id,
    refresh\_url: 'https://yourdomain.com/onboarding/refresh',
    return\_url: 'https://yourdomain.com/onboarding/complete',
    type: 'account\_onboarding'
  });
  
  // Return the URL to redirect your seller to
  return accountLink.url;
}

PHP:


function createSellerAccount($sellerId) {
  // First, create a Connect Express account
  $account = \Stripe\Account::create([
    'type' => 'express',
    'metadata' => [
      'seller\_id' => $sellerId
    ]
  ]);
  
  // Store the account ID in your database
  // saveAccountIdToDatabase($sellerId, $account->id);
  
  // Then, create an account link for onboarding
  $accountLink = \Stripe\AccountLink::create([
    'account' => $account->id,
    'refresh\_url' => 'https://yourdomain.com/onboarding/refresh',
    'return\_url' => 'https://yourdomain.com/onboarding/complete',
    'type' => 'account\_onboarding'
  ]);
  
  // Return the URL to redirect your seller to
  return $accountLink->url;
}

 

Step 6: Redirect the Seller to the Onboarding URL

 

Now that you have generated the account link URL, redirect the seller to this URL to complete the Stripe onboarding process. Here's how you might do this in a web application:

Node.js (Express.js):


app.get('/onboard-seller/:id', async (req, res) => {
  const sellerId = req.params.id;
  
  try {
    const onboardingUrl = await createSellerAccount(sellerId);
    res.redirect(onboardingUrl);
  } catch (error) {
    console.error('Error creating onboarding link:', error);
    res.status(500).send('Unable to create onboarding link');
  }
});

PHP:


// Assuming you have a route that handles /onboard-seller/{id}
$sellerId = $\_GET['id'];
try {
  $onboardingUrl = createSellerAccount($sellerId);
  header("Location: $onboardingUrl");
  exit();
} catch (Exception $e) {
  echo 'Error creating onboarding link: ' . $e->getMessage();
}

 

Step 7: Handle the Return from Stripe

 

After the seller completes (or abandons) the Stripe onboarding process, they'll be redirected to your return_url or refresh_url. Set up handlers for these routes:

Node.js (Express.js):


// Handle successful completion of onboarding
app.get('/onboarding/complete', async (req, res) => {
  const sellerId = req.query.seller\_id;
  
  // Retrieve the account ID from your database based on seller\_id
  // const accountId = getAccountIdFromDatabase(sellerId);
  
  // Check if the account is fully onboarded
  try {
    const account = await stripe.accounts.retrieve(accountId);
    
    if (account.details\_submitted) {
      // Seller has completed onboarding
      // Update your database to mark the seller as active
      res.send('Congratulations! Your account has been set up successfully.');
    } else {
      // Seller didn't complete all steps
      res.send('Your account setup is not complete. Please finish all steps.');
    }
  } catch (error) {
    console.error('Error checking account status:', error);
    res.status(500).send('Error checking account status');
  }
});

// Handle the need to refresh the onboarding link
app.get('/onboarding/refresh', async (req, res) => {
  const sellerId = req.query.seller\_id;
  
  // Retrieve the account ID from your database
  // const accountId = getAccountIdFromDatabase(sellerId);
  
  try {
    // Create a new account link for the same account
    const accountLink = await stripe.accountLinks.create({
      account: accountId,
      refresh\_url: 'https://yourdomain.com/onboarding/refresh',
      return\_url: 'https://yourdomain.com/onboarding/complete',
      type: 'account\_onboarding'
    });
    
    // Redirect to the new link
    res.redirect(accountLink.url);
  } catch (error) {
    console.error('Error refreshing onboarding link:', error);
    res.status(500).send('Error refreshing onboarding link');
  }
});

 

Step 8: Set Up Webhook Events

 

Stripe sends webhook events for important account updates. Set up a webhook endpoint to listen for these events:


// Node.js (Express.js) example
const bodyParser = require('body-parser');
app.post('/webhook', bodyParser.raw({type: 'application/json'}), async (req, res) => {
  const sig = req.headers['stripe-signature'];
  let event;
  
  try {
    event = stripe.webhooks.constructEvent(
      req.body,
      sig,
      'whsec_your_webhook\_secret'
    );
  } catch (err) {
    console.error(`Webhook Error: ${err.message}`);
    return res.status(400).send(`Webhook Error: ${err.message}`);
  }
  
  // Handle specific events
  switch (event.type) {
    case 'account.updated':
      const account = event.data.object;
      console.log(`Account ${account.id} was updated`);
      
      // If the account is now fully onboarded, update your database
      if (account.details_submitted && account.charges_enabled) {
        // updateSellerStatus(account.id, 'active');
        console.log(`Seller with account ${account.id} is now active`);
      }
      break;
      
    case 'account.application.deauthorized':
      // The seller has disconnected their account
      const accountId = event.data.object.id;
      // updateSellerStatus(accountId, 'disconnected');
      console.log(`Seller with account ${accountId} has disconnected`);
      break;
  }
  
  res.json({received: true});
});

 

Step 9: Create a Dashboard Link for Sellers

 

After a seller has been onboarded, they may need to access their Stripe Express dashboard to view payouts, update information, etc. Generate a dashboard link:


async function createDashboardLink(accountId) {
  const loginLink = await stripe.accounts.createLoginLink(accountId);
  return loginLink.url;
}

Implement this in an endpoint:


app.get('/seller/dashboard/:id', async (req, res) => {
  // Get the seller's account ID from your database
  // const accountId = getAccountIdFromDatabase(req.params.id);
  
  try {
    const dashboardUrl = await createDashboardLink(accountId);
    res.redirect(dashboardUrl);
  } catch (error) {
    console.error('Error creating dashboard link:', error);
    res.status(500).send('Unable to access dashboard');
  }
});

 

Step 10: Process Payments and Handle Transfers

 

Once sellers are onboarded, you can process payments on their behalf and automatically transfer funds. Here's a basic example:


async function createPaymentWithTransfer(amount, currency, customerId, sellerAccountId, applicationFeeAmount) {
  try {
    const paymentIntent = await stripe.paymentIntents.create({
      amount: amount,
      currency: currency,
      customer: customerId,
      payment_method_types: ['card'],
      application_fee_amount: applicationFeeAmount,
      transfer\_data: {
        destination: sellerAccountId,
      },
    });
    
    return paymentIntent;
  } catch (error) {
    console.error('Error creating payment with transfer:', error);
    throw error;
  }
}

This function:

  • Creates a payment intent for the specified amount
  • Takes an application fee for your platform
  • Automatically transfers the remainder to the seller's account

 

Step 11: Monitor Account Status and Compliance

 

It's important to regularly check the status of your connected accounts to ensure they remain in good standing:


async function checkAccountStatus(accountId) {
  try {
    const account = await stripe.accounts.retrieve(accountId);
    
    // Check if the account is fully onboarded and can process payments
    const isActive = account.details_submitted && account.charges_enabled;
    
    // Check if there are any requirements that need attention
    const requiresAttention = account.requirements.currently\_due.length > 0;
    
    return {
      isActive,
      requiresAttention,
      requirements: account.requirements
    };
  } catch (error) {
    console.error(`Error checking account ${accountId} status:`, error);
    throw error;
  }
}

You can schedule this to run periodically or in response to webhook events.

 

Step 12: Implement Account Updates

 

Sometimes sellers need to update their information. You can create a new account link specifically for updates:


async function createAccountUpdateLink(accountId) {
  const accountLink = await stripe.accountLinks.create({
    account: accountId,
    refresh\_url: 'https://yourdomain.com/account/refresh',
    return\_url: 'https://yourdomain.com/account/updated',
    type: 'account\_update'
  });
  
  return accountLink.url;
}

 

Conclusion

 

You've now set up a complete flow for onboarding sellers with Stripe Connect Express accounts. This implementation provides:

  • A streamlined onboarding experience for your sellers
  • Automatic handling of compliance and verification
  • Dashboard access for sellers to manage their accounts
  • Payment processing with automatic transfers
  • Monitoring for account status and compliance issues

Remember that this tutorial covers the Express account type, which is ideal for most marketplaces. If you need more control over the user experience, you might consider Custom accounts, though they require more development and compliance work.

For production use, make sure to implement proper error handling, data validation, and security measures throughout your application.

Want to explore opportunities to work with us?

Connect with our team to unlock the full potential of no-code solutions with a no-commitment consultation!

Book a Free Consultation

Client trust and success are our top priorities

When it comes to serving you, we sweat the little things. That’s why our work makes a big impact.

Rapid Dev was an exceptional project management organization and the best development collaborators I've had the pleasure of working with. They do complex work on extremely fast timelines and effectively manage the testing and pre-launch process to deliver the best possible product. I'm extremely impressed with their execution ability.

CPO, Praction - Arkady Sokolov

May 2, 2023

Working with Matt was comparable to having another co-founder on the team, but without the commitment or cost. He has a strategic mindset and willing to change the scope of the project in real time based on the needs of the client. A true strategic thought partner!

Co-Founder, Arc - Donald Muir

Dec 27, 2022

Rapid Dev are 10/10, excellent communicators - the best I've ever encountered in the tech dev space. They always go the extra mile, they genuinely care, they respond quickly, they're flexible, adaptable and their enthusiasm is amazing.

Co-CEO, Grantify - Mat Westergreen-Thorne

Oct 15, 2022

Rapid Dev is an excellent developer for no-code and low-code solutions.
We’ve had great success since launching the platform in November 2023. In a few months, we’ve gained over 1,000 new active users. We’ve also secured several dozen bookings on the platform and seen about 70% new user month-over-month growth since the launch.

Co-Founder, Church Real Estate Marketplace - Emmanuel Brown

May 1, 2024 

Matt’s dedication to executing our vision and his commitment to the project deadline were impressive. 
This was such a specific project, and Matt really delivered. We worked with a really fast turnaround, and he always delivered. The site was a perfect prop for us!

Production Manager, Media Production Company - Samantha Fekete

Sep 23, 2022