Accept a card payment

Collecting payments on your website consists of creating a payment object, collecting card information, and submitting the payment to MONEI for processing.


1. Create a Payment Server-side

Create a Payment on your server with an amount and currency. Always decide how much to charge on the server side, a trusted environment, as opposed to the client. This prevents malicious customers from being able to choose their own prices.

curl --request POST '' \
--header 'Authorization: pk_test_3c140607778e1217f56ccb8b50540e00' \
--header 'Content-Type: application/json' \
--data-raw '{
"amount": 110,
"currency": "EUR",
"orderId": "14379133960355",
"description": "Test Shop - #84370745531439",
"customer": {
"email": ""
"callbackUrl": "",
"completeUrl": ""

The following parameters are required:

  • amount positive integer - Amount intended to be collected by this payment. A positive integer representing how much to charge in the smallest currency unit (e.g., 100 cents to charge 1.00 USD)
  • currency string - Three-letter ISO currency code, in uppercase. Must be a supported currency.
  • orderId string - An order ID from your system. A unique identifier that can be used to reconcile the payment with your internal system.
  • completeUrl string - The URL the customer will be directed to after transaction completed (successful or failed).
  • callbackUrl string - The URL to which a payment result should be sent asynchronously.

Check all available request parameters.

Included in the returned Payment object is a payment id, which is used on the client side to securely complete the payment process instead of passing the entire Payment object.

2. Collect card details Client-side

Include monei.js on your checkout page by adding the script tag to the head of your HTML file.

<script src=""></script>

Add MONEI Card Input Component to your payment page. Create empty DOM nodes (containers) with unique IDs in your payment form.

<div class="card-field">
<div id="card-input">
<!-- A MONEI Card Input Component will be inserted here. -->
<!-- Used to display card errors. -->
<div id="card-error"></div>
<button type="submit" id="payment-button">
Submit payment

Initialize MONEI Card Input

var container = document.getElementById('card-input');
var errorText = document.getElementById('card-error');
// Create an instance of the Card Input using payment_id.
var cardInput = monei.CardInput({
paymentId: '{{payment_id}}',
onChange: function (event) {
// Handle real-time validation errors.
if (event.isTouched && event.error) {
errorText.innerText = event.error;
} else {
errorText.innerText = '';
// Render an instance of the Card Input into the `card_input` <div>.

The Card Input Component simplifies the form and minimizes the number of required fields by inserting a single, flexible input field that securely collects all necessary card and billing details.

Check MONEI JS Reference for more options.

3. Submitting the payment to MONEI Client-side

To complete the payment you need to submit a payment form with the method="post" and action="{{payment_id}}/confirm" (replace {{payment_id}} with your payment ID obtained in step 1)

The submitted form should include paymentToken generated with Card Input Component. You can also provide additional parameters like (use . as a separator for nested parameters). Check all available parameters.

// Handle form submission.
var paymentForm = document.getElementById('payment-form');
var paymentButton = document.getElementById('payment-button');
paymentForm.addEventListener('submit', function (event) {
paymentButton.disabled = true;
.then(function (result) {
if (result.error) {
// Inform the user if there was an error.
errorText.innerText = result.error;
} else {
// Send the token to MONEI.
paymentButton.disabled = false;
.catch(function (error) {
paymentButton.disabled = false;
// Submit the form with the token ID.
function moneiTokenHandler(token) {
// Insert the token ID into the form
var hiddenInput = document.createElement('input');
hiddenInput.setAttribute('type', 'hidden');
hiddenInput.setAttribute('name', 'paymentToken');
hiddenInput.setAttribute('value', token);
// Submit the form

After the form is submitted a customer goes through 3D secure verification process (is redirected to the page provided by the bank issued the card for confirmation of the transaction) if required.


As an alternative process you can submit generated paymentToken to your sever and then confirm payment on the server-side.

4. Customer is redirected back to your server.

A customer is redirected to the completeUrl with payment_id query parameter. Use get payment endpoint to get the payment status.

5. An asynchronous request is sent to your server.

MONEI will notify you about a payment status by sending an HTTP POST request to the callbackUrl. The request body will contain full payment object in JSON format.

This ensures that you get the payment status even when customer closed the browser window or lost internet connection.

The request also contains a MONEI-Signature header. Verify this signature to confirm that received request is sent from MONEI.

To acknowledge receipt of the request, your endpoint must return a 200 HTTP status code to MONEI. All other response codes, including 3xx codes, indicate to MONEI that you did not receive the event.

If MONEI does not receive a 200 HTTP status code, the notification attempt is repeated. After multiple failures to send the notification over multiple days, MONEI marks the request as failed and stops trying to send it to your endpoint.