Plugins and links / Medusa
Medusa
A payment provider for Medusa v2. Your storefront sends the customer to the Mintage Pay payment page, and Medusa completes the cart and captures the payment by itself when the payment is final.
Tested on 5 October 2026 with Medusa 2.21 on Node 22 and a region priced in euros, against the sandbox: connect, payment session, payment, cart completed into an order with a captured payment, and removal. The run used the Store API. The Next.js starter storefront and its return page have not been run yet, so test your storefront with a sandbox key first.
What you need
- Medusa v2 with
@medusajs/framework2.21 or later, on Node 20.19 or later. The package does not install on an older backend: upgrade Medusa first. The official starter may still pin an older version. - The backend repository and the right to deploy it, and an admin user who can edit regions.
- The storefront repository: it needs one redirect and a return page.
- Region currencies Mintage Pay supports: USD, EUR, GBP, CAD, AUD, CHF, JPY, MXN, BRL, INR, SGD, AED, PLN, SEK, NOK, DKK, NZD, ZAR, TRY, KRW, HKD, NGN, ARS, PHP, IDR, VND, PKR, EGP, BDT, KES, GHS, TZS, COP, CLP, PEN, UYU, PYG, BOB, DOP, GTQ, CRC, THB, MYR, TWD, LKR, NPR, KZT, UAH, ILS, SAR, QAR, CZK, HUF, RON, ISK, XAF or XOF. Your customers always pay in US dollar stablecoins: a price in another currency is converted when they check out, and the payment page shows both amounts.
- Your backend on https, reachable from the internet. Mintage Pay tells your backend about payments by calling
https://your-backend/hooks/payment/mintagepay_mintagepay. - A Mintage Pay account with at least one payout address set.
Install
Download medusa-payment-mintagepay.tgz and put it in your backend repository, for example in
vendor/.In the backend, run:
npm install ./vendor/medusa-payment-mintagepay.tgzAdd the provider to
medusa-config.ts:module.exports = defineConfig({ // ... modules: [ { resolve: "@medusajs/medusa/payment", options: { providers: [ { resolve: "medusa-payment-mintagepay", id: "mintagepay", options: { api_key: process.env.MINTAGEPAY_API_KEY, webhook_secret: process.env.MINTAGEPAY_WEBHOOK_SECRET, redirect_url: process.env.MINTAGEPAY_REDIRECT_URL, }, }, ], }, }, ], })In the Mintage Pay dashboard, open Developers > API keys and create a key. Copy it: it is shown only once. Set it on the backend as
MINTAGEPAY_API_KEY. SetMINTAGEPAY_REDIRECT_URLto your storefront's return page.
The key decides where the provider connects: a live key (mp_live_...) uses the live service and a test key
(mp_test_...) uses the sandbox.
Connect the webhook
Medusa has no settings screen for payment providers, so a small command does this step. Run it in the backend folder:
MINTAGEPAY_API_KEY=mp_test_... npx mintagepay-medusa-webhook connect \
--url https://your-backend/hooks/payment/mintagepay_mintagepay --out .env.mintagepayThe command checks the key, prints your business name and writes MINTAGEPAY_WEBHOOK_SECRET and the endpoint id to
.env.mintagepay. It never prints the secret. Copy the secret into your backend's secret store, keep the endpoint id
and delete the file. Then deploy the backend.
Run the command again for each key: the sandbox and the live service each have their own endpoint and secret.
Turn it on in your regions
In Medusa Admin, go to Settings > Regions > (your region) > Payment providers and add Mintage Pay
(pp_mintagepay_mintagepay). Do this for every region that should offer it.
Update the storefront
Start the payment session with the provider and send the customer to the payment page:
const { payment_collection } = await sdk.store.payment.initiatePaymentSession(cart, {
provider_id: "pp_mintagepay_mintagepay",
data: {
redirect_url: `${origin}/checkout/mintagepay-return?cart_id=${cart.id}`,
cancel_url: `${origin}/cart`,
},
})
const session = payment_collection.payment_sessions.find((s) => s.provider_id === "pp_mintagepay_mintagepay")
window.location.href = session.data.checkout_url as stringOn the return page, call sdk.store.cart.complete(cartId).
- An order comes back: done.
- "Not authorized" comes back: the payment is still confirming. Show "payment confirming" and try again a little later. Medusa also completes the cart by itself when Mintage Pay reports the payment, so the order is not lost if the customer closes the page.
The session data your storefront can read holds no secret: the invoice id, the payment page address, the status and the amounts.
Try it first with test money
- Create a free account at sandbox.mintagepay.com, set a payout address and create a key there.
- Set the sandbox key on the backend, run the connect command with it and deploy.
- Place an order in your storefront and choose Mintage Pay. You land on a payment page with a Test mode banner.
- Pay on the payment page with free test money. The page has a button to get some.
- Within a few minutes the cart is completed and the order has a captured payment, whether or not you returned to the storefront.
- When you are happy, set your live key, run the connect command again with it, set the live webhook secret and deploy.
What you will see
| What happened | In Medusa |
|---|---|
| Customer sent to pay | Payment session waiting for the customer |
| Payment seen, not final yet | Session pending, with a "payment detected" note |
| Paid in full | Payment captured, cart completed into an order |
| Paid, but the amount does not match the order | Not captured, with a note. Check it by hand |
| Part paid | Not captured, with a note saying how much is still owed |
| Payment window closed with nothing paid | Session in error. No order is created |
| Customer cancelled on the payment page | Session cancelled |
| Payment window closed with part paid | Not captured, with a note. Refund the customer or collect the rest |
A refund started in Medusa Admin is refused: Mintage Pay never holds your money, so it cannot send a refund for you. Send the refund from your own wallet and record it in the Mintage Pay dashboard.
If something is wrong
- The backend log says
rejected: no_secret:webhook_secretis not set in the provider options. - The backend log says
rejected: invalid_signature: the secret is wrong (a sandbox secret with a live key, or the other way round), or something in front of the backend changed the request body. - The cart is not completed after a payment: look at the webhook delivery in the Mintage Pay dashboard, then at the backend log. Medusa answers every webhook with 200, so the reason is in its log.
npm installis refused with ERESOLVE: your Medusa is older than 2.21. Upgrade the backend first.
Your key and webhook secret are never written to the log.
Remove the provider
Switch off the connection at Mintage Pay:
MINTAGEPAY_API_KEY=... npx mintagepay-medusa-webhook disable --id (endpoint id)Remove Mintage Pay from your regions and from
medusa-config.ts, then deploy.
Last updated . This page as Markdown. Something missing or wrong? Write to hello@mintagepay.com.