Home Development resources

Development resources

By Henrik Skogstrøm and 1 other
4 articles

Mion checkout integration

Integrating Mion as a payment method consists of the following steps: - Creating a payment session - Forwarding the user to Mion checkout - Verifying the payment status Creating a payment session Create a payment session by calling the endpoint Initiate a new payment session. Be sure to call this endpoint from your backend. This is an authenticated endpoint for which you must use an API key that you can create in the Mion web UI. Remember to set the Payments Read & Write permission for the API key. The usage of the API key is explained here. Notes: - Only "EUR" is currently supported as the currencyIso3 - The amount must be given in cents. For example, for 12 € set the amount to 1200. - Payments on the Bitcoin blockchain can take hours, so set a sufficiently long expiry - The retailPos parameter must be set to false for online payments. In case of point of sale payment, refer to the separate guide for them. It is highly suggested to save the payment session id (returned from the request) into your database. Alternatively, you can also use the (optional) reference to identify the payment session at Mion. Forwarding the user to Mion checkout After the payment session is successfully created, redirect the user to https://app.mion.group/checkout/<payment session id> Replace the <payment session id> with the payment session id that you got when the payment session was created. Verifying the payment status To verify if the user has completed the payment, call one of the endpoints: Get a payment session status, Retrieve a payment session by its reference, or Retrieve a payment session by its ID. It's also possible to initiate a webhook to get the status updates in real time with the endpoint: Initiate a webhook for payment session status updates If in the response of these calls, paidAt has a valid timestamp, the user has successfully paid the requested amount. In this case the status will be one of the following statuses that indicate a completed payment: "funding-received", "funding-collected", "exchanged", "funded" Verify the payment status when the user returns to the redirectUrl. At that point the payment should be completed. Payment status verification asynchronously (In addition to when user returns to your page) you should also either: - Create a background process that periodically checks the payment status until the payment session expires. - Get status updates from the "status update webhook". This is because the user might close the browser before the redirect or loses connection, in which case the redirect back to the redirectUrl never happens even though the payment is successful. Development notes - When testing such that both "merchant UI" and "checkout UI" is used, it's best to use different browsers or for example incognito mode for one of those. The login for both uses same mechanisms and it's not possible to be simultaneously loggend in as a "merchant user" and a customer.

Last updated on Sep 12, 2025

Point-of-Sale integration

Integrating Mion into a Point-of-Sale system is straightforward to do using our API. The process consists of three steps. Make sure you have created an API key with the correct permissions. You can find the guide to creating and using API keys here. Remember to give the API key the Payments Read & Write  and Retail Point-of-sale Payments Create permissions. 1. Create a new payment session Create a payment session by sending a POST request to the new payment session endpoint. This is where you specify the amount, currency, expiration, and internal reference. This endpoint requires authentication through an API key and should not be called in the frontend for security reasons. After getting a successful response from the API, get the paymentSessionId from the JSON object returned. You will need this in the following steps to request payment attempts and check the status of the payment. It is important to store the paymentSessionId, reference or both into your database, so that you can identify the payment session at Mion. The payment session ID is most convenient as this is the ID used by all Mion endpoints. Notes: - Unless otherwise approved, EUR (Euro) is the only accepted value provided to the currencyIso3 parameter. - amount must be given in cents. For example, for 12 € set the amount to 1200. This is done to prevent floating point errors. - Remember to set retailPos to true. Otherwise the payment session is for online payments and requires customer details. - Payments on the Bitcoin blockchain can take hours, which is why we recommend only allowing Bitcoin over Lightning for Point-of-Sale integration. If you want to enable regular bitcoin payments, we recommend that you set a sufficiently long expiry time. 2. New Payment Attempt With the payment session created, you can request a payment attempt by providing the paymentSessionId obtained above. Remember to set retailPos to true in the request. The payment attempt contains the Lightning invoice, bitcoin amount, expiry time, and so on. { "amountMsat": 25000000, "blockedByCompliance": false, "expiry": "2019-08-24T14:15:22Z", "lnInvoice": "string", "missingComplianceCustomerFields": [], "onChainAddress": "string", "paymentMethod": "lightning", "paymentSessionId": "75099bcf-22d5-43f9-8976-b7c5692eaa85", "suggestedFeeRate": 0 } From this response we want to get amountMsat , expiry and lnInvoice for lightning payments. The amountMsat field contains the amount of bitcoin to request from the customer denominated in "milli-satoshi". To get the bitcoin amount divide by amountMsat by 100 billion (amountMsat/(10^11)). In the response above we got 25000000 mSat, which is 0.00025 Bitcoin, or 25,000 sat. You can then display the Lightning invoice found in lnInvoice using a QR code, and the customer scans it using his or her favorite Lightning-enabled bitcoin wallet. The expiry time for the lightning payment attempts is very short (currently ~2min). After that the payment attempt can't be paid anymore. Create a new payment attempt always when the customer has not yet made a payment and the old payment attempt is close to expiry. Note: - What is a milli-satoshi? The bitcoin amount is provided as "milli-satoshi" or "mSat" for short. To explain this further, similar to how there are 100 cents in 1 Euro, there are 100 million sat in 1 bitcoin (BTC). For example, 0.1 bitcoin is 10 million sat. To further prevent possible problems of divisibility in micro transactions, we operate with "milli sat" where we further divide a Satoshi by 1000. - Some Bitcoin users prefer seeing the bitcoin value presented as Satoshi ("sat" for short) because €10 is ₿0,00019, which is harder to read than 19,000 SAT. To get sat from mSat, divide by 1000. 3. Check Payment status After the payment session is created, we need to check that the payment is completed. There are a few different approaches for doing this: - Polling the Get payment session status or Get payment session by reference endpoints - We suggest you check every second or half a second to see if the payment succeeded. - Using a webhook. The webhook will immediately send a callback to your server for each change in status of the payment session. - Note that there will be some callbacks even after the payment is done that notify about the internal processing of the payment at Mion. These are not relevant for the basic usage. - We will soon release documentation for using WebSocket in addition (Rest API used as fallback). The payment status response will look like this: "expiresAt": "2019-08-24T14:15:22Z", "feeStatus": "correct", "fundingAmountAvailable": 0, "fundingStatus": "well-funded", "paidAt": "2019-08-24T14:15:22Z", "paymentMethod": "lightning", "paymentSessionId": "75099bcf-22d5-43f9-8976-b7c5692eaa85", "refundSessionIds": [], "status": "funded" } When the paidAt time is set, the payment is completed. Done At this point your integration should be done. Please reach out to us on support@mion.group or to your account manager if you need help or there are errors in this guide.

Last updated on Sep 12, 2025