/stripe-guides

How to create an Express account with Stripe Connect?

Learn how to create a Stripe Connect Express account step-by-step using Node.js and Express, including onboarding, webhooks, and dashboard integration.

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 create an Express account with Stripe Connect?

How to Create an Express Account with Stripe Connect

 

Step 1: Set Up Your Stripe Account

 

Before you can create Express accounts, you need to have a Stripe platform account. If you don't have one yet, go to Stripe's website (https://stripe.com) and sign up. Make sure to complete the verification process to unlock all features.

 

Step 2: Install Required Dependencies

 

For a Node.js project, install the Stripe SDK and other necessary packages:

npm install stripe express body-parser dotenv

 

Step 3: Configure Your Environment

 

Create a .env file in your project root to store your Stripe API keys:

# .env file
STRIPE_SECRET_KEY=sk_test_your_test_key
STRIPE_PUBLISHABLE_KEY=pk_test_your_test_key
STRIPE_WEBHOOK_SECRET=whsec_your_webhook\_secret

 

Step 4: Set Up Your Express Server

 

Create a server.js file with the basic Express configuration:

const express = require('express');
const bodyParser = require('body-parser');
const dotenv = require('dotenv');
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);

dotenv.config();

const app = express();
const port = process.env.PORT || 3000;

// Middleware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static('public'));

// Start server
app.listen(port, () => {
  console.log(`Server running on port ${port}`);
});

 

Step 5: Create an Express Account Creation Endpoint

 

Add an endpoint to create a Stripe Connect Express account:

app.post('/create-express-account', async (req, res) => {
  try {
    // Extract user information from request
    const { email, name, country } = req.body;
    
    // Create an Express account with Stripe Connect
    const account = await stripe.accounts.create({
      type: 'express',
      country: country || 'US',
      email: email,
      capabilities: {
        card\_payments: { requested: true },
        transfers: { requested: true },
      },
      business\_type: 'individual',
      business\_profile: {
        url: req.body.website || 'https://example.com',
        mcc: '5734', // Computer Software Stores
        product\_description: 'Software services',
      },
      metadata: {
        user_id: req.body.userId || 'user_123',
      },
    });
    
    // Return the account ID
    res.status(200).json({ 
      success: true, 
      accountId: account.id 
    });
  } catch (error) {
    console.error('Error creating Express account:', error);
    res.status(500).json({ 
      success: false, 
      error: error.message 
    });
  }
});

 

Step 6: Create an Account Link for Onboarding

 

Add an endpoint to generate an account link for the onboarding process:

app.post('/create-account-link', async (req, res) => {
  try {
    const { accountId } = req.body;
    
    if (!accountId) {
      return res.status(400).json({ error: 'Account ID is required' });
    }
    
    // Create an account link for the user to onboard
    const accountLink = await stripe.accountLinks.create({
      account: accountId,
      refresh\_url: `${req.headers.origin}/onboarding-refresh`,
      return\_url: `${req.headers.origin}/onboarding-success`,
      type: 'account\_onboarding',
      collect: 'eventually\_due',
    });
    
    // Return the account link URL
    res.status(200).json({ 
      success: true, 
      url: accountLink.url 
    });
  } catch (error) {
    console.error('Error creating account link:', error);
    res.status(500).json({ 
      success: false, 
      error: error.message 
    });
  }
});

 

Step 7: Handle Onboarding Refresh and Success Routes

 

Create routes to handle the redirect URLs from the onboarding process:

// Route for handling onboarding refresh
app.get('/onboarding-refresh', (req, res) => {
  res.send(\`
    
      
        

Onboarding session expired

Please refresh the page to continue with the onboarding process.

\`); }); // Route for handling successful onboarding app.get('/onboarding-success', (req, res) => { res.send(\`

Onboarding Successful!

Your Stripe Connect Express account has been set up successfully.

Return to Dashboard \`); });

 

Step 8: Create a Simple Frontend Interface

 

Create a public folder with an index.html file to provide a user interface:




  
  
  Stripe Connect Express Onboarding
  


  

Create Stripe Connect Express Account

 

Step 9: Add Routes to Check Account Status

 

Create an endpoint to check the status of an Express account:

app.get('/account-status/:accountId', async (req, res) => {
  try {
    const { accountId } = req.params;
    
    // Retrieve the account from Stripe
    const account = await stripe.accounts.retrieve(accountId);
    
    // Return the account details and onboarding status
    res.status(200).json({
      success: true,
      account: {
        id: account.id,
        email: account.email,
        chargesEnabled: account.charges\_enabled,
        payoutsEnabled: account.payouts\_enabled,
        requirements: account.requirements,
        detailsSubmitted: account.details\_submitted,
      }
    });
  } catch (error) {
    console.error('Error retrieving account:', error);
    res.status(500).json({ 
      success: false, 
      error: error.message 
    });
  }
});

 

Step 10: Set Up a Webhook Handler

 

Add a webhook endpoint to handle Stripe events related to Connect accounts:

app.post('/webhook', express.raw({type: 'application/json'}), async (req, res) => {
  const sig = req.headers['stripe-signature'];
  let event;

  try {
    // Verify webhook signature
    event = stripe.webhooks.constructEvent(
      req.body,
      sig,
      process.env.STRIPE_WEBHOOK_SECRET
    );
  } catch (err) {
    console.error('Webhook signature verification failed:', 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 updated:', account.id);
      
      // Check if account is now fully onboarded
      if (account.charges_enabled && account.payouts_enabled) {
        console.log('Account fully onboarded:', account.id);
        // Update your database or notify your systems
      }
      break;
      
    case 'account.application.deauthorized':
      // Handle when a user disconnects from your platform
      const accountId = event.data.object.id;
      console.log('Account disconnected:', accountId);
      // Update your database to mark the account as disconnected
      break;
      
    default:
      console.log(`Unhandled event type: ${event.type}`);
  }

  res.json({received: true});
});

 

Step 11: Complete the Setup with Error Handling

 

Add global error handling to your Express application:

// Global error handler
app.use((err, req, res, next) => {
  console.error('Global error:', err);
  res.status(500).json({
    success: false,
    error: process.env.NODE\_ENV === 'production' 
      ? 'An error occurred' 
      : err.message
  });
});

// Handle 404 errors
app.use((req, res) => {
  res.status(404).json({
    success: false,
    error: 'Resource not found'
  });
});

 

Step 12: Run and Test Your Application

 

Start your application and test the Express account creation flow:

// Run the application
node server.js

Navigate to http://localhost:3000 in your browser, fill out the form, and follow the onboarding process.

 

Step 13: Setting Up Stripe CLI for Webhook Testing

 

For local development, install the Stripe CLI to forward webhook events to your local server:

# Install Stripe CLI (Mac with Homebrew)
brew install stripe/stripe-cli/stripe

# Login to your Stripe account
stripe login

# Forward webhook events to your local server
stripe listen --forward-to localhost:3000/webhook

The Stripe CLI will provide a webhook signing secret. Add this to your .env file as STRIPE_WEBHOOK_SECRET.

 

Step 14: Implementing Custom Connect Account Dashboard

 

Add an endpoint to create a dashboard link for Express account users:

app.post('/create-dashboard-link', async (req, res) => {
  try {
    const { accountId } = req.body;
    
    if (!accountId) {
      return res.status(400).json({ error: 'Account ID is required' });
    }
    
    // Create a login link for the Express account
    const loginLink = await stripe.accounts.createLoginLink(accountId);
    
    // Return the login link URL
    res.status(200).json({ 
      success: true, 
      url: loginLink.url 
    });
  } catch (error) {
    console.error('Error creating dashboard link:', error);
    res.status(500).json({ 
      success: false, 
      error: error.message 
    });
  }
});

Add a button to your frontend to generate and navigate to the dashboard link when needed.

 

Step 15: Deploying to Production

 

When deploying to production, follow these best practices:

  • Use environment variables for all Stripe API keys
  • Enable TLS/SSL for secure connections
  • Set up proper logging and monitoring
  • Implement rate limiting for API endpoints
  • Set up automated testing for your integration

Before going live, test the entire flow in Stripe's test mode, then switch to live mode when ready for production.

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