Skip to main content
The Payout module ships its workflows in packages/core/src/workflows/payout. Import them, and their steps, from @mercurjs/core/workflows. The events they emit are listed in Events. Core doesn’t schedule any of them; see The payout pipeline.

createPayoutAccountWorkflow

Creates a payout account for a seller through the provider, links it to the seller and publishes the onboarding link. Workflow id create-payout-account-workflow. Steps, in order:
  1. use-query-graph-step (payout-account-seller-query): loads the seller’s profile and current account
  2. validate-seller-without-payout-account: fails with 409 when the seller already has an account
  3. create-payout-account: calls the service’s createPayoutAccount with the seller’s profile; on rollback, deletes the account with deletePayoutAccount, at the provider too when it supports deleteAccount
  4. create-remote-links: links the seller and the account
  5. create-onboarding: publishes the onboarding link
Returns the PayoutAccountDTO. Exposes no hooks.

createOrRefreshSellerPayoutAccountWorkflow

Makes sure one seller has an account and, until they submit their details, a current onboarding link. Workflow id create-or-refresh-seller-payout-account. Safe to run on every seller change. It loads the seller, runs createPayoutAccountWorkflow when no account exists, and otherwise publishes a fresh onboarding link while the account still needs onboarding, because provider links expire. Returns { account_id, onboarding_published }.

linkPayoutAccountWorkflow

Attaches an account that already exists at the provider to a seller, behind POST /admin/payout-accounts. Workflow id link-payout-account. It validates that the seller has no account, stores the account without calling the provider (create-payout-accounts, deleted on rollback), links it, then runs syncPayoutAccountWorkflow. Returns the synced PayoutAccountDTO.

createOnboardingWorkflow

Publishes the next link for a payout account. Workflow id create-onboarding-workflow, exported as createOnboardingWorkflowId. It runs one step, create-onboarding, and returns the OnboardingDTO. The service picks an onboarding link or, once details are submitted, a dashboard login link.

refreshPayoutAccountLinkWorkflow

Publishes a new link for an account, behind POST /admin/payout-accounts/:id/refresh-link. Workflow id refresh-payout-account-link. Input { id }; it runs create-onboarding and returns the OnboardingDTO.

refreshOnboardingWorkflow

Exchanges an expired onboarding link for a fresh one, behind the public GET /payout/onboarding/refresh?token=. Workflow id refresh-onboarding. Input { token }; it finds the account by onboarding_token and fails (validate-onboarding-token) with 404 when none matches, or with 400 when the token is older than the module’s onboarding.tokenTtlSeconds (24 hours by default). It then runs create-onboarding with rotate_token, so the used token stops working and the new link’s refresh URL carries a new one, and returns { url }.

syncPayoutAccountWorkflow

Re-reads an account from the provider. Workflow id sync-payout-account. Steps, in order:
  1. sync-payout-account-step: calls the service’s syncPayoutAccount; restores the previous fields on rollback
  2. create-onboarding: only when details_submitted is true, to publish the dashboard login link
  3. Emits payout_account.updated with { id }
Returns the PayoutAccountDTO.

createOrderPayoutsWorkflow

Pays each order’s seller their share. Workflow id create-order-payouts, exported as createOrderPayoutsWorkflowId.
Steps, in order:
  1. use-query-graph-step (payout-orders-query, existing-payouts-query, payout-commission-lines-query): loads the orders with their fulfillments and payments, their existing payouts, and their commission lines
  2. create-payouts: one new payout per order without one; deleted on rollback unless it was already sent
  3. update-payouts: re-decides payouts that are on_hold or failed; restored on rollback unless it was already sent
  4. create-remote-links: links new payouts to the seller and the order
  5. process-payouts: sends each pending payout with the service’s processPayout
  6. Emits payout.failed with { id } for every payout the provider refused
Returns { counts, payouts }: the number of payouts per resulting status, such as { paid: 2, on_hold: 1 }, and the payouts sent in this run. Payouts that are already paid, processing, or aborted are skipped.

createPayoutReversalsWorkflow

Takes refunded shares back. Workflow id create-payout-reversals. It loads the orders’ refunds, payouts and commission lines, then creates or re-decides one reversal per refund on an order whose payout exists, net of commission, skipping refunds already deducted from the payout (create-payout-reversals-step, update-payout-reversals). It sends each pending reversal with process-payout-reversals and emits payout.reversal_failed for refusals. Returns { counts, reversals }.

processPayoutWorkflow

Sends existing payouts again. Workflow id process-payout. It runs process-payouts and emits payout.failed for refusals. Payouts that aren’t pending or failed are returned unchanged.

retryPayoutWorkflow

Retries one payout, behind POST /admin/payouts/:id/retry. Workflow id retry-payout. Input { id }. It fails with 400 unless the payout is failed, on_hold or pending (validate-payout-retry). A failed or on_hold order payout runs createOrderPayoutsWorkflow for its order, so it is re-decided first. A pending payout, and any payout without an order, runs processPayoutWorkflow and is sent as is.

processPayoutReversalWorkflow

Sends existing reversals again. Workflow id process-payout-reversal. Input { reversal_ids: string[] }; it runs process-payout-reversals and emits payout.reversal_failed for refusals.

processPayoutForWebhookWorkflow

Applies a parsed provider webhook. Workflow id process-payout-for-webhook, exported as processPayoutForWebhookWorkflowId. Its input is a PayoutWebhookResult: an action and an optional data with id, the provider’s object id, and for payout events payout_id, Mercur’s payout id. The status update runs update-payouts. Returns nothing.

Steps

You can compose these steps into your own workflows:
The process steps and create-onboarding have no compensation. Money that reached the provider, or a link a seller already received, can’t be undone by a rollback; a payout’s status, status_reason, and data.attempts record what happened instead, and the next run picks up where it stopped. For the same reason, the create and update compensations skip a payout or reversal that is processing or paid, or was attempted after the step ran.