Integration Knowledge Base

Prev

# Monri Payments — Integration Knowledge Base

Sources: (1) the "Monri Integrations Hub" demo project (client React app + Node/Express test backend + assorted test scripts), cross-referenced against (2) Monri's own internal Documentation.docx (official WebPay Form, Lightbox, Components, Payment API, Customers API, Pay-by-Link, Card-on-File, mobile SDK, merchant-onboarding and web-shop-compliance documentation). Where the two sources agreed, that content is presented as settled fact. Where they disagreed, both versions are shown and flagged under §13 Known Discrepancies — do not silently trust one over the other without confirming with Monri support.

Note on credentials: all merchant keys, authenticity tokens and digests shown below are illustrative placeholders or values found in retired/sandbox test scripts and documentation examples. They must never be reused. Always use the specific merchant's own merchant_key / authenticity_token, and always calculate digests server-side.

Note on completeness: the source Documentation.docx file is itself incomplete — its own table of contents promises sections (Keks Pay / AirCash / Flik Pay / IPS / PayCek integration detail, PayPal, Valu Pay, and four separate "List of Response Codes" tables) that are not actually present in the file. Those gaps are called out inline rather than filled in with guesses.


1. Core Concepts

1.1 Environments

Environment Base URL
Test / Sandbox https://ipgtest.monri.com
Production https://ipg.monri.com

Always parametrize this base URL in code — every official guide repeats this warning, since it's the single most common integration mistake (hardcoding the test host).

1.2 Credentials & Compliance

Every merchant account has:

  • Merchant Key (merchant_key / "key") — looks like key-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx. A shared secret used only to calculate digests. Found under merchant account settings.
  • Authenticity Token (authenticity_token) — a long hex string that both identifies the merchant and is folded into the digest. Also found under merchant account settings.

These must only ever be used/calculated on the backend and must never be shipped to the browser or embedded in frontend JavaScript. client_secret (returned by /v2/payment/new) is the one value that is safe to expose to the frontend.

Monri Payments is PCI DSS Level 1 certified, and all card data submitted through Monri's hosted/embedded fields is transmitted over TLS and never touches the merchant's own servers when using Components, Lightbox, or Redirect. Merchants integrating via the Direct API (posting raw card data on their own page) take on significant additional PCI-DSS scope obligations — see §11 Web Shop Compliance.

1.3 Signature / Digest Schemes

Monri uses SHA-based digests to authenticate requests. There are several distinct schemes depending on which integration/API is used — mixing them up is the most common cause of "invalid digest" errors.

A) Simple SHA-512 digest (WebPay Form Redirect & Lightbox)

digest = SHA512(key + order_number + amount + currency)
  • amount is in minor units (e.g. 5000 = 50.00).
  • Included as a hidden digest field (Form Redirect) or data-digest attribute (Lightbox).
  • Confirmed identical in both the demo app and the official WebPay Form / Lightbox documentation, including a worked example: with key=2345klj, order_number=abcdef, amount=54321, currency=EUR → digest = f71b8c1560bd7511ba2f0307b3823c06dd39042cd77480543e3d7bf9f3eefa6debed252979ba8edc7a82d9f111d90f8e31c1c7ab5af39796b26e59a0b2d7cf98.
  • Because it has no timestamp, it is technically calculable client-side, but production integrations should still generate it server-side so the merchant key is never exposed in browser JS.

B) WP3-v2 Authorization header (older Components/Payment scheme — no path)

timestamp = current Unix time (seconds)
body      = JSON.stringify(requestPayload)
digest    = SHA512(merchant_key + timestamp + authenticity_token + body)
Authorization: WP3-v2 <authenticity_token> <timestamp> <digest>

Documented in the "Monri Components — New Payment Integration" guide for POST {base_url}/v2/payment/new, and this is also exactly what the demo project's server.js and PHP curl example implement. See §13 for a conflict: a newer, dedicated "Payment API" document describes the same endpoint using scheme C (WP3-v2.1, with the path folded in) instead.

C) WP3-v2.1 Authorization header (current, path-aware v2 API)

timestamp = current Unix time (seconds)
full_path = the path portion of the URL only, e.g. "/v2/terminal-entry/create-or-update"
body      = JSON.stringify(payload)   // for GET requests, body = "" (empty string)
digest    = SHA512(merchant_key + timestamp + authenticity_token + full_path + body)
Authorization: WP3-v2.1 <authenticity_token> <timestamp> <digest>

This is the scheme documented in the dedicated, versioned Payment API, Customers API, and Pay-by-Link API guides (all last updated 2021–2022) for every endpoint they cover, including /v2/payment/new itself. Officially documented worked example:

  • merchant_key = qwert1234, timestamp = 1593457122, authenticity_token = 7db11ea5d4a1af32421b564c79b946d1ead3daf0, fullpath = /v2/payment/new, body = {"example":"1"}
  • → digest = bd120476c656a8ec3ce5d6a150f17061d03a8e280b0fbba278a73a15066830562f73ce5536882c9222e265f1ff6c2df629173375b549cba5a9275b08686f32ea
  • Full header: Authorization: WP3-v2.1 7db11ea5d4a1af32421b564c79b946d1ead3daf0 1593457122 bd120476...f32ea

Response status conventions for every WP3-v2.1 endpoint:

status value HTTP code Meaning
created 200 Resource created
updated 200 Resource updated
approved 200 Request successful
invalid-request 4xx Something wrong with the request (validation message included)
error 500 Something went wrong server-side while processing
  • HTTP 401 → authentication problem (bad digest/header).
  • HTTP 400 → request processing failure (e.g. invalid amount).

D) Legacy XML Transaction Management API (SHA-1) — current for Capture/Refund/Void, not deprecated

This uses SHA-1, not SHA-512, and is a still-current, officially documented part of the WebPay Form integration for managing transactions after the fact (capture an authorization, refund, void). Digest is embedded directly in the request body, not in an Authorization header:

digest = SHA1(key + order_number + amount + currency)

See §5 (Transaction Management API) for the exact endpoints and XML shape. Correction from an earlier version of this document: this scheme is not legacy/deprecated — it is Monri's own currently-documented mechanism for Capture/Refund/Void on WebPay Form transactions, and it deliberately differs from the JSON v2 schemes above.

⚠️ One test script in this project's server/test functions/DinoMerlin/newDateScriptDino.js posts to /v2/transaction using SHA512(merchant_key + order_number + amount + currency) (scheme A) instead of SHA-1, with no Authorization header. This wasn't confirmed against the official docs (which don't document /v2/transaction as a public JSON endpoint at all) — treat it as unverified and confirm with Monri support before relying on it.

E) WP3-callback Authorization header (Callbacks & Webhooks — inbound requests from Monri to you)

digest = SHA512(merchant_key + request_body)
Authorization: WP3-callback <digest>

To validate an inbound callback/webhook:

  1. Check the Authorization header starts with WP3-callback.
  2. Extract the digest (the part after WP3-callback ).
  3. Recompute SHA512(your_merchant_key + raw_request_body).
  4. Compare the two digests (constant-time compare) — reject the request if they don't match.
import hashlib

def verify_request(merchant_key, request_body, received_digest):
    expected_digest = hashlib.sha512((merchant_key + request_body).encode()).hexdigest()
    return expected_digest == received_digest

Delivery guarantee (confirmed by official docs, not present in the demo app): Monri expects your callback endpoint to respond with HTTP 200 OK. If it doesn't receive a 200, it will keep retrying the same POST periodically until it does. Your handler should therefore be idempotent (safe to process the same transaction notification more than once).

F) Success-URL digest (outbound redirect from Monri back to the shop)

See §6.1 — uses SHA512(merchant_key + full_redirect_url_without_digest_param).


2. Transaction Types & Lifecycle

These apply across every integration method (Form Redirect, Lightbox, Components, Pay-by-Link):

Type Meaning Time window / notes
Authorize (authorize) Funds are reserved ("pre-authorization") on the buyer's account, not yet transferred. Preferred for e-commerce that ships later. Must be captured within 28 days (period can vary by acquiring bank) or it's auto-voided. Can be voided if the buyer cancels.
Purchase (purchase) Direct charge — funds move in the next settlement cycle (usually next business day), no separate capture step. Refundable within 180 days.
Capture Settles a previously approved Authorization, transferring funds. Can be for a partial amount (partial delivery). Must happen within 28 days of the authorization or it is auto-voided.
Refund Returns funds for an approved Purchase or Capture. Can be partial. Within 180 days of the original purchase/capture.
Void Cancels a previously approved Authorization, Capture, Purchase, or Refund before it settles. Within 28 days of the original message.

All four management operations (Capture/Refund/Void, plus the original Authorize/Purchase) can be executed either through the merchant dashboard UI or programmatically via API (see §5).

3-D Secure: Monri's Redirect Form, Lightbox, and Components all handle 3-D Secure authentication automatically — no additional programming is required from the merchant for 3DS itself (aside from setting a correct mobile viewport meta tag for Components, see §3.3).


3. Integration Methods

3.1 Redirect Form ("WebPay Form")

What it is: The customer is redirected (via an auto-submitting HTML <form> POST) to a Monri-hosted payment page at POST {base_url}/v2/form. After paying, Monri redirects the customer back to the shop's configured Success URL.

Flow:

  1. Customer selects products → shop computes amount (minor units), order_number (unique), order_info, currency.
  2. Shop collects billing details.
  3. Backend calculates the digest (scheme A, §1.3).
  4. Backend/frontend auto-submits a hidden HTML form POST to {base_url}/v2/form.
  5. If digest/authenticity token are valid, Monri's hosted form opens; buyer enters card details; the request goes to the issuing bank for authorization; the buyer is redirected to the shop's Success URL (see §6.1). If declined, the buyer stays on Monri's side and sees the form redisplayed with an error — there is no way to detect a declined attempt from the merchant side at that moment (only an approved one triggers the redirect/Callback).
  6. Optionally, Monri can send confirmation emails to merchant and/or buyer (see §3.1.3).

Field reference (buyer's profile):

Field Length Format Notes
ch_full_name 3–30 alphanumeric Buyer's full name
ch_address 3–100 alphanumeric Buyer's address
ch_city 3–30 alphanumeric Buyer's city
ch_zip 3–9 alphanumeric Buyer's ZIP
ch_country 2–3 alphanumeric Alpha-2, alpha-3, or 3-digit numeric ISO country code
ch_phone 3–30 alphanumeric Buyer's phone
ch_email 3–100 alphanumeric Buyer's email
customer_uuid 20 alphanumeric Optional — id of a previously created Customer (§4.2)

Field reference (order details):

Field Length Format Notes
order_info 3–100 alphanumeric Short order description
order_number 1–40 alphanumeric Unique per attempt
amount 3–11 integer Minor units, e.g. 10.24 USD → 1024
currency predefined alpha Officially documented list: USD, EUR, BAM, HRK. Newer test/integration code in this project also uses RSD, MKD, ALL (Serbia/North Macedonia/Albania) — the docx is dated and doesn't reflect Monri's regional expansion. Note also that HRK is obsolete since Croatia adopted the euro in 2023; treat it as legacy.

Field reference (processing data):

Field Length Format Notes
language predefined alpha en, es, ba, hr
transaction_type predefined alpha authorize, purchase, capture, refund, void
authenticity_token 40 alphanumeric From merchant settings
digest (documented as 40, but see note) alphanumeric SHA-512 hex of key+order_number+amount+currency. Note: the official docs list this field's length as "40", but a SHA-512 hex digest is actually 128 characters — this looks like a copy/paste error in Monri's own tables (possibly confused with authenticity_token's length). Don't validate digest length against "40" in your own code.
number_of_installments 1–2 integer Range 2–12
moto boolean — Mail Order/Telephone Order flag; missing = false

Optional/advanced fields:

Field Purpose
tokenize_pan_offered (boolean) If Secure Vault is enabled, shows the buyer a "save card" checkbox; on success returns pan_token.
tokenize_pan (boolean) Tokenizes the card silently on success, without prompting the buyer. Requires prior user consent (T&Cs) obtained elsewhere.
tokenize_brands (comma-separated) Restrict tokenization to specific brands. Supported: visa, master, maestro, diners, amex, jcb, discover.
supported_payment_methods Comma-separated payment methods/tokens. If a valid saved-card token is supplied, only CVV is asked for (other fields pre-filled); multiple tokens can be sent, letting the buyer choose. Replaces the deprecated whitelisted_pan_tokens (just rename the key).
supported_cc_issuers (comma-separated) Restrict payment to specific card issuers, e.g. supported_cc_issuers=zaba-hr,ucbm-ba,rba-hr. Transaction declines if the entered card's issuer isn't in the list. Contact support@monri.com for the full issuer list.
rules (comma-separated, BETA) Apply custom merchant-defined rules, e.g. rules=rule-id-1,rule-id-2. Declines if a rule isn't satisfied. Contact support@monri.com to set up.
force_installments (true/false) Forces the buyer to choose an installment plan (no one-time payment option). Only works if installments are already enabled on the merchant profile — otherwise it errors.
custom_attributes (JSON string) Currently supports two keys: installments_config (per-brand min/max installment rules) and fields_config (mark specific fields e.g. ch_email/ch_full_name as read-only when pre-filled). See example JSON below.
custom_params (JSON string) Arbitrary merchant metadata, echoed back on the Success URL redirect and in Callback/Webhook payloads.
success_url_override / cancel_url_override / callback_url_override Per-request HTTPS URLs overriding the merchant-profile defaults for that single transaction.

custom_attributes example:

{
  "installments_config": {
    "rules": [
      { "brand": "visa", "min_installments": 2, "max_installments": 12 },
      { "brand": "master", "min_installments": 12, "max_installments": 24 }
    ]
  },
  "fields_config": {
    "fields": [
      { "name": "ch_email", "readonly": true },
      { "name": "ch_full_name", "readonly": true }
    ]
  }
}

Test card: 4341792000000044, any CVV, any future expiry date.

3.1.3 Email notifications. Monri can send confirmation emails to the merchant and/or buyer on successful purchase (configured, with custom templates, under the merchant account). Templates can interpolate: FULL_NAME, ADDRESS, CITY, ZIP, COUNTRY, PHONE, EMAIL, CARD_ISSUER, AMOUNT, ORDER_NUMBER, ORDER_INFO, CC_TYPE, DATE, SUCCESS_URL, DOMAIN. SUCCESS_URL in the email carries the same value/parameters as the actual Success URL redirect, so it should expire or be session-protected the same way.

3.2 Lightbox (iframe modal)

Functionally and field-for-field identical to Redirect Form (same digest formula, same buyer/order/processing field tables, same tokenize_pan_offered/tokenize_pan/tokenize_brands/custom_attributes options — replacing data-whitelisted-pan-tokens with data-supported-payment-methods is the migration path). It differs only in presentation:

  • Required script: https://ipgtest.monri.com/dist/lightbox.js (swap host for production), loaded inside a <script class="lightbox-button" data-*="..."> tag placed inside a <form> whose action attribute points at your own server-side endpoint (not directly back to Monri) — the Lightbox script auto-submits your form there, appending a transaction_response field (URL-encoded JSON of the transaction) once the payment finishes.
  • Every data-* attribute name is the dasherized version of the matching form-field name (e.g. ch_full_name → data-ch-full-name, order_number → data-order-number).
  • After processing, parse transaction_response from the form POST (server-side) or, per the demo app's SPA pattern, from window.location.search if you're redirected with it as a query param:
const transactionResponse = new URLSearchParams(window.location.search).get("transaction_response");
const response = JSON.parse(decodeURIComponent(transactionResponse));
// response.status === "approved" | other
  • Cleanup note (SPA-specific, from the demo app, not the official docs): when navigating away from a Lightbox page in a single-page app, explicitly remove Monri's injected DOM nodes/scripts (.monri-lightbox, .monri-lightbox-overlay, .monri-loader, .monri-iframe-container, .monri-frame-container, iframe[src*="monri.com"], script[src*="monri.com"], .lightbox-form, .lightbox-button) and reset document.body/document.documentElement inline styles (overflow, position, height, width, pointer-events) plus the window.Monri global — otherwise the modal/overlay can leak into other routes.
  • Same XML Capture/Refund/Void management API as Redirect Form (§5) and same Callback mechanism.

3.3 Components (embedded fields — "on-site" integration)

What it is: Monri's JS SDK (Monri.js) renders PCI-compliant payment UI elements directly inside the merchant's own page — no redirect, no iframe modal. Requires HTTPS on the page hosting Components (to avoid mixed-content warnings and MITM risk).

Backend step — create a payment, get a client_secret:

  1. POST {base_url}/v2/payment/new, signed per §1.3 (see §13 for the WP3-v2 vs WP3-v2.1 conflict on this endpoint), with a JSON body:
Field Length Type Required Notes
amount 1–11 Integer ✅ Minor units
order_number 2–40 String ✅ Unique order id
currency 3 String ✅ e.g. BAM, HRK, EUR, USD, CHF (docs say "etc" — not an exhaustive list)
transaction_type enum String ✅ authorize or purchase
order_info 3–100 String ✅ Short description
scenario enum String optional charge (default behavior) or add_payment_method
supported_payment_methods array Array<String> optional pan-tokens and/or "card"
customer_uuid 20 String optional Attach to a Customers API profile (§4.2)
success_url_override / cancel_url_override / callback_url_override URL String optional Per-request overrides

⚠️ scenario: "add_payment_method" warning (verbatim from official docs): this scenario will automatically execute a refund or void (depending on transaction type) after saving the card — only use it purely to save a card for later, never to actually collect money at the same time.

  1. Response:
Field Type Notes
status String approved | declined | invalid-request | error
id String Unique payment id — save it for debugging/tracking
client_secret String Send to the frontend; used to confirm payment via Components
  1. Backend returns only the client_secret to the frontend — never the merchant key/authenticity token.

Frontend step — mount the payment element:

<script src="https://ipgtest.monri.com/dist/components.js"></script>
// Officially documented constructor call — first argument is the authenticity_token
var monri = Monri('<authenticity-token>', { locale: 'hr' /* optional */ });
var components = monri.components({ clientSecret: '<client-secret>' });

var card = components.create('card', {
  style: { base: { fontSize: '16px', color: '#663399' } },
  tokenizePan: true,               // tokenize on success
  // tokenizePanOffered: true,     // OR offer a "save card" checkbox (ignored if tokenizePan is true)
  // showInstallmentsSelection: true
});
card.mount('card-element');

card.onChange(function (event) {
  // event.error is set (with .message) if input is currently invalid
});

document.getElementById('payment-form').addEventListener('submit', function (event) {
  event.preventDefault();
  monri.confirmPayment(card, {
    address, fullName, city, zip, phone, country, email, orderInfo
  }).then(function (result) {
    if (result.error) { /* show result.error.message */ }
    else { /* handle result.result — see PaymentResult shape below */ }
  });
});

⚠️ Discrepancy vs. this demo project's actual code (see §13): the official docs pass the authenticity_token as the first argument to Monri(...). The demo app instead calls window.Monri(client_secret, { locale }) — passing the client secret as the first argument. Confirm which is actually required with Monri support/your SDK version before assuming either is correct.

Component types: card, saved_card, cvv (a customer with a default saved card can be switched via setActivePaymentMethod), plus wallet/local-scheme components: apple-pay, google-pay, keks-pay, air-cash, flik-pay, ips-rs, pay-cek (crypto — see §3.4). Wallet components take trx_token (= the client_secret), environment ('test'/'prod'), and a transaction object with billing fields, and emit paymentSuccess/paymentError events instead of using confirmPayment directly (except PayCek, see §3.4).

Locales supported: hr (Croatia), en (USA, default), sr (Serbia), bs (Bosnia and Herzegovina), ba_hr (Croatian in BiH), sl (Slovenia), me (Montenegro), mk (North Macedonia), de (Germany). Only affects UI language, not number/date formatting.

Custom fonts: an optional fonts array can be passed in the same options object as locale, each entry { family, src, display?, weight?, style?, stretch?, 'unicode-range'? } (family/src required).

Styling (style option on components.create): a style object has a base sub-object (applied to every element) plus optional invalid, complete, empty overrides, and separately-styleable sub-elements: label, input, rememberCardLabel, selectPaymentMethod (each themselves accepting base/invalid/complete/empty). Supported CSS-like keys: fontSize, color, fontFamily, fontSmoothing, fontVariant, fontWeight, letterSpacing, textDecoration, textShadow, textTransform, border, borderTop, borderRight, borderBottom, borderLeft, borderRadius, padding, margin, lineHeight, textIndent, position, top, bottom, left, right, width, height, backgroundColor, boxShadow.

Card component options:

Option Type Default Notes
tokenizePan boolean false Silently tokenizes PAN on approval.
tokenizePanOffered boolean false Shows a "save card for future payments" checkbox. Ignored if tokenizePan is true.
showInstallmentsSelection boolean false Shows an installments dropdown — only works if installments are enabled for the merchant (contact support otherwise).

Listening to input changes: card.addChangeListener('card_number' | 'expiry_date' | 'cvv' | 'installments', callback). Each callback receives { data, message, valid, element }, e.g. for card_number: data: { bin, brand }; for expiry_date: data: { month, year }; for installments: data: { selectedInstallment }.

confirmPayment(component, transactionParams) return shape:

type Result<PaymentResult> = { result: PaymentResult | null, error: { message: string } | null }
type PaymentResult = {
  status: string,              // "approved" or "declined"
  currency: string,
  amount: number,               // minor units
  order_number: string,
  pan_token: string | null,
  created_at: string,
  transaction_type: string,     // "authorize" or "purchase"
  payment_method: { type: string, data: { brand, issuer, masked, expiration_date, token } } | null,
  errors: string[] | null
}

3-D Secure authentication is handled automatically by the Components library.

Mobile viewport requirement: for 3DS to render correctly on mobile inside Components, the page must include:

<meta name="viewport" content="width=device-width, initial-scale=1"/>

Test card (generic Components demo): 4111 1111 1111 1111, any future expiry, any CVV.

3.4 Payment Methods via Components (wallets & alternative methods)

All of the following are created via components.create(<type>, options) after the same backend /v2/payment/new + client_secret flow as the Card component (§3.3), and require the same <script src=".../dist/components.js"></script> include.

Officially documented method list (per Monri's own "Payment Methods via Components" index): Google Pay, Apple Pay, Keks Pay, AirCash, Flik Pay, IPS (Serbia), PayCek, PayPal, Valu Pay. Of these, only Google Pay, Apple Pay, and PayCek have actual documented detail in the source file this knowledge base was built from — Keks Pay, AirCash, Flik Pay, IPS, PayPal, and Valu Pay are listed in the table of contents but their content sections were never written into that document. The Keks Pay/AirCash/Flik Pay/IPS parameter shapes shown below are therefore reconstructed from the demo app's working code, not Monri's own docs — treat them as reasonably reliable (they're live demo code) but confirm exact option names with Monri support if precision matters. PayPal and Valu Pay integration details are not available in either source — don't invent parameters for them; refer the merchant to support@monri.com.

Google Pay:

const googlePay = components.create("google-pay", {
  trx_token: "<trx_token>",           // the client_secret
  buttonStyle: 'black',               // or 'white'
  buttonType: 'buy',                  // 'checkout', 'donate', etc. — see Google's button docs
  buttonLocale: 'en',
  environment: isTestSystem ? "test" : "prod",
  transaction: {
    ch_full_name, address, city, zip, phone, country, email,
    orderInfo, language
  }
});
googlePay.mount("google-pay-element");
googlePay.on('paymentSuccess', (result) => { /* ... */ });
googlePay.on('paymentError', (error) => { /* ... */ });

Notes: the button only renders if the browser/device supports Google Pay; trx_token is single-use; the transaction object is required or the component may fail to initialize; Google Pay doesn't render custom input fields, it just inherits language/order-summary info; styling options are limited compared to the Card component.

Apple Pay: identical shape, components.create("apple-pay", {...}), with locale (e.g. 'en-US', per Apple's ApplePayButtonLocale), buttonStyle ('black' / 'white' / 'white-outline'), buttonType (per Apple's ApplePayButtonType) instead of Google's button options. Same caveats (device support required, single-use trx_token, required transaction object, limited styling).

Keks Pay / AirCash / Flik Pay (reconstructed from demo code, not confirmed against official docs):

const paymentMethod = components.create(compType, {   // 'keks-pay' | 'air-cash' | 'flik-pay'
  trx_token: clientSecret,
  environment: 'test' | 'prod',
  transaction: { ch_full_name, address, city, zip, phone, country, email, orderInfo, language }
});
paymentMethod.mount(elementId);
paymentMethod.on('paymentSuccess', ...);
paymentMethod.on('paymentError', ...);

IPS-RS (Serbia instant payments): same shape, but the transaction object uses fname / lname instead of ch_full_name:

components.create('ips-rs', {
  trx_token: clientSecret,
  environment: 'test' | 'prod',
  transaction: { fname, lname, address, city, zip, phone, country, email, orderInfo, language }
});

PayCek (crypto currency payments):

var options = { payCekOptions: { size: "small" } };
var payCek = components.create("pay-cek", options)
  .onStartPayment(() => {
    // called when the user clicks the PayCek button — collect any last-minute info here
    monri.confirmPayment(payCek, transactionParams)   // same transactionParams shape as Card (§3.3)
      .then(e => {
        if (e.error) { /* show e.error.message */ }
        else { /* handle e.result — same PaymentResult shape as Card */ }
      });
  });
payCek.mount("pay-cek-element");

Unlike the wallet components (which use paymentSuccess/paymentError events), PayCek uses the same monri.confirmPayment(component, transactionParams) Promise-based flow as the Card component. Clicking the PayCek button opens a popup letting the buyer pick a supported cryptocurrency, then shows a QR code with a wallet address; the approved/declined result then resolves the confirmPayment promise.

3.5 Pay-by-Link

What it is: the backend generates a secure, Monri-hosted payment URL (no card data ever touches the merchant's own site) that can be sent to a customer via email/chat/SMS — ideal for manual orders, invoicing, phone/remote sales, and bulk link generation. The digest must be generated server-side.

Idempotency: every Pay-by-Link resource ("terminal entry") is keyed by order_number. POSTing the same order_number again updates the existing entry rather than creating a new one.

Create or Update: POST {base_url}/v2/terminal-entry/create-or-update, signed with WP3-v2.1 (§1.3-C, digest includes the path /v2/terminal-entry/create-or-update).

Request body fields:

Field Length Type Required Updatable Notes
amount 1–11 Integer ✅ ✅ Minor units
currency 3 String ✅ ✅ BAM, HRK, EUR, USD, CHF, etc.
order_number 2–40 String ✅ — (idempotency key)
transaction_type enum String ✅ ✅ authorize or purchase
order_info 3–100 String ✅ ✅
number_of_installments 1–2 Integer optional ✅ Range 2–12
supported_payment_methods array Array<String> optional ✅ pan-token(s) and/or "card"
ch_address, ch_city, ch_zip, ch_country, ch_phone, ch_email — String optional ✅ Same length/format rules as §3.1
language predefined String optional ✅ en, es, ba, hr
tokenize_pan_offered / tokenize_pan boolean boolean optional ✅ Same semantics as §3.1
expires_at ISO 8601 String optional ✅ e.g. "2021-09-26T07:58:30.996+0200"
success_url_override / cancel_url_override / callback_url_override URL String optional ✅

Response fields include everything above plus: id, status, payment_url (send this to the customer), terminal_entry_status (pending = not yet charged, approved = an approved authorize/purchase exists for this order_number, expired = entry no longer active), active (boolean), moto, force_cc_type, created_at/updated_at (ISO UTC).

Show (check status): GET {base_url}/v2/terminal-entry/<order_number>/show, same WP3-v2.1 scheme with empty body. Response shape is identical to Create-or-Update's, except status is always approved if the request itself was valid (it describes "the request succeeded", not "the payment succeeded" — check terminal_entry_status for the actual payment state).

Deactivate / Activate: same POST /v2/terminal-entry/create-or-update endpoint — provide expires_at (in the past, to deactivate) to change the active flag. Response is the same shape; check active.

3.6 Secure Vault / Tokenization / Card on File (COF)

Card tokenization is a paid add-on — merchants must have it enabled by Monri support before any of this works (support@monri.com).

Saving a card: request tokenization on any transaction (Redirect Form, Lightbox, or Components) via tokenize_pan: true (silent) or tokenize_pan_offered: true (buyer checkbox), optionally scoped to specific brands with tokenize_brands (visa/master/maestro/diners/amex/jcb/discover — used together with tokenize_pan_offered). On an approved, tokenized transaction, the response contains a pan_token — store it server-side.

Charging a saved card later ("Card on File" / MIT): post directly to the legacy /v2/transaction endpoint (JSON) with:

{
  "transaction": {
    "transaction_type": "authorize",
    "amount": 100,
    "ip": "10.1.10.111",
    "order_info": "Monri components trx",
    "ch_address": "Address", "ch_city": "City", "ch_country": "BIH",
    "ch_email": "test@test.com", "ch_full_name": "Test", "ch_phone": "061 000 000", "ch_zip": "71000",
    "currency": "BAM",
    "digest": "<SHA512(key + order_number + amount + currency)>",
    "order_number": "1568236677437",
    "authenticity_token": "<authenticity_token>",
    "language": "en",
    "pan_token": "<stored pan_token>",
    "moto": true
  }
}

Key points: supply pan_token instead of raw card number/expiry/CVV, and set moto: true since the cardholder isn't present. Response is 201 Created with a transaction object; only trust the status field (approved / declined / invalid) to determine the outcome — don't infer success from HTTP status or the presence of other fields.

Merchant-Initiated Transactions (recurring/unscheduled, from the demo app's working test code — not found verbatim in the official docs, but consistent with the COF pattern above):

{ "pan_token": "...", "future_usage": "unscheduled_recurring", "merchant_initiated_transaction": true, "cit_id": "<original customer-initiated transaction id>", "moto": true }

Fetching a customer's stored payment methods: GET {base_url}/v2/customers/{customer_uuid}/payment-methods?limit=&offset= (WP3-v2.1, empty body). Response:

{
  "status": "approved",
  "data": [
    {
      "id": "<token>", "masked_pan": "405840******0005", "expiration_date": "2025-12-31",
      "keep_until": "2024-12-31T23:00:00Z", "customer_uuid": "...", "token": "<same as id>",
      "expired": false, "created_at": "...", "updated_at": "..."
    }
  ]
}

Default page size is 50; use offset to page (results sorted created_at DESC).


4. Payment API & Customers API (dedicated v2 JSON APIs)

Both documented as standalone, versioned APIs (latest updates 21.02.2022 / 22.03.2022) using the WP3-v2.1 scheme (§1.3-C) throughout — headers Content-Type: application/json, Accept: application/json, Authorization: <computed header>.

4.1 Payment API

Create — POST /v2/payment/new. Body fields: amount, order_number, currency, transaction_type (authorize/purchase), order_info — all required; scenario (charge/add_payment_method), supported_payment_methods, customer_uuid, success_url_override/cancel_url_override/callback_url_override — all optional. See §3.3 for the add_payment_method warning. Response: { status, client_secret, id, message? }.

Update — POST /v2/payment/<payment-id>/update. Only amount can be updated. Response: { status, client_secret, amount, currency, id, message? }.

4.2 Customers API

A customer profile lets a merchant attach saved payment methods and metadata to a stable identity, referenced via customer_uuid on Payment/Pay-by-Link/Components calls.

Action Method & Path Notes
Create a customer POST /v2/customers Fields: merchant_customer_id, description, email, name, phone, metadata (key/value dict), zip_code, city, address, country (ISO 3166-1 alpha-2) — all optional. Response includes a generated uuid.
Retrieve a customer GET /v2/customers/:uuid
Retrieve via merchant's own id GET /v2/merchants/customers/:merchant_customer_id Look a customer up by your id instead of Monri's uuid.
Update a customer POST /v2/customers/:uuid Only supplied fields change; setting a metadata key to null unsets it.
Delete a customer DELETE /v2/customers/:uuid Response: { status, id, deleted: true }.
List all customers GET /v2/customers?limit=&offset= Default limit 50, sorted created_at DESC.
List a customer's payment methods GET /v2/customers/:uuid/payment-methods?limit=&offset= Same shape as §3.6's fetch-payment-methods call.

Example customer object:

{
  "uuid": "4b281da4-d145-4233-b957-2018cf9aa0fb",
  "merchant_customer_id": "customer-id-1234",
  "description": "Customer", "email": "email@email.com", "name": "Test", "phone": null,
  "status": "approved", "deleted": false, "city": null, "country": "BA", "zip_code": "71000",
  "address": null, "metadata": { "key": "value" },
  "created_at": "2019-02-12T11:22:33Z", "updated_at": "2019-02-12T11:22:33Z", "deleted_at": null
}

5. Transaction Management API (Capture / Refund / Void — WebPay Form & Lightbox)

REST-ish XML API, all requests POST-ed over HTTPS with Content-Type: application/xml and Accept: application/xml. Digest uses SHA-1, embedded in the XML body (see §1.3-D) — not an Authorization header. XML node names are the dasherized version of the field name (order_number → order-number).

Operation Endpoint Notes
Capture POST {base_url}/transactions/:order_number/capture.xml Settles a prior authorization. :order_number from the original authorization. Can be a partial amount.
Refund POST {base_url}/transactions/:order_number/refund.xml :order_number from the original purchase or capture.
Void POST {base_url}/transactions/:order_number/void.xml :order_number from the original authorize/capture/purchase/refund.

Example capture request body:

<?xml version="1.0" encoding="UTF-8"?>
<transaction>
  <amount>54321</amount>
  <currency>EUR</currency>
  <digest>e64d4cd99367f0254ed5296d38fad6ce87d3acab</digest>
  <authenticity-token>7db11ea5d4a1af32421b564c79b946d1ead3daf0</authenticity-token>
  <order-number>11qqaazz</order-number>
</transaction>

digest = SHA1(key + order_number + amount + currency).

Responses:

  • Success → 201 Created, Location header pointing at the new transaction resource, XML body with id, acquirer, order-number, amount, response-code, approval-code, response-message, reference-number, systan, cc-type, status (approved/decline/invalid), transaction-type, created-at. Only status should be trusted to determine success — keep the whole raw response for troubleshooting.
  • Invalid request → 406 Not Acceptable, XML <errors><error>...</error></errors> body describing what's wrong (e.g. "Digest is invalid").

Checking payment status (newer v2 JSON API): GET {base_url}/v2/payment/{payment_id}/status, WP3-v2.1 scheme, empty body — payment_id is the id returned by /v2/payment/new.

Legacy order lookup (from demo test code, not in the docx): POST {base_url}/orders/show with XML {order_number, authenticity_token, digest}, digest = SHA1(key + order_number).


6. Post-Payment Notifications

Three complementary mechanisms. Treat Callback/Webhook as the source of truth — the browser can be closed before a Success-URL redirect completes.

6.1 Success URL (redirect after Form Redirect/Lightbox payments)

Configured per-merchant in account settings; only fires if "redirect to success URL" is enabled and only after an approved transaction. Monri issues a GET redirect with query parameters appended:

https://yourdomain.com/payment-success?acquirer=integration_acq&amount=100&approval_code=629762
  &authentication=Y&cc_type=visa&ch_full_name=John+Doe&currency=USD
  &custom_params=%7Ba%3Ab%2C+c%3Ad%7D&enrollment=Y&language=en
  &masked_pan=434179-xxx-xxx-0044&number_of_installments=&order_number=02beded6e6106a0
  &response_code=0000&digest=<sha512 digest>

Parameters: acquirer, amount, approval_code, authentication, cc_type, ch_full_name, currency, custom_params, enrollment, language, masked_pan, number_of_installments, order_number, response_code, digest. response_code === "0000" = success.

Verifying the digest:

  1. Strip the digest query parameter (and trailing ?/&) from the full incoming URL.
  2. Prepend the merchant key with no separator: key + url_without_digest.
  3. SHA512 that string.
  4. Compare to the digest on the URL — reject on mismatch (possible tampering).

Officially documented worked example — with key = 2345klj and the URL above (minus digest), the resulting digest is b96025517326db3b952ba783281701bf48cd1fffa4fb61f0c05847e6498919f99630fbfd575ce9ea9f361ec8bb9bf9e0d349dee0c5474a5141ce91b3e1f95ef3. (This matches the demo app's own docs verbatim, confirming the formula.)

The Success URL itself should expire after a sensible time, or be session-protected — it's a bare GET link and could otherwise be replayed. When debugging mismatches, log every step (raw URL → URL without digest → concatenated string → computed digest); a stray character breaks the whole comparison. An online SHA-512 tool (e.g. https://emn178.github.io/online-tools/sha512.html) can help sanity-check by hand — Monri's own docs link to an internal "Calculate Digest" tool for the same purpose.

6.2 Callback (server-to-server POST for successful transactions)

  • Set the Callback URL under the merchant profile if you want a POST for every approved transaction (flat JSON body — see the example in §1.3-E's referenced payload, identical structure across the WebPay Form, Lightbox, and Components docs).
  • Must respond HTTP 200 OK or Monri retries periodically until it gets one — design the handler to be idempotent.
  • Auth: Authorization: WP3-callback <digest> where digest = SHA512(merchant_key + raw_request_body) (§1.3-E).

6.3 Webhooks (server-to-server POST for a broader range of events)

  • Unlike Callback (approved transactions only), Webhooks cover many lifecycle events and must be configured on Monri's side (contact support).
  • Supported events: transaction:refund:approved/declined, transaction:void:approved/declined, transaction:capture:approved/declined, transaction:management:approved/declined, transaction:purchase:approved/declined, transaction:authorize:approved/declined, transaction:approved/declined, payment-method:tokenized.
  • Payload envelope differs from Callback: { "event": "transaction:declined", "payload": { ...same fields as Callback... } }.
  • Same WP3-callback auth/validation as §6.2.

7. Mobile SDKs

7.1 Android

  • Java/Kotlin library; PCI compliance is achieved by sending card data directly from the device to Monri's servers (never through the merchant's own backend), returning a token the app then sends to the merchant's server.
  • Supports Android 4.4 (API level 19) and above.
  • Install via Gradle: implementation 'com.monri:monri-android:3.2.3'.
  • Proguard rule required:
    -keep public class com.monri.** { public protected private *; }
    -keep public enum com.monri.** { *; }
    
  • Two integration paths: Payment API Integration (create payment → collect payment details → confirmPayment → handle result in-app and/or on your backend) or Tokens API Integration (collect payment details → create a token request → create a token → use the token for server-side transaction authorization).
  • Also documented: Google Pay Integration (3 possible implementation approaches) and ScanDoc AI Integration (extracts card data from a photographed card).

7.2 iOS

  • Install via CocoaPods: pod 'Monri', '~> 1.0' (then pod install, and use the generated .xcworkspace, not .xcodeproj).
  • Same two integration paths as Android: Payment API Integration (charge) and Tokens API Integration (tokenize for later server-side use).

7.3 Cross-platform

Flutter, React Native, and (per the onboarding guide) Ionic are supported as wrapper targets around the native Android/iOS SDKs.


8. Plugins & eCommerce Modules

Platform Link / notes
WooCommerce (WordPress) Official "Monri Payments Gateway for WooCommerce" plugin — install from the WordPress Dashboard plugin search
PrestaShop https://github.com/MonriPayments/prestashop/releases (download monri.zip)
Magento https://commercemarketplace.adobe.com/monripayments-magento2.html
Shopify https://apps.shopify.com/monri
Flutter https://github.com/MonriPayments/flutter-monri-android-ios
React Native https://github.com/MonriPayments/react-native-monri-android-ios
iOS https://github.com/MonriPayments/monri-ios
Android https://github.com/MonriPayments/monri-android
Full source of the various web integration types (demo) https://github.com/harunk-monri/monri-integrations
Live "behind the scenes" services demo https://ipgtest.monri.com/services-demo/home
Official public API documentation https://ipg.monri.com/en/documentation

WooCommerce setup (high level): obtain Merchant Key + Authenticity Token → install the plugin → enter credentials in WooCommerce → Settings → Payments → test in test mode → disable test mode and go live.


9. Merchant Onboarding — From Initial Contact to Production

This is the process a new merchant goes through (distinct from the technical integration steps above) — useful context when a client asks "how long until we can go live" or "what do we need to sign."

"From Initial Contact to Successful Production" — 7 steps:

  1. Submit Access Form — merchant receives an electronic access form; completes, signs, and stamps the required bank forms (returned as Word/PDF); Monri Sales forwards them onward.
  2. Test Environment Setup — a test account is created; technical documentation is sent to the contact provided on the access form.
  3. Integrate with WebPay & Brand Your Website — merchant integrates and brands their site per the compliance instructions (§11), then notifies Monri Support that integration is complete.
  4. Website Inspection — Monri Support inspects the site; the acquiring bank may also inspect it independently.
  5. Bank Contract Signing & Parameter Issuance — the bank(s) invite the merchant to sign a contract and issue TID/MID parameters.
  6. 3-D Secure Authentication Registration — the account is registered with global card schemes for 3DS; handled mostly by the bank, except for UCBM/BiH where Monri itself handles it.
  7. Monri Contract Signing — a Monri contract is signed (terms vary by region).

→ Once all of the above are complete, the production environment is activated.

"Getting Integration Started With Monri Online" — practical checklist:

  • Requirements: a test-environment account (via Monri Sales/Support) and access to the integration documentation. New merchants without info yet should contact ecomm-prodaja@monri.com.
  • Step 1: sign in to the Monri Online test environment.
  • Step 2: initial setup — configure SuccessURL, CancelURL (if applicable), CallbackURL.
  • Step 3: choose transaction & integration type (agree with your Monri key account manager if unsure):
    • By use case: simple Pay-by-Link / Pay-by-Link API, a classic web shop (custom integration or plugin), a mobile app, or "other" (platform/cross-platform integrations).
    • Transaction types: Authorization, Purchase, Capture, Refund, Void (definitions per §2).
    • Technical integrations: Redirect, Components, Mobile SDK (Android/iOS, or Flutter/React Native/Ionic wrappers), Pay-by-Link API, Lightbox.
  • Step 4: additional features to consider, some self-serve and some requiring a Monri support agent to enable:
    • Self-serve-ish: Callback & Webhooks, Installments, Discounts (BIN- or card-targeted), Customers module, and request-level limitations like custom attributes/rules/custom parameters.
    • Requires a Monri support agent to set up (one-time, for both test and production): card tokenization (Secure Vault), Discounts, and Webhooks (the "back-off" notification mechanism covering declined transactions — except 3DS declines — plus approved/declined for refund/void/authorization and tokenized-card events).
  • Step 5: get help — helpdesk@monri.com for technical questions, ecomm-prodaja@monri.com for business/sales questions.

10. Additional Merchant-Facing Business Info

  • Support contacts observed across the documentation: support@monri.com (general integration questions, test accounts, enabling tokenization/rules/installments), helpdesk@monri.com (technical help during onboarding), ecomm-prodaja@monri.com (sales/business questions).
  • Monri is PCI DSS Level 1 certified and regulated under Visa/Mastercard rules — a fact merchants can cite in their own site's security statement (see §11).

11. Web Shop Compliance Requirements

Card scheme rules (Visa/Mastercard/etc.) require every merchant's checkout to display certain information correctly. This is mandatory — "every requirement must be fulfilled, otherwise acceptance of credit/debit card payment is not possible." Summarized for AI-agent reference (see the full compliance PDF for exact wording/graphics):

1. Web shop required content: full company name, commercial court number, company tax code, company number, company HQ + webshop address (if different), phone/email for customer contact.

2. Card names: only list card brands actually accepted; correct order is Mastercard before Maestro (no other brand between them); on first mention, American Express, Mastercard, and Maestro must carry the ® mark; all accepted brands must be displayed with equal prominence (no favoring one).

3. Card logos: must appear on the payment-method-selection page; must include every accepted brand; must not be resized/cropped/altered; must have clear surrounding space; Mastercard before Maestro with nothing between them; equal prominence for all.

4. Payment security logos: shown on the page with the card-security statement and on the payment page itself (recommended on the homepage too); one instance per page. Specific placement/spacing rules apply for Visa Secure, Mastercard Identity Check, and "Diners – Safe Online Shopping" logos/text. The Monri Payments PSP logo must also be shown (linking to http://monri.com/).

5. Mandatory legal/security text (templates provided in the source doc, adaptable per merchant):

  • Credit card purchase security statement — must mention TLS/SSL encryption, that Monri is PCI DSS Level 1 certified and regulated by Visa/Mastercard, that card numbers are never stored by the merchant, and that 3-D Secure is used for additional authentication.
  • Privacy statement — customers must be able to opt out of marketing use of their data; data is collected only as needed and access restricted to staff who need it.
  • Terms and conditions / Terms of sale — must cover ordering, payment, delivery, complaints/returns, and currency (a full example template exists for general e-commerce and one for hotel reservations with deposit/cancellation terms).
  • Currency conversion notice — if the webshop bills in a currency other than the buyer's card currency, disclose that the charged amount will be converted at the card network's exchange rate.

6. Product/cart/order display: clear product descriptions (name, key properties, picture if available, price with taxes/fees and currency); a persistently visible cart link; before final confirmation, the customer must see: product price, delivery price, discounts, base price, VAT, total charged amount, and must actively agree to the purchase terms (an explicit "click to accept" checkbox, not a pre-checked box).

7. Direct API card-data-entry rules (only relevant if the merchant collects raw card data on their own page, i.e. a Direct/custom integration rather than Components/Lightbox/Redirect):

  • Never store card number, expiration date, or CVV, and never redisplay them on any later page (e.g. order confirmation).
  • Only the first 6 and last 4 digits of the card number may ever be stored/shown; everything else must be masked.
  • Browser back/forward navigation to the card-entry page must not reveal previously entered card data.
  • Validate the card number with the Luhn algorithm before submitting, and inform the customer if invalid.
  • Collect expiry as MM/YY and reject expired dates client-side.
  • CVV length varies by brand: Amex 3 or 4 digits, Mastercard 3, Maestro 0 or 3 (varies), Visa 3.
  • Name/address/city/zip/country must be entered exactly as they appear on the card issuer's records, without regional diacritics.

Compliance checklist (from the source doc's own summary table): (1) web shop information present, (2) correct card-name spelling/order, (3) clickable card acceptance logos, (4) card security-program logos, (5) clickable Monri Payments logo, (6) credit-card security statement text, (7) data-privacy statement text, (8) terms & conditions text, (9) clear explanation of how refunds work, (10) description of delivery method, (11) description of products/services.


12. Testing Reference

  • Test base URL: https://ipgtest.monri.com
  • Test cards:
    • 4341792000000044 — Redirect Form walkthrough (any future expiry, any CVV).
    • 4111 1111 1111 1111 — generic Components demo card (12/25 expiry, 123 CVV in the example).
  • Amounts are always in minor units (100 = 1.00 in a 2-decimal currency).
  • Currencies: officially documented as USD, EUR, BAM, HRK (+ "CHF etc." on the v2 APIs); this project's newer test code also uses RSD, MKD, ALL for regional expansion markets. Treat HRK as legacy (Croatia is on the euro since 2023) and don't assume the official list is exhaustive.
  • Countries: pass ISO alpha-2/alpha-3/numeric codes in ch_country — HR, BA, RS, US, etc. seen across examples.
  • Before going live: test a successful purchase, a declined purchase, digest-mismatch handling, and your Success URL / Callback / Webhook receivers — and remember Monri's own "Website Inspection" step (§9) will check the compliance items in §11 before production is activated.

13. Known Discrepancies to Confirm with Monri

Flagging these rather than silently resolving them, since getting a digest scheme or endpoint wrong causes real integration failures:

  1. /v2/payment/new authorization scheme. The "Monri Components" guide and this project's actual working demo code (server.js, PHP curl sample) sign this endpoint with WP3-v2 (no request path in the digest). A separate, more recently dated, standalone "Payment API" document signs the same endpoint with WP3-v2.1 (path included), and uses /v2/payment/new as its own worked digest example. These two official sources contradict each other for the same endpoint. Since the demo app's code is confirmed working, WP3-v2 may still be accepted for backward compatibility even if WP3-v2.1 is the currently "correct" documented form — verify directly with Monri support before hardcoding either into a new integration.
  2. Monri(...) constructor argument. Official Components docs pass the authenticity_token as the first argument (Monri('<authenticity-token>')). This project's actual demo code instead passes the client_secret (window.Monri(client_secret, {...})). Confirm which is correct for your SDK version.
  3. digest field length. Both WebPay Form and Lightbox variable tables list the digest field's length as "40" — but a SHA-512 hex digest is 128 characters. This is very likely a copy/paste artifact in Monri's own documentation (possibly duplicated from the authenticity_token row) rather than a real constraint; don't validate against it.
  4. Legacy /v2/transaction digest algorithm. One retired test script in this project (DinoMerlin/newDateScriptDino.js) posts to /v2/transaction using a SHA-512 digest with no Authorization header, while the officially documented Card-on-File example posts JSON to the same /v2/transaction endpoint with pan_token/moto and (implicitly, per the surrounding legacy-XML sections) a SHA-1-style embedded digest. This project's other legacy scripts (testPayment.js, testPaymentJSON.js) also use SHA-1 for what looks like the same endpoint. Treat the SHA-512 variant as unverified.
  5. Missing "List of Response Codes" tables. Four separate sections of the source Documentation.docx (WebPay Form, Lightbox, Components, Card-on-File) list "List of response codes" in their own tables of contents, but none of that content actually exists in the file — it cuts off entirely after the Apple Pay Components section, before Keks Pay/AirCash/Flik Pay/IPS/PayCek detail, PayPal, and Valu Pay sections that are also listed in the TOC but never written. No response-code table is available in either source used to build this document — do not fabricate one; request the current list from support@monri.com if a client needs it.

14. Supported Payment Methods (supported_payment_methods values)

Value Description
card Standard card payment (Visa/Mastercard/Amex/etc.)
apple-pay Apple Pay wallet
google-pay Google Pay wallet
keks-pay KEKS Pay (local wallet)
air-cash Air Cash (local wallet)
flik-pay FLIK Pay (Serbia)
ips-rs IPS Instant Payment Scheme (Serbia) — use fname/lname instead of ch_full_name
pay-cek PayCek — cryptocurrency payment (Components only)
PayPal, Valu Pay Referenced in Monri's own documentation index but with no available parameter detail in either source — confirm with support@monri.com
<pan_token> A previously tokenized card — enables Card-on-File / saved-card payment

supported_payment_methods can also be a merchant-configured "hash" bundling several enabled methods, depending on account configuration.


15. Common Request Fields Glossary

Field Meaning
merchant_key / key Per-merchant shared secret used only for digest calculation. Backend-only.
authenticity_token Per-merchant identifier, also folded into the digest and sent in the Authorization header. Backend-only.
order_number Unique id per purchase attempt (1–40 chars); also the idempotency key for Pay-by-Link.
amount Integer, minor currency units.
currency 3-letter code — see currency notes in §3.1/§12.
order_info Free-text order description (3–100 chars), stored on the transaction and shown to the buyer.
transaction_type authorize, purchase, capture, refund, void (WebPay Form/Lightbox) — Components/Payment API only accept authorize/purchase at creation time.
scenario charge (default) or add_payment_method (⚠️ auto-refunds/voids — see §3.3).
ch_full_name, ch_address, ch_city, ch_zip, ch_country, ch_phone, ch_email Cardholder/billing details — see length/format tables in §3.1.
fname, lname Used instead of ch_full_name for IPS-RS payments.
language UI language: en, es, ba, hr (form field) — Components locales are broader, see §3.3.
custom_params Merchant-defined JSON metadata, echoed back in Success URL/Callback/Webhook.
digest Computed signature — formula depends on the endpoint, see §1.3.
tokenize_pan / tokenize_pan_offered / tokenize_brands Card tokenization controls (Secure Vault paid add-on).
pan_token Token representing a previously saved card.
future_usage, merchant_initiated_transaction, cit_id, moto Merchant-Initiated Transaction / Card-on-File / MOTO fields.
client_secret Short-lived token from /v2/payment/new, used client-side to initialize Components. Safe to expose to the frontend.
customer_uuid Id of a Customers-API profile (§4.2), 20 chars.
number_of_installments 1–2 digit integer, range 2–12.
custom_attributes JSON string enabling installments_config and/or fields_config (see §3.1).
success_url_override, cancel_url_override, callback_url_override Per-request HTTPS URL overrides.
supported_cc_issuers, rules, force_installments Advanced restriction/behavior flags — see §3.1.

16. Architecture Pattern (recommended for every integration type)

  1. Frontend collects cart/order data and customer billing details. It never touches the merchant key or authenticity token.
  2. Frontend calls your own backend (not Monri directly).
  3. Backend validates input, builds the exact JSON/XML body Monri expects, computes the timestamp + digest, builds the Authorization header (or embeds the digest field for XML/legacy endpoints), and calls the appropriate Monri endpoint.
  4. Backend returns to the frontend only what it needs — a digest/form-action URL (Redirect/Lightbox) or a client_secret (Components/Payment API) — never the merchant key/authenticity token.
  5. Frontend submits a hidden form (Redirect/Lightbox) or initializes Monri Components and mounts the relevant payment element.
  6. Backend separately handles Success URL redirects and/or Callback/Webhook POSTs to confirm the final transaction outcome and update the order — treat this as the source of truth, since the browser-side flow can be interrupted.

Secrets and signing live only on the backend — this is the single most important security rule across every integration type in this document.