---
title: "Recurring payments"
slug: "recurring-payments"
updated: 2026-01-27T11:14:58Z
published: 2026-01-27T11:14:58Z
canonical: "docs.monri.com/recurring-payments"
---

> ## Documentation Index
> Fetch the complete documentation index at: https://docs.monri.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Recurring payments

### What are recurring payments?

In the simplest terms, recurring payments (also known as subscription payments, automatic payments, or recurring billing) **take place when customers authorize a merchant to charge them repeatedly for goods or services on a prearranged schedule** (monthly, weekly, daily or annually).

### How recurring payments work?

With recurring payments you can charge a customer for access to a product.

Recurring payments are MIT (Merchant Initiated Transactions) payments - i.e customer did not initiate payment.

To process MIT you need:

- **an approval from acquiring bank(s) to use MIT (Merchant Initiated Transactions).** If acquiring bank does not support **MIT** transactions then you need an approval to process MIT as MOTO. In case you have any questions or need help feel free to contact us at [support@monri.com](mailto:support@monri.com)
- an approval from customer for future authorizations

## How to implement recurring payments?

For recurring payments you need to execute initial CIT (Customer Initiated Transaction).

- If you use our tokenization then you should set: save card for future payments to true
- If you are not using our tokenization i.e you are using your own tokenization solution then set `external_tokenization` to true. In this case you are required to store `cit_id` received in transaction authorization response

Once you saved card or received `cit_id` for initial CIT then you are ready to execute first merchant initiated transaction.

For MIT you should:

- set value of field `merchant_initiated_transaction` to `true`
- set value of field `pan_token` if you are using our tokenization service
- if you are using external tokenization then you need to set value of fields
  - pan
  - expiration_date

### Request/response

Try out example below:

```
const axios = require('axios');
const crypto = require('crypto');

// Set your merchant key if you want to try it our for your merchant account
const merchantKey = 'qwert1234'
// Set your authenticity token if you want to try it our for your merchant account
const authenticityToken = '7db11ea5d4a1af32421b564c79b946d1ead3daf0'
const orderNumber = `mit-${(Math.random() + 1).toString(36).substring(10)}`
const amount = 1000;
const currency = "EUR";

const digest = crypto.createHash('sha512')
    // Concat all values required for digest calculation
    .update([merchantKey, orderNumber, amount, currency].join(''))
    .digest('hex');

const data = {
    "transaction": {
        "transaction_type": "authorize",
        "amount": amount,
        "ip": "10.1.1.1",
        "order_info": "RunKit MIT",
        "ch_address": "Address",
        "ch_city": "City",
        "ch_country": "BIH",
        "ch_email": "mit-test@monri.com",
        "ch_full_name": "Monri",
        "ch_phone": "061 000 000",
        "ch_zip": "71000",
        "currency": currency,
        "digest": digest,
        "order_number": orderNumber,
        "authenticity_token": authenticityToken,
        "language": "en",
        "pan_token": "f167252fecfeff8f134001bf8e7a700c53e8653f631362dd84913e23260199bf",
        "merchant_initiated_transaction": true
    }
}

const bodyAsString = JSON.stringify(data);

const requestOptions = {
    headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json'
    }
}

try {
    const response = await axios.post('https://ipgtest.monri.com/v2/transaction', bodyAsString, requestOptions);
    const status = response.status
    if (response.data['errors']) {
        console.error(response.data['errors']);
    } else {
        const responseBody = response.data['transaction']
        console.log(`Received response, status=${status}`);
        Object.keys(responseBody).forEach(key => {
            console.log(`${key}: ${responseBody[key]}`)
        })
    }

} catch (error) {
    console.error(error)
}
```

### SCA Exemptions

Optionally and if applicable you can set value of SCA Exemption - depending on payment type. We support following exemptions:

- LVP (Low value payment)
- TRA (Transaction Risk Analysis)
- RP (Recurring Payment)
- MIT (Merchant-Initiated Transaction) - automatically applied if `merchant_initiated_transaction` is set to `true`
- UTT (Unattended transit terminal)
- ASO (Authentication Service Outage)

Exemptions are not supported by all acquiring banks.
