Skip to main content
moneydevkit is self-custodial — your app runs its own Lightning node, and moneydevkit never holds your money. A payout moves funds off that node: either to a wallet you control, or (with programmatic payouts) to a destination your own server code chooses to pay. There are three ways to pay out. Choose one under How do you want to receive payouts? on the Payouts page of the dashboard:
MethodWho initiatesWhere the money goes
ManualYou, from the dashboardYour WITHDRAWAL_DESTINATION
Auto-payoutmoneydevkit, on every incoming paymentYour WITHDRAWAL_DESTINATION
ProgrammaticYour app’s server codeA destination your code supplies
Manual withdrawals are always available, whichever method you select.

Setting your payout destination

Manual and automatic payouts send funds to a destination that only your app knows — moneydevkit never sees it. Set WITHDRAWAL_DESTINATION in your app’s environment variables to a Lightning Address (name@domain), LNURL, or Bolt12 offer:
WITHDRAWAL_DESTINATION=yourname@walletdomain.com

How do I payout to CashApp?

Make sure you have a CashApp account with the ability to send and receive Bitcoin. Find your CashTag by tapping your profile picture in the top right of CashApp. Your cashtag will have a $ sign in front of it. Set your WITHDRAWAL_DESTINATION to your cashtag@cash.app. Do not include the $.
WITHDRAWAL_DESTINATION=cashtag@cash.app

How do I payout to Phoenix wallet?

Tap “Receive” then select “Reusable” for a Bolt12 offer. Tap “Copy” then copy “Lightning Bolt12.” Your Bolt12 offer should start with lno. Set WITHDRAWAL_DESTINATION to your Bolt12 offer.
WITHDRAWAL_DESTINATION=lno...

Manual payouts

The default. On the Payouts page, enter an amount in sats (or click Send max) and click Send payout. Your node pays the amount to your WITHDRAWAL_DESTINATION. The dashboard shows how much is available to withdraw, which is slightly less than your total balance — a small portion is reserved to cover Lightning routing fees.

Automatic payouts

The recommended option for most apps. With Auto-payout enabled, every incoming payment triggers a payout of your full balance to your WITHDRAWAL_DESTINATION. A small routing-fee reserve is kept back, so some funds always remain on the node. There’s nothing to schedule or configure beyond WITHDRAWAL_DESTINATION — it just runs after each payment. Failed payouts are retried automatically, and you can still withdraw manually whenever you like.

Programmatic payouts

An advanced option that lets your app’s server code send Lightning payments — to destinations your code supplies, not your WITHDRAWAL_DESTINATION. This is what powers agentic commerce flows like paying L402 invoices with pay402, or any business logic where your app pays a supplier, affiliate, or user out of its own balance. The Merch Store example uses it to pay a print-on-demand supplier on every sale. Enable it by selecting Programmatic payouts on the Payouts page. Your app also needs an app-scoped MDK_ACCESS_TOKEN in its environment — programmatic payout requests are authenticated and scoped to a single app. From code, use programmaticPayout (or pay402, which wraps it) from @moneydevkit/nextjs/server:
import { programmaticPayout, waitForPayoutResult } from "@moneydevkit/nextjs/server";

const { paymentId } = await programmaticPayout({
  destination: "lnbc1...", // BOLT11, BOLT12, LNURL, or Lightning Address
  amountSats: 21000,       // required unless the BOLT11 has a fixed amount
  idempotencyKey: `order-${orderId}`,
});

const result = await waitForPayoutResult({ paymentId });
Several safety mechanisms are built in:
  • Idempotency keys are required. Every payout needs a stable idempotencyKey; retrying with the same key returns the original result instead of paying twice. Reusing a key with a different amount is rejected.
  • Per-request cap. A single payout can’t exceed a platform-enforced maximum (currently 1,000,000 sats by default). Larger requests fail with amount_too_large.
  • Rolling daily limit. Each app has a rolling 24-hour programmatic payout budget (currently 5,000,000 sats by default). Requests over the limit fail with daily_limit_exceeded. Manual and automatic payouts don’t count against this budget.
  • Everything is recorded. Programmatic payouts appear in your payout history on the Payouts page, just like withdrawals.
If programmatic payouts are disabled for the app, requests fail with programmatic_payouts_disabled — flip the switch on the Payouts page to resolve it.