Developers
SDKs
Official libraries for Node.js / TypeScript, PHP and Python. Same resources, same behaviour, same safety guarantees.
| Language | Package | Requires |
|---|---|---|
| TypeScript / JavaScript | @muny/sdk | Node 18+, Bun, Deno, edge runtimes |
| PHP | muny/muny-php | PHP 8.1+, ext-curl, ext-json |
| Python | muny | Python 3.9+ |
All three have zero runtime dependencies and share the same design:
- Idempotency built in. Creating a payment intent, checkout session, payout or payout batch always sends an
Idempotency-Keyand reuses it on retries, so a network blip never charges or pays twice. Pass your own key (your order id) to make your own retries safe too. - Retries with exponential backoff and jitter on connection errors,
429(honouringRetry-After) and5xx— only for safe or idempotent requests. - Typed errors carrying status, type, code, request id and details: authentication, permission, not found, invalid request, idempotency, conflict, risk, rate limit, API and connection errors.
- Money is always a string. Amounts are decimal strings; the Python SDK rejects floats outright.
- Webhook verification with constant-time comparison and a 5-minute replay window.
Node.js / TypeScript#
npm install @muny/sdkimport { Muny } from "@muny/sdk";
const muny = new Muny({ apiKey: process.env.MUNY_API_KEY });
const payment = await muny.paymentIntents.create({
display_amount: "29.00", // price in your currency…
display_currency: "USD", // …Muny quotes the MUNY amount
reference: "ORDER-48291",
success_url: "https://shop.example/thanks",
});
redirect(payment.checkout_url);Secret keys are server-side only — the SDK refuses to run with an apiKey in a browser. Create the payment on your server and redirect the customer to checkout_url.
PHP#
composer require muny/muny-php$muny = new \Muny\MunyClient(['api_key' => getenv('MUNY_API_KEY')]);
$payment = $muny->paymentIntents->create([
'display_amount' => '29.00',
'display_currency' => 'USD',
'reference' => 'ORDER-48291',
'success_url' => 'https://shop.example/thanks',
]);
header('Location: ' . $payment->checkout_url);Python#
pip install munyimport os, muny
client = muny.Muny(api_key=os.environ["MUNY_API_KEY"])
payment = client.payment_intents.create(
display_amount="29.00",
display_currency="USD",
reference="ORDER-48291",
success_url="https://shop.example/thanks",
)
return redirect(payment.checkout_url)Verify webhooks#
Always verify against the raw request body, before parsing JSON, and fulfil orders on payment.confirmed — never on the customer's redirect. See payment webhooks.
// Node
const event = await verifyWebhook(rawBody, req.header("muny-signature"), secret);
// PHP
$event = \Muny\Webhook::constructEvent($payload, $_SERVER['HTTP_MUNY_SIGNATURE'] ?? null, $secret);
# Python
event = muny.Webhook.construct_event(request.get_data(), request.headers.get("Muny-Signature"), secret)Send payouts#
The same clients send payouts from the balance your payments settle into.
// Node
await muny.payouts.create({ recipient: "7xKX…gAsU", amount: "500", reference: "affiliate-123" });
// PHP
$muny->payouts->create(['recipient' => '7xKX…gAsU', 'amount' => '500', 'reference' => 'affiliate-123']);
# Python
client.payouts.create(recipient="7xKX…gAsU", amount="500", reference="affiliate-123")Test and live
mk_test_… keys run against Muny's devnet environment, mk_live_… keys against mainnet. Every SDK takes a base_url / baseUrl option if you use a staging or self-hosted API.
Selling on WordPress?
The Muny for WooCommerce plugin is built on the PHP SDK — no code required.