Skip to main content
Create a seller’s payout account from server code, for example in an operator route or a custom signup flow. The Vendor API already does this for sellers at POST /vendor/payout-accounts.

Before you begin

You need:
  • A seller id, such as sel_01JD8Q1234567
  • A payout provider. Without one, the system provider creates accounts that are active at once
  • For Stripe Connect, @mercurjs/stripe-connector-plugin/providers/payout-stripe-connect registered on the payout module, as in the Stripe Connect integration

Create the account

1

Add a route that runs the workflow

Create an admin route that takes the seller id from the path and the provider data from the body:
src/api/admin/payout-setup/[id]/route.ts
The workflow validates the seller has no account, creates it through the provider, links it to the seller, and publishes the onboarding link. The response returns only the id, because result.data holds the full provider object.
2

Call the route

Send the seller’s country. The module passes data.country to the provider, falling back to the seller’s address and then the onboarding.defaultCountry option:
With Stripe Connect, the new account is pending, external_id holds the Stripe acct_… id, and data holds the Express account Stripe created.

Handle a seller that already has an account

validateSellerPayoutAccountStep runs first and throws a MedusaError of type INVALID_DATA with the message Seller already has a payout account. Medusa returns it as a 400. To reuse the existing account instead, look it up through the seller link:

What happens when the provider call fails

The module creates the PayoutAccount row before it calls the provider. If the provider throws, the module deletes that row and rethrows, so no orphaned account is left. The provider receives the new pacc id as data.account_id, metadata.account_id, and the default context.idempotency_key, so a retried call doesn’t create a second provider account. Webhooks find the account later by its external_id. If you already have an account at the provider, map it instead of creating one: POST /admin/payout-accounts with seller_id and external_id links it to the seller and syncs it from the provider.

Next steps