Skip to main content
The Payout module owns vendor payout accounts, provider onboarding, and payout records. It delegates account creation, onboarding, and payout execution to a single registered payout provider — Stripe Connect ships out of the box — and enforces that payouts only fire for active accounts. For the conceptual introduction, see Payouts.

Data models

PayoutAccount

Table payout_account, ID prefix pacc. One per seller (linked via the seller module).
FieldTypeNotes
statusenumPayoutAccountStatus, default pending
datajsonProvider-owned account data
contextjsonNullable; creation context passed to the provider
Relations: onboarding (one-to-one), payouts (one-to-many).

Payout

Table payout, ID prefix pout.
FieldTypeNotes
display_idautoincrementHuman-readable number
currency_codetext
amountbigNumber
statusenumPayoutStatus, default pending
datajsonNullable; provider response data

Onboarding

Table onboarding, ID prefix onb. Holds the provider’s onboarding state for an account:
FieldTypeNotes
datajsonNullable; e.g. the Stripe onboarding link
contextjsonNullable; e.g. return/refresh URLs

Enums

enum PayoutAccountStatus {
  PENDING = "pending",
  ACTIVE = "active",
  RESTRICTED = "restricted",
  REJECTED = "rejected",
}

enum PayoutStatus {
  PENDING = "pending",
  PROCESSING = "processing",
  PAID = "paid",
  FAILED = "failed",
  CANCELED = "canceled",
}
Linked entityCardinalityPurpose
SellerPayoutAccountone-to-oneA seller’s provider account
SellerPayoutone seller — many payoutsSettlement history
Order.orderPayoutone order — many payoutsTraces a payout back to the order it settles

Service

PayoutModuleService extends MedusaService with auto-generated CRUD, plus:
MethodBehavior
createPayoutAccount(input)Creates the local record, calls the provider with an idempotency key, stores the provider’s data and status; deletes the local record if the provider call fails
createOnboarding(input)Calls the provider and upserts the onboarding record for the account
createPayouts(input)Asserts the account is active, calls the provider, persists the payout with the provider’s data and status
getWebhookActionAndData(input)Resolves an incoming provider webhook into a payout action (consumed by POST /hooks/payout)
getOptions()Returns the merged module options

Module options

OptionTypeDefaultPurpose
providersarrayProvider registrations (resolve, id, options)
disabledbooleanfalseTurns payout processing off
authorizationWindowMsnumber7 daysHow long a payment authorization is trusted before capture must happen
sellerActionWindowMsnumber72 hHow long the seller has to act (e.g. fulfill) before escalation
captureSafetyBufferMsnumber24 hSafety margin before the authorization expires
requiredFulfillmentStatusstring"fulfilled"Fulfillment state an order must reach before its payout is generated

Provider interface

Exactly one payout provider must be registered (under the payout_ registration prefix); the module throws at boot otherwise. A provider implements four verbs:
interface PayoutProvider {
  createPayoutAccount(input): Promise<{ data; status }>
  createOnboarding(input): Promise<{ data }>
  createPayout(input): Promise<{ data; status }>
  getWebhookActionAndData(payload): Promise<PayoutWebhookResult>
}
The Stripe Connect implementation lives in @mercurjs/payout-stripe-connect — see Configuration for its options and Stripe Connect integration for the setup guide.
  • GET /admin/payouts — platform-wide payout monitoring
  • GET /vendor/payouts, GET/POST /vendor/payout-accounts, POST /vendor/payout-accounts/:id/onboarding — seller-side account and history
  • POST /hooks/payout — provider webhook receiver

Next steps

Stripe Connect integration

Configuration