How To Integrate Stripe Connect with Your Marketplace

How To Integrate Stripe Connect with Your Marketplace

Stripe Connect is one of the most popular and dynamic payment systems for marketplaces, platforms, and eCommerce products that need to route money between buyers, sellers, service providers, contractors, or other connected users.

It supports multi-vendor, ticketing, on-demand, marketplace, and eCommerce platforms all over the world. With Stripe Connect, marketplace owners can accept customer payments, onboard sellers, manage platform commissions, route funds to connected accounts, handle payouts, and support compliance workflows.

This article explains how to integrate Stripe Connect into a marketplace app with code examples. This includes connected account setup with Accounts v2, seller onboarding, buyer payments, platform commissions, transfers, webhooks, and edge cases.  

What is Stripe Connect?

Stripe Connect is Stripe’s payment infrastructure for Ebusinesses and marketplaces. It helps marketplaces accept payments from customers and route funds to the businesses, sellers, or service providers that operate on the platform.

It processes confidential payment and account data, including payment method details, identity verification data, transaction history, balances, and payout information.

From the integration point of view, Stripe is a widely known solution with extensive documentation, a transparent workflow, and a large developer ecosystem.

Our data-driven research allows us to conclude that Stripe Connect is a strong fit for managing payments on marketplace projects, especially when the product needs seller onboarding, platform fees, split payments, delayed transfers, or payout management.

Stripe Connect is successfully used by numerous eCommerce A-listers, like Lyft, Shopify, Woocommerce, Kickstarter, etc.  Depending on their business model, each platform can use Stripe Connect differently (discover the list of Stripe’s customers for more info).

Stripe Connect pricing

And just a heads-up — this payment gateway isn’t free.

Stripe pricing depends on the platform’s country, connected account setup, payment method, currency, payout flow, and Connect capabilities. 

Generally, Stripe provides flexible, pay-as-you-go pricing. Depending on your Connect setup, pricing may include:

  • payment processing fees;
  • Connect account or payout fees;
  • Instant Payout fees;
  • cross-border payout fees;
  • currency conversion fees;
  • custom pricing for businesses with high payment volume or unique business models.

Stripe Connect also gives platforms two general pricing approaches:

  • Stripe handles pricing for your users.
  • Your platform handles pricing for your users.

For a marketplace, the second model is often more relevant because the platform may collect its own fees, define commission logic, and control how much is transferred to connected sellers.

Always check the current Stripe pricing page for the country and integration model you plan to use.

What account setup does Stripe Connect offer?

In older Stripe Connect integrations, connected accounts were usually described through three account types: Standard, Express, and Custom. With Stripe Accounts v2, the model is more flexible.

Accounts v2 allows platforms to create one connected Account object and assign it one or more configurations depending on what the account needs to do.

For example:

  • merchant configuration allows the connected account to accept payments from customers.
  • recipient configuration allows the connected account to receive transfers.
  • customer configuration allows the account to be charged as a customer of the platform.

This is useful because a marketplace user can sometimes act in more than one role. For example, the same user may sell products on the platform, receive payouts, and also buy paid services from the platform. Accounts v2 makes it easier to represent these relationships without maintaining separate account and customer objects for the same user.

You also need to define the connected account’s Dashboard access:

  • full — the connected account can access the full Stripe Dashboard.
  • express — the connected account can access the Stripe Express Dashboard with limited functionality.
  • none — the connected account has no Stripe Dashboard access, so your platform must provide the required account, payout, and reporting functionality itself.

For many marketplaces, express or none will be the most relevant options. Express lets Stripe handle much of the onboarding and account management experience, while none gives the platform more control but also more responsibility.

In our particular case, we’ll focus on a marketplace flow where sellers need to receive funds from customer purchases. This usually means creating connected accounts with the recipient configuration. If the connected account also needs to be treated as the merchant of record or accept payments directly, the merchant configuration may also be needed.

Speaking about the marketplace app, the target audience is twofold: customers and retailers, contractors, wholesalers, or service providers. In some products, users can also switch between these roles.

Let’s jump to the step-by-step guide for a better understanding of how to manage a payment made by a client. In this example, the platform accepts the customer’s payment, keeps the funds until the order is confirmed, takes the platform commission, and transfers the remaining amount to the seller.

How to onboard sellers with Stripe Accounts v2

The first step is to create a connected account for each seller who needs to receive payouts.

With Accounts v2, this is done by creating an Account object and assigning the required configuration. For a seller that only needs to receive transfers from the platform, the account should request the recipient configuration.

Example request:

curl -X POST https://api.stripe.com/v2/core/accounts \
  -H "Authorization: Bearer {{STRIPE_SECRET_KEY}}" \
  -H "Stripe-Version: 2026-05-27.preview" \
  --json '{
    "contact_email": "seller@example.com",
    "display_name": "Seller Store",
    "dashboard": "express",
    "identity": {
      "country": "us",
      "entity_type": "individual"
    },
    "configuration": {
      "recipient": {
        "capabilities": {
          "stripe_balance": {
            "stripe_transfers": {
              "requested": true
            }
          }
        }
      }
    },
    "defaults": {
      "currency": "usd",
      "responsibilities": {
        "fees_collector": "application",
        "losses_collector": "application"
      },
      "locales": ["en-US"]
    }
  }'

After the account is created, save the connected account ID in your user model.

Example user model:

import { Schema } from 'mongoose';

export const UserSchema = new Schema({
    fullName: { type: String, trim: true },
    photo: String,
    email: { type: String, trim: true },
    stripeAccountId: String,
    createdAt: {
        type: Date,
        default: Date.now,
    },
});

Seller onboarding with Account Links

For a current Accounts v2 integration, it is recommended to use Account Links or embedded onboarding.

An Account Link is a single-use URL that sends the connected account user to Stripe-hosted onboarding. Stripe collects the required verification and payout information and then redirects the user back to your platform.

Create an Account Link on the backend:

curl -X POST https://api.stripe.com/v2/core/account_links \
  -H "Authorization: Bearer {{STRIPE_SECRET_KEY}}" \
  -H "Stripe-Version: 2026-05-27.preview" \
  --json '{
    "account": "{{CONNECTED_ACCOUNT_ID}}",
    "use_case": {
      "type": "account_onboarding",
      "account_onboarding": {
        "configurations": ["recipient"],
        "refresh_url": "https://example.com/reauth",
        "return_url": "https://example.com/return"
      }
    }
  }'

The refresh_url is used when the Account Link has expired, has already been visited, or is otherwise invalid. In that case, your backend should generate a new Account Link.

The return_url is where Stripe redirects the user after they complete or exit onboarding. A return to this URL does not automatically mean that the account is fully verified or ready for payouts, so the platform still needs to retrieve the account and check its requirements and capability status.

If you are building a mobile application, do not open Stripe-hosted onboarding inside an embedded WebView. Open it in a secure browser flow instead. Alternatively, use Stripe’s embedded components where they are supported for your platform.

Checking seller payout readiness

Once the seller returns from onboarding, retrieve the connected account and check whether the required capability is active.

For a recipient account, the important capability is the ability to receive transfers to the Stripe balance. If the status is not active, the account may still have outstanding requirements.

A simplified backend check can look like this:

t const getConnectedAccount = async (stripeAccountId) => {
    return stripe.v2.core.accounts.retrieve(stripeAccountId, {
        include: ['configuration.recipient', 'requirements'],
    });
};

You should use the returned account data to decide whether to show:

  • onboarding completed status;
  • missing requirements;
  • payout disabled status;
  • a button that sends the seller back through onboarding.

You should also listen to account requirement webhooks, especially when requirements change after the account has already been onboarded.

Buyer payment flow

Stripe now recommends using the Payment Methods API with PaymentIntents. PaymentIntents track the lifecycle of a payment and support authentication flows such as 3D Secure, which is especially important for European payments and Strong Customer Authentication.

For web apps, you can use Stripe Checkout or the Payment Element. For React Native apps, use Stripe’s current React Native SDK and PaymentSheet or a supported custom flow.

A typical buyer payment flow looks like this:

  1. The buyer chooses a product or service.
  2. The frontend asks the backend to create a PaymentIntent.
  3. The backend creates the PaymentIntent with the order amount and currency.
  4. The frontend confirms the payment using Stripe’s SDK.
  5. The backend listens for payment webhooks and updates the order status.

If the buyer’s card requires authentication, Stripe handles the additional confirmation step through the PaymentIntent flow. 

Creating a buyer account or using Accounts v2 as customers

In older integrations, you usually created a Stripe Customer object for each buyer:

export const createCustomer = email =>
    stripe
        .customers
        .create({ email })
        .then(({ id }) => id);

With Accounts v2, Stripe allows platforms to represent a user as an Account with the customer configuration in many cases. This can reduce the need to maintain separate Account and Customer objects for the same user.

However, Stripe still supports the Customers API, and many existing integrations may continue to use Customers during migration. If your marketplace already has a working Customer-based buyer flow, you can migrate gradually.

For a new Accounts v2-first marketplace, consider using:

  • an Account with recipient configuration for sellers who receive transfers;
  • an Account with customer configuration for users who pay the platform;
  • both configurations when the same user can act as both seller and buyer.

How does Stripe work from a vendor’s perspective?

For implementing our target payment flow, you need to choose how funds should move. 

Destination charges

Destination charges are useful when the customer is paying for a product or service provided by a connected account and the platform wants to immediately transfer funds to that connected account.

In this flow:

  • the charge is created on the platform account;
  • the connected account receives the transferred funds;
  • the platform can collect an application fee;
  • the platform is generally responsible for Stripe fees, refunds, and chargebacks.

Example with Stripe Checkout:

curl https://api.stripe.com/v1/checkout/sessions \
  -u "{{STRIPE_SECRET_KEY}}:" \
  -d "line_items[0][price_data][currency]=usd" \
  -d "line_items[0][price_data][product_data][name]=T-shirt" \
  -d "line_items[0][price_data][unit_amount]=1000" \
  -d "line_items[0][quantity]=1" \
  -d "payment_intent_data[application_fee_amount]=123" \
  -d "payment_intent_data[transfer_data][destination]={{CONNECTED_ACCOUNT_ID}}" \
  -d mode=payment \
  --data-urlencode "success_url=https://example.com/success?session_id={CHECKOUT_SESSION_ID}"

This flow is convenient when the seller is known at checkout and the platform does not need to hold the seller’s funds until a later order milestone.

Separate charges and transfers

For our marketplace example, the platform needs to accept a buyer’s payment, wait until the customer receives the order, take a commission, and only then send the seller’s share.

In that case, separate charges and transfers are usually more suitable.

The flow looks like this:

  1. The buyer pays the platform.
  2. The payment succeeds and the platform stores the PaymentIntent ID.
  3. The order remains in a pending or in-progress status.
  4. Once the customer receives the order, the platform calculates the seller amount.
  5. The platform creates a transfer to the seller’s connected account.
  6. The platform keeps its commission.

First, create the PaymentIntent on the platform account:

export const createPaymentIntent = async ({ amount, currency, customerId, paymentMethodId }) => {
    return stripe.paymentIntents.create({
        amount,
        currency,
        customer: customerId,
        payment_method: paymentMethodId,
        confirm: true,
        automatic_payment_methods: {
            enabled: true,
            allow_redirects: 'never',
        },
    });
};

When the order is completed, create a transfer to the seller:

export const createTransfer = ({ amount, currency, stripeAccountId, paymentIntentId }) => {
    return stripe.transfers.create({
        amount,
        currency,
        destination: stripeAccountId,
        transfer_group: paymentIntentId,
    });
};

If you still need to reference the underlying Charge, you can retrieve it from the PaymentIntent after the payment succeeds. However, for new integrations, it is better to store the PaymentIntent ID as the main payment reference.

Getting the seller balance

After the seller is onboarded and has an active connected account, you can retrieve balance information for that account.

export const getBalance = async (stripeAccountId) => {
    if (!stripeAccountId) return null;

    return stripe.balance.retrieve({
        stripeAccount: stripeAccountId,
    });
};

In the application UI, this data can be shown on a “My Balance” page together with payout status, payout history, and account requirements.

For an Express Dashboard setup, you can also create a login link that lets the seller open the Stripe Express Dashboard:

export const createLoginLink = stripeAccountId =>
    stripe
        .accounts
        .createLoginLink(stripeAccountId)
        .then(({ url }) => url);

If you use dashboard: none, the seller will not have Stripe Dashboard access. In that case, your platform must provide the required account management, balance, payout, and reporting functionality. You can build this manually with the API or use Connect embedded components to embed dashboard-like functionality directly into your product.

Webhooks you need for a reliable marketplace payment flow

Do not rely only on frontend redirects or immediate API responses. Payment and onboarding flows can be asynchronous, and users can close the app or browser before the final callback runs.

At minimum, your marketplace should use webhooks for:

  • successful payments;
  • failed payments;
  • asynchronous payment completion;
  • refunds;
  • disputes;
  • account requirement updates;
  • transfer or payout status changes.

For Checkout-based flows, listen to events such as:

  • checkout.session.completed;
  • checkout.session.async_payment_succeeded;
  • checkout.session.async_payment_failed.

For PaymentIntent-based flows, listen to events such as:

  • payment_intent.succeeded;
  • payment_intent.payment_failed.

For Accounts v2 onboarding and verification updates, listen to account requirement events and send sellers back through onboarding when required information is missing, due, or past due.

Stripe dashboard: what to monitor

The Stripe Dashboard contains the key information associated with your marketplace app. By clicking on the Balance section, you can see the current balance of your platform. The Transactions section stores payments conducted through your platform.

From a developer’s point of view, we strongly recommend using the Developers menu, where you can find API logs, webhook events, request history, and API keys. This is especially useful when testing onboarding, payments, transfers, refunds, disputes, and payout status.

For connected accounts, the exact dashboard experience depends on your account configuration:

  • full gives connected accounts access to the full Stripe Dashboard;
  • express gives them access to the Express Dashboard;
  • none means your platform must provide the user-facing interface.

How long does it take to integrate Stripe Connect?

The timeline depends on the marketplace payment flow, account setup, countries, onboarding requirements, payout logic, and the level of UI control you want.

A simpler marketplace can use Stripe-hosted onboarding and Checkout with destination charges. A more advanced marketplace may require Accounts v2 configurations, delayed transfers, custom seller dashboards, embedded components, account requirement handling, refunds, disputes, and more complex payout logic.

The integration usually depends on:

  • whether users only sell, only buy, or can do both;
  • whether the seller needs recipient, merchant, or customer configuration;
  • whether you use Stripe-hosted onboarding, embedded components, or custom onboarding;
  • whether you use destination charges or separate charges and transfers;
  • whether the platform or connected account is responsible for fees, losses, and compliance workflows;
  • how refunds, disputes, cancellations, and failed payments are handled;
  • how much balance and payout functionality you want to show inside your own product.

A proper Stripe Connect integration is not just a payment form. It is a marketplace payment architecture that has to cover onboarding, verification, payment collection, commission logic, transfers, payouts, account status, webhooks, and compliance-related updates.

Stripe edge cases that are useful for marketplaces and platforms

One of the reasons Stripe is often chosen for marketplace and platform products is that it handles many payment edge cases that would otherwise require custom billing logic.

Subscription upgrades and downgrades

If your platform uses subscriptions, users may want to change their plan before the current billing period ends. For example, a seller may upgrade from a basic plan to a premium plan, or downgrade because they no longer need the same level of functionality.

Stripe Billing can handle this through prorations. When a subscription changes mid-cycle, Stripe can calculate how much of the previous plan was unused and how much of the new plan remains in the current billing period.

Depending on the change, the user can be:

  • charged the proportional difference when upgrading to a more expensive plan;
  • credited for unused time when downgrading to a cheaper plan;
  • billed immediately or at the next invoice, depending on how the platform configures the update.

This is especially useful for marketplaces with seller subscriptions, paid platform plans, premium vendor tools, or usage-based add-ons. Instead of building all subscription adjustment logic manually, the platform can rely on Stripe’s existing billing and invoice behavior.

Safer testing with Stripe Sandboxes

Another important advantage is Stripe’s testing environment. Before going live, developers can test the payment flow with sandbox data and test cards without real charges or money movement.

This is useful not only for checking a basic card payment, but also for testing more complex marketplace scenarios, such as:

  • successful and failed payments;
  • payment authentication flows;
  • refunds and disputes;
  • seller onboarding;
  • account requirement updates;
  • transfers and payout-related flows;
  • webhook handling;
  • subscription plan changes.

For a marketplace product, this matters a lot. Payment flows often involve several users and several states: buyer payment, seller onboarding, order confirmation, commission logic, transfers, refunds, disputes, and payouts. Testing these cases before launch helps developers catch integration issues before real customers and sellers are affected.

Importance of proper payment system evaluation

Here at Apiko, we’ve already covered Stripe in the Payment Gateway Integration article as a powerful and easily integrated solution.

When developing a marketplace app, a lot of focus goes on the homepage and design — it’s the first thing visitors see when they arrive. Still, don’t miss out on proper payment system evaluation, since payments are a milestone of marketplace app structure.

A marketplace payment system has to be user-friendly, time- and cost-effective, professional-looking, and reliable enough to manage dozens, hundreds, or thousands of transactions. Looks like too much? No worries, you can always get professional consultation from our software integration services team.

Conclusion

Stripe Connect can be a strong payment infrastructure choice for marketplaces, platforms, and eCommerce products that need to onboard sellers, accept customer payments, collect platform commissions, and route funds to connected accounts.

At Apiko, we help businesses design and integrate payment systems that match their marketplace logic, user roles, payout rules, and long-term product plans. If you need to build or update a Stripe Connect integration, our software integration team can help you choose the right payment flow and implement it reliably.