


Implementing Stripe Connect in WeWeb with Supabase: Architecture and Webhooks
Implementing Stripe Connect in WeWeb with Supabase: Architecture and Webhooks
Implementing Stripe Connect in WeWeb with Supabase: Architecture and Webhooks
By
Jocsan Morera
Published on:
Oct 6, 2025
Payment integration is one of the most critical components of any SaaS platform or marketplace. In our case, we didn’t just want to accept subscription payments for our own service, we wanted to allow multiple businesses to receive payments directly through our platform. This required a solution that could handle account onboarding, payment routing, and commissions. For this reason, we chose Stripe Connect, a powerful tool that enables multi-party payments but requires a carefully designed architecture to work safely in a no-code environment like WeWeb.
In this article, I’ll walk you through how we implemented Stripe Connect using Supabase as our backend, WeWeb as the frontend, and a combination of Edge Functions and webhooks to tie everything together. Along the way, we’ll look at key differences between standard Stripe and Stripe Connect, how we solved synchronization and security challenges, and the best practices we developed to ensure the system remains scalable and maintainable.
Architecture and Overall Flow
From day one, we knew that keeping sensitive keys and payment logic out of the frontend was essential. WeWeb is excellent for building interfaces quickly, but the client should never have direct access to Stripe’s APIs. This is why we built our integration around Supabase Edge Functions, which act as secure middleware between the frontend and Stripe.
The data flow is simple but powerful: the frontend triggers a request to create an account, checkout session, or subscription. The Edge Function securely calls Stripe using the correct secret keys, then returns only the necessary data to the frontend. When an important event occurs — for example, a completed payment, an account verification, or a subscription cancellation — Stripe sends a webhook to another Edge Function, which updates the database accordingly. This approach keeps the frontend, backend, and Stripe in sync and provides a clear audit trail of every transaction.

Creating and Managing Connect Accounts
One of the first challenges was implementing the creation of Stripe Connect Express accounts, allowing each business to receive payments directly. Rather than making calls to Stripe from WeWeb, we built a dedicated Edge Function that receives the business_id, creates the account in Stripe, and stores the resulting stripe_account_id in our database.
This step ensures that every business in our system is tied to the correct Stripe account and that we can later use this ID to route payments, generate transfers, and display the correct onboarding status. We also implemented an onboarding flow that allows business owners to complete their verification process in Stripe. Tracking account requirements such as charges_enabled and payouts_enabled turned out to be critical. Without this, a business might attempt to charge customers before their account is ready to receive funds. Our WeWeb dashboard shows the onboarding state in real time, ensuring a smooth experience for users.

Webhook Handling and Synchronization
Synchronization between Stripe and our database was one of the most challenging aspects. Stripe sends multiple events for the same transaction, sometimes out of order, and will retry events if no 200 OK is received. Without careful handling, this can lead to duplicate records or inconsistent states.
To solve this, we implemented an idempotency check by storing every processed event_id in our database and discarding duplicates. We also store the full Stripe object in a stripe_result JSON column, which allows us to re-process events later if we improve our business logic or need to audit a payment. This design choice has been invaluable in production — for example, when troubleshooting failed payments, chargebacks, or disputes.
Another key insight was realizing that two different webhook endpoints are needed when working with Connect. The first webhook listens to platform-level events (such as subscription payments, invoices, or customer updates) that occur in the main Stripe account. The second webhook is specifically configured for Connect events (such as account onboarding, payout status, or capability updates) that originate from connected accounts. Keeping these separated helps us apply different logic depending on the event type and prevents us from mixing platform workflows with account-specific operations.
By designing the webhook system this way, we were able to keep both types of events clear and maintain a clean separation of concerns between the platform’s billing and the connected accounts’ onboarding and payouts.

Standard Stripe vs. Stripe Connect: Key Insights
One of the most important lessons we learned was understanding that Stripe Connect is fundamentally different from standard Stripe. In a regular Stripe integration, the platform itself is the merchant of record, meaning all payments go into a single account, and it’s the platform’s responsibility to distribute funds manually.
With Connect, the money flows directly to connected accounts, which requires specifying in every payment who the real recipient is. This is done through parameters like on_behalf_of and transfer_data, which ensure that payments are attributed correctly and funds are deposited into the right balance.
We also use the application_fee_amount parameter to automatically apply our platform commission on every transaction. This means we no longer need to create separate invoices or manual charges to collect fees, simplifying both the accounting and the user experience.
Another key decision was how to handle customers, invoices, and products. In Stripe Connect, these objects can live either in the platform account or directly inside each connected account. We chose to manage them inside the connected accounts, so that every business owns its own customers, subscriptions, and invoices natively in Stripe.
This approach ensures that each business has full control and visibility over its billing, while the platform simply acts as the orchestrator. The trade-off is that reporting and synchronization become more complex, since the platform needs to query multiple accounts rather than a single source of truth. However, this model better aligns with our business goals: businesses remain independent, their Stripe dashboards reflect their actual customers and payments, and the platform can still collect its fees through application_fee_amount on each transaction.
Managing Customers in Stripe and the Database
Maintaining the relationship between our users and their corresponding Stripe customers was critical for invoicing and subscriptions. Whenever a user signs up in our app, we immediately create a customer object in Stripe and store its stripe_customer_id in our database. This allows us to reliably associate invoices, subscriptions, and payments.
We also listen to customer.updated webhooks so that if the customer updates their email or payment method from the Stripe billing portal, we synchronize those changes in our database. This two-way synchronization prevents stale data and keeps our dashboard accurate without requiring manual updates.

Conclusion
Integrating Stripe Connect with WeWeb and Supabase was ultimately about building financial infrastructure, not just payment integration. By centralizing critical logic in Edge Functions, validating every event with dedicated webhooks, and carefully isolating multi-tenant data, we created a billing system that is secure, scalable, and trusted by businesses.
The journey showed us that success lies in solving deeper challenges of concurrency, compliance, and data synchronization. Payments at scale are about more than moving money; they are about ensuring accuracy, transparency, and resilience in the face of complexity. Our architecture now supports businesses confidently, providing both independence through connected accounts and oversight through the platform.
Most importantly, we learned that trust is the true currency of payment systems. Every processed invoice, every transparent payout, and every consistent report builds confidence in the platform. By approaching Stripe Connect not as a feature but as a core infrastructure layer, we positioned our platform for sustainable growth and long-term reliability.
Payment integration is one of the most critical components of any SaaS platform or marketplace. In our case, we didn’t just want to accept subscription payments for our own service, we wanted to allow multiple businesses to receive payments directly through our platform. This required a solution that could handle account onboarding, payment routing, and commissions. For this reason, we chose Stripe Connect, a powerful tool that enables multi-party payments but requires a carefully designed architecture to work safely in a no-code environment like WeWeb.
In this article, I’ll walk you through how we implemented Stripe Connect using Supabase as our backend, WeWeb as the frontend, and a combination of Edge Functions and webhooks to tie everything together. Along the way, we’ll look at key differences between standard Stripe and Stripe Connect, how we solved synchronization and security challenges, and the best practices we developed to ensure the system remains scalable and maintainable.
Architecture and Overall Flow
From day one, we knew that keeping sensitive keys and payment logic out of the frontend was essential. WeWeb is excellent for building interfaces quickly, but the client should never have direct access to Stripe’s APIs. This is why we built our integration around Supabase Edge Functions, which act as secure middleware between the frontend and Stripe.
The data flow is simple but powerful: the frontend triggers a request to create an account, checkout session, or subscription. The Edge Function securely calls Stripe using the correct secret keys, then returns only the necessary data to the frontend. When an important event occurs — for example, a completed payment, an account verification, or a subscription cancellation — Stripe sends a webhook to another Edge Function, which updates the database accordingly. This approach keeps the frontend, backend, and Stripe in sync and provides a clear audit trail of every transaction.

Creating and Managing Connect Accounts
One of the first challenges was implementing the creation of Stripe Connect Express accounts, allowing each business to receive payments directly. Rather than making calls to Stripe from WeWeb, we built a dedicated Edge Function that receives the business_id, creates the account in Stripe, and stores the resulting stripe_account_id in our database.
This step ensures that every business in our system is tied to the correct Stripe account and that we can later use this ID to route payments, generate transfers, and display the correct onboarding status. We also implemented an onboarding flow that allows business owners to complete their verification process in Stripe. Tracking account requirements such as charges_enabled and payouts_enabled turned out to be critical. Without this, a business might attempt to charge customers before their account is ready to receive funds. Our WeWeb dashboard shows the onboarding state in real time, ensuring a smooth experience for users.

Webhook Handling and Synchronization
Synchronization between Stripe and our database was one of the most challenging aspects. Stripe sends multiple events for the same transaction, sometimes out of order, and will retry events if no 200 OK is received. Without careful handling, this can lead to duplicate records or inconsistent states.
To solve this, we implemented an idempotency check by storing every processed event_id in our database and discarding duplicates. We also store the full Stripe object in a stripe_result JSON column, which allows us to re-process events later if we improve our business logic or need to audit a payment. This design choice has been invaluable in production — for example, when troubleshooting failed payments, chargebacks, or disputes.
Another key insight was realizing that two different webhook endpoints are needed when working with Connect. The first webhook listens to platform-level events (such as subscription payments, invoices, or customer updates) that occur in the main Stripe account. The second webhook is specifically configured for Connect events (such as account onboarding, payout status, or capability updates) that originate from connected accounts. Keeping these separated helps us apply different logic depending on the event type and prevents us from mixing platform workflows with account-specific operations.
By designing the webhook system this way, we were able to keep both types of events clear and maintain a clean separation of concerns between the platform’s billing and the connected accounts’ onboarding and payouts.

Standard Stripe vs. Stripe Connect: Key Insights
One of the most important lessons we learned was understanding that Stripe Connect is fundamentally different from standard Stripe. In a regular Stripe integration, the platform itself is the merchant of record, meaning all payments go into a single account, and it’s the platform’s responsibility to distribute funds manually.
With Connect, the money flows directly to connected accounts, which requires specifying in every payment who the real recipient is. This is done through parameters like on_behalf_of and transfer_data, which ensure that payments are attributed correctly and funds are deposited into the right balance.
We also use the application_fee_amount parameter to automatically apply our platform commission on every transaction. This means we no longer need to create separate invoices or manual charges to collect fees, simplifying both the accounting and the user experience.
Another key decision was how to handle customers, invoices, and products. In Stripe Connect, these objects can live either in the platform account or directly inside each connected account. We chose to manage them inside the connected accounts, so that every business owns its own customers, subscriptions, and invoices natively in Stripe.
This approach ensures that each business has full control and visibility over its billing, while the platform simply acts as the orchestrator. The trade-off is that reporting and synchronization become more complex, since the platform needs to query multiple accounts rather than a single source of truth. However, this model better aligns with our business goals: businesses remain independent, their Stripe dashboards reflect their actual customers and payments, and the platform can still collect its fees through application_fee_amount on each transaction.
Managing Customers in Stripe and the Database
Maintaining the relationship between our users and their corresponding Stripe customers was critical for invoicing and subscriptions. Whenever a user signs up in our app, we immediately create a customer object in Stripe and store its stripe_customer_id in our database. This allows us to reliably associate invoices, subscriptions, and payments.
We also listen to customer.updated webhooks so that if the customer updates their email or payment method from the Stripe billing portal, we synchronize those changes in our database. This two-way synchronization prevents stale data and keeps our dashboard accurate without requiring manual updates.

Conclusion
Integrating Stripe Connect with WeWeb and Supabase was ultimately about building financial infrastructure, not just payment integration. By centralizing critical logic in Edge Functions, validating every event with dedicated webhooks, and carefully isolating multi-tenant data, we created a billing system that is secure, scalable, and trusted by businesses.
The journey showed us that success lies in solving deeper challenges of concurrency, compliance, and data synchronization. Payments at scale are about more than moving money; they are about ensuring accuracy, transparency, and resilience in the face of complexity. Our architecture now supports businesses confidently, providing both independence through connected accounts and oversight through the platform.
Most importantly, we learned that trust is the true currency of payment systems. Every processed invoice, every transparent payout, and every consistent report builds confidence in the platform. By approaching Stripe Connect not as a feature but as a core infrastructure layer, we positioned our platform for sustainable growth and long-term reliability.