The payout account
A payout account is the record a payout is sent to. It’s thePayoutAccount data model (table payout_account, id prefix pacc), and the seller_payout_account link ties it to exactly one seller.
You create one with createPayoutAccountWorkflow. The workflow checks the seller has no account yet, asks the module to create the account with the seller’s profile, links it to the seller, and publishes the first onboarding link:
createPayoutAccount runs 3 writes in order:
- Create the
PayoutAccountrow with yourdataandcontext - Call the provider’s
createAccountwithdata.account_idandmetadata.account_idset to the newpaccid, andcontext.idempotency_keydefaulting to the same id - Store the provider’s account id as
external_id, its flags, the derivedstatusandkyc_status, and itsdata
pending. The built-in system provider returns an active account at once.
With the onboarding.prefill option, the module also passes the seller’s name, website, email, phone, country, and business type, so the provider can prefill its forms. onboarding.defaultCountry applies when the seller has no address.
createOrRefreshSellerPayoutAccountWorkflow does this for one seller only when needed: it creates the account when it’s missing, and otherwise publishes a fresh onboarding link until the seller has submitted their details. Run it again as often as you like.
A seller can have only one payout account.
validateSellerWithoutPayoutAccountStep fails with a 409 when the seller already has one.Onboarding
Onboarding is the provider’s setup flow: identity checks, bank details, and anything else the provider needs. Its state lives in theOnboarding data model (table onboarding, id prefix onb), a one-to-one child of the payout account.
createOnboardingWorkflow takes an account_id and calls the provider’s createOnboarding with the account’s external_id, a refresh_url, and a return_url. By default both URLs come from the module’s onboarding options: return_url is onboarding.returnUrl, and refresh_url is <onboarding.refreshBaseUrl>/payout/onboarding/refresh?token=<onboarding_token>. Pass them in data to override:
data holds what the provider returned, plus url, kind (onboarding or login), and expires_at. For Stripe Connect, data.url is the hosted onboarding page. The workflow is safe to re-run:
- First run: creates the
Onboardingrecord - Later runs: update the same record with new provider data, which you need when a Stripe link expires
Provider data and context
Every payout record has adata JSON field, and accounts and onboarding records also have context. They play different roles:
data: the provider’s durable payload, such as the Stripe account, the account link, or the transfer behind a payoutcontext: per-call hints for the provider, today onlyidempotency_key
data. It passes it to the provider and stores what comes back. When you switch providers, the records keep the same shape.
Related
- Account lifecycle for the statuses an account moves through after onboarding
- Create a payout account for a full route example
- Start provider onboarding for the onboarding route