@moneydevkit/nextjs is the moneydevkit checkout SDK for App Router-based Next.js apps. It bundles the client hook, hosted checkout UI, API route handler, and config helpers required to launch Lightning-powered payments within minutes.Install with AI Coding Tools
Use an AI coding assistant to set up moneydevkit in your project. Choose the option that matches your situation:- New Account
- Existing Account
Creates a moneydevkit account and implements the SDK for you.Claude Code:ChatGPT Codex:
Cursor
Click to install MCP in Cursor
VS Code
Click to install MCP in VS Code
Setup
- Create a Money Dev Kit account at moneydevkit.com or run
npx @moneydevkit/createto generate credentials locally, then grab yourapi_keyand mnemonic. - Install the SDK in your project:
- Add required secrets to
.env(or similar):
Quick Start (Next.js App Router)
1
Trigger a checkout from any client component
2
Render the hosted checkout page
3
Expose the unified Money Dev Kit endpoint
4
Configure Next.js
Verify successful payments
When a checkout completes, useuseCheckoutSuccess() on the success page.
Server-side payouts
Programmatic payouts let your server send sats out to a Lightning destination (BOLT11 invoice, BOLT12 offer, or LNURL / Lightning address) without any user interaction. They must run from a server function (Server Action, route handler, cron, webhook), and the app must have programmatic payouts enabled in the moneydevkit dashboard.Minimal example
About idempotencyKey
The key is how moneydevkit dedupes retries. If your code (or a cron, or a Vercel retry) fires the same payout twice with the same key, the second call is a no-op instead of a double-pay.
- Do use a stable id from your own database:
orderId,withdrawalId,userId + payoutDate. - Don’t generate a fresh
crypto.randomUUID()on every call. That defeats the whole point and you can double-pay. - It’s just a string, any length, your choice.
Full example with error handling
result.error tells you whether the failure is worth retrying:
result.error.retryable === true- transient (daily limit, dispatch failure). Retry the same call with the sameidempotencyKey.result.error.retryable === false- retrying won’t help. Fix the input or your config.result.error.retryable === undefined- the SDK couldn’t classify it. Log and inspect.
Common gotchas
- Don’t call from client code.
programmaticPayoutchecks forwindowand refuses to run in a browser. Server Actions, route handlers, cron jobs, or webhook receivers only. - Set
MDK_ACCESS_TOKEN. Same env var as the rest of the SDK. If missing, you getmissing_access_token(not retryable). - Always pass the same
idempotencyKeyon retry. Changing it makes moneydevkit treat it as a new payout - and you can double-pay.
Error reference
result.error.reason is a short machine-readable string. Use it for branching; use result.error.message for logs.
Client-side validation errors (always
retryable: false):
Reading the merchant balance
getBalance() reads the spendable (outbound) balance of the Lightning node tied to your MDK_ACCESS_TOKEN. Same server-only constraints as programmaticPayout: refuses to run in a browser, routes through mdk.com over HTTPS, which in turn dials the merchant node over the WS control plane.
The first call after the merchant function has been idle may take a few seconds: mdk.com fires a spin-up webhook and waits for the node to register. Subsequent calls within the same function lifetime are fast.
Notes
- App-scoped API key required. Balance is meaningful per-app, not per-org. Legacy org-level keys return
GET_BALANCE_APP_KEY_REQUIRED(not retryable). Use the API key from the App page in the dashboard. - Server-only. Same
typeof windowguard asprogrammaticPayout. Don’t import from a client component. - Idempotent. Safe to retry. Transient errors are flagged
retryable: true; auth and config errors areretryable: false.
Error reference
Customers
Collect customer information during checkout to track purchases and enable refunds.Product Checkouts
Sell products defined in your Money Dev Kit dashboard usingtype: 'PRODUCTS':

