Skip to content

⏱ 8 min
👤 Product Team
Technical integration guidance for the Ratepay Pay in 3 payment method

Overview

This guide explains how to integrate Ratepay Pay in 3 across the buyer journey.

It covers:

  • how to calculate Pay in 3 plan values
  • how to display Pay in 3 on product, cart, and checkout pages
  • how to connect the checkout flow to Ratepay APIs
  • when to use client-side calculation and when to use CALCULATION_REQUEST

This page focuses on technical integration. For mandatory legal disclosure requirements, see Pay in 3 legal requirements.

Recommended approach: calculate Pay in 3 plan details client-side for display purposes, and use the standard Ratepay checkout API flow for payment processing.

Integration summary

TopicRecommended approachAlternative approach
Product page plan displayClient-side calculationCALCULATION_REQUEST
Cart page plan displayClient-side calculationCALCULATION_REQUEST
Checkout plan displayClient-side calculationCALCULATION_REQUEST
Payment processingPAYMENT_INIT + PAYMENT_REQUESTSame
Final order confirmationPAYMENT_CONFIRM, if required for your setupSame

Visual overview

The examples below illustrate the main integration contexts and UI states in the buyer journey.

ScreenStagePurposeNotes
Pay in 3 — Product teaserProduct pageShow Pay in 3 teaser near the product priceOptional from a legal perspective, but recommended for transparency and conversion
Pay in 3 — Cart teaserCart pageRecalculate and show Pay in 3 based on the current cart totalUpdate whenever quantity or cart contents change
Pay in 3 — Calculation details modalProduct / CartShow detailed plan values in a modal or detail viewTypically opened through a “Learn more” interaction
Pay in 3 — Checkout compact viewCheckoutShow Pay in 3 as the selected payment method in the default checkout stateExample of the main payment method view before expanding additional instalment details
Pay in 3 — Checkout expanded viewCheckoutShow the expanded checkout state with additional instalment breakdown detailsExample of an expanded buyer-facing checkout view

Core credit terms to show

Label in UIGerman labelDescription
Per monthMonatliche RateMonthly instalment amount
DurationLaufzeitNumber of instalments and duration
Effective InterestEffektiver JahreszinsAnnual percentage rate of charge (APR)
InterestZinsbetragTotal interest amount
TotalGesamtbetragTotal amount payable
Monthly instalment amountMonatliche RateRegular instalment amount shown to the buyer
Final instalment amountLetzte RateFinal instalment amount, which may differ slightly because of rounding

For Pay in 3, these values are typically:

  • Duration = 3 months
  • Effective Interest = 0%
  • Interest = 0
  • Total = basket amount
  • Monthly instalment amount = regular instalment amount calculated from the basket amount
  • Final instalment amount = last instalment amount, which may differ slightly because of rounding

Integration

1. Choose your calculation approach

Before showing Pay in 3 to the buyer, you need to obtain the plan values for the current amount.


Option A — Client-side calculation

This is the recommended approach for display purposes.

Pay in 3 is a fixed product:

  • 3 monthly instalments
  • 0% interest
  • 0 fees

Because most parameters are static, the display values can be calculated client-side from the basket amount. The final instalment absorbs any rounding remainder.

The calculation function can also accept an optional shipmentDate (YYYY-MM-DD). If your shop has a reliable delivery estimate, you can use it to generate a more accurate estimated instalment schedule. If omitted, the function uses today’s date and returns a general estimate.


Use the following helper function to calculate Pay in 3 plan values directly in your frontend or backend application code.

function calculatePayIn3(amount, shipmentDate) {
  // --- Configuration: Pay in 3 is a 0% interest, 0-fee product ---
  const NUMBER_OF_INSTALLMENTS = 3;
  const DURATION_UNIT = "months";
  const INTEREST_RATE = 0;
  const INTEREST_AMOUNT = 0;
  const FEES_AMOUNT = 0;
  const HAS_INTEREST = false;
  const HAS_FEES = false;

  // --- Calculate installment amounts ---
  // Split evenly; any rounding remainder goes to the final installment
  const regularAmount = Math.round((amount / NUMBER_OF_INSTALLMENTS) * 100) / 100;
  const finalAmount = Math.round((amount - regularAmount * (NUMBER_OF_INSTALLMENTS - 1)) * 100) / 100;

  // --- Determine the first due date ---
  // First instalment is due on the 2nd of the month following shipment,
  // provided there are at least 28 days between shipment and that date.
  // Otherwise, it is pushed to the 2nd of the subsequent month.
  function getFirstDueDate(shipment) {
    let next2nd = new Date(Date.UTC(shipment.getUTCFullYear(), shipment.getUTCMonth() + 1, 2));
    const shipmentUTC = Date.UTC(shipment.getUTCFullYear(), shipment.getUTCMonth(), shipment.getUTCDate());
    const next2ndUTC = Date.UTC(next2nd.getUTCFullYear(), next2nd.getUTCMonth(), next2nd.getUTCDate());
    const diffDays = Math.floor((next2ndUTC - shipmentUTC) / (1000 * 60 * 60 * 24));
    if (diffDays >= 28) return next2nd;
    return new Date(Date.UTC(shipment.getUTCFullYear(), shipment.getUTCMonth() + 2, 2));
  }

  // Parse shipmentDate string (YYYY-MM-DD) or default to today, using UTC for consistency
  let shipment;
  if (shipmentDate) {
    const parts = shipmentDate.split("-");
    shipment = new Date(Date.UTC(+parts[0], +parts[1] - 1, +parts[2]));
  } else {
    const today = new Date();
    shipment = new Date(Date.UTC(today.getFullYear(), today.getMonth(), today.getDate()));
  }
  const firstDue = getFirstDueDate(shipment);

  // --- Build the installment schedule ---
  const schedule = [];
  let remaining = amount;
  for (let i = 1; i <= NUMBER_OF_INSTALLMENTS; i++) {
    const dueDate = new Date(Date.UTC(firstDue.getUTCFullYear(), firstDue.getUTCMonth() + (i - 1), 2));
    const payment = i < NUMBER_OF_INSTALLMENTS ? regularAmount : finalAmount;
    remaining = Math.round((remaining - payment) * 100) / 100;
    schedule.push({
      installmentNumber: i,
      estimatedDueDate:
        dueDate.getUTCFullYear() + "-" +
        String(dueDate.getUTCMonth() + 1).padStart(2, "0") + "-" +
        String(dueDate.getUTCDate()).padStart(2, "0"),
      paymentAmount: payment,
      principalAmount: payment,
      interestAmount: INTEREST_AMOUNT,
      feesAmount: FEES_AMOUNT,
      remainingPrincipalBalanceAmount: remaining,
    });
  }

  // --- Return the complete plan object ---
  return {
    planMetadata: { hasInterest: HAS_INTEREST, hasFees: HAS_FEES },
    repaymentPlan: {
      numberOfInstallments: NUMBER_OF_INSTALLMENTS,
      durationOfInstallments: DURATION_UNIT,
      regularInstallmentAmount: regularAmount,
      finalInstallmentAmount: finalAmount,
    },
    creditTerms: {
      totalPayableAmount: amount,
      totalCostOfCreditAmount: INTEREST_AMOUNT + FEES_AMOUNT,
      totalInterestAmount: INTEREST_AMOUNT,
      totalFeesAmount: FEES_AMOUNT,
      nominalInterestRatePercentage: INTEREST_RATE,
      annualPercentageRate: INTEREST_RATE,
    },
    fees: { serviceFeeAmount: FEES_AMOUNT },
    installmentSchedule: schedule,
  };
}

Example function usage

const productAmount = 200;
const plan = calculatePayIn3(productAmount);

Key output fields

JSON fieldUI labelMeaning
repaymentPlan.regularInstallmentAmountPer monthRegular monthly instalment amount
repaymentPlan.numberOfInstallments + repaymentPlan.durationOfInstallmentsDurationNumber and duration of instalments
creditTerms.annualPercentageRateEffective InterestEffective interest rate shown to the buyer
creditTerms.totalInterestAmountInterestTotal interest amount
creditTerms.totalPayableAmountTotalTotal amount payable
repaymentPlan.finalInstallmentAmountFinal instalmentFinal instalment amount, if it differs due to rounding
installmentSchedule[].estimatedDueDateEstimated due date for each instalment, if a shipment date is used to generate the schedule

Option B — Server-side calculation

Use the Ratepay XML API CALCULATION_REQUEST operation if you prefer to retrieve plan values from the server instead of calculating them client-side.

The response contains the core instalment values needed for display and checkout mapping.

See also: CALCULATION_REQUEST

For Pay in 3, both approaches can support the same buyer-facing disclosure values. Choose the option that best fits your architecture.

<?xml version="1.0"?>
<request version="1.0" xmlns="urn://www.ratepay.com/payment/1_0">
  <head>
    <system-id>MyTestsystem</system-id>
    <operation subtype="calculation-by-time">CALCULATION_REQUEST</operation>
    <credential>
      <profile-id>INTEGRATION_TE_DACH</profile-id>
      <securitycode>4c0a11923fa3433fb168f9c7176429e9</securitycode>
    </credential>
  </head>
  <content>
    <installment-calculation>
      <amount>200.00</amount>
      <calculation-time>
        <month>3</month>
      </calculation-time>
    </installment-calculation>
  </content>
</request>

Key response fields

For Pay in 3, you can ignore <service-charge> and <monthly-debit-interest> because these values are always 0.

XML fieldUI labelMeaning
<rate>Per monthRegular monthly instalment amount
<number-of-rates>DurationNumber of monthly instalments
<annual-percentage-rate>Effective InterestEffective interest rate shown to the buyer
<interest-amount>InterestTotal interest amount
<total-amount>TotalTotal amount payable
<last-rate>Final instalmentFinal instalment amount, if it differs due to rounding
<payment-firstday>Day of month used for direct debit collection and for installment schedule logic

2. Product page integration

On the product page, you may show a Pay in 3 teaser near the product price.

  • calculate Pay in 3 plan details using chosen calculation approach (see Calculation Approaches)
  • show the monthly instalment amount
  • show the duration
  • provide a Learn more link or similar interaction
  • open a modal or detail view with the full plan values
  • update values dynamically when the product price changes, for example after variant selection

Required detail values for the modal or expanded view

LabelDescription
Per monthMonthly instalment amount
DurationNumber and duration of instalments
Effective InterestAnnual percentage rate
InterestTotal interest amount
TotalTotal amount payable

Example UI

Product page teaserProduct page modal
Pay in 3 — Product teaserPay in 3 — Calculation details modal

3. Cart page integration

The cart page follows the same principle as the product page, but the amount must always reflect the current cart total.

  • calculate Pay in 3 plan details using chosen calculation approach (see Calculation Approaches)
  • update the values whenever quantity or items change
  • show the teaser in the cart summary area
  • provide a “Learn more” interaction with the detailed values

Example UI

Cart page teaserCart page modal
Pay in 3 — Cart teaserPay in 3 — Calculation details modal

4. Checkout integration

StepPurpose
PAYMENT_INITInitialize the Ratepay transaction and receive transaction-id
Plan calculationGenerate the display values and instalment details
Buyer-facing checkout displayShow the selected Pay in 3 plan and required inputs
PAYMENT_REQUESTSend customer, basket, and payment data to Ratepay
PAYMENT_CONFIRMFinalize the transaction if required for your setup

Submit PAYMENT_INIT

The first step of the checkout workflow is PAYMENT_INIT. This operation initializes the transaction and returns a transaction-id that must be included in subsequent API calls.

See also: PAYMENT_INIT

<?xml version="1.0" encoding="UTF-8"?>
<request version="1.0" xmlns="urn://www.ratepay.com/payment/1_0">
  <head>
    <system-id>myshop</system-id>
    <operation>PAYMENT_INIT</operation>
    <credential>
      <profile-id>INTEGRATION_TE_DACH</profile-id>
      <securitycode>4c0a11923fa3433fb168f9c7176429e9</securitycode>
    </credential>
  </head>
</request>

Calculate plan details for checkout

Use the final checkout basket amount to generate the Pay in 3 plan values using chosen calculation approach.

See Calculation Approaches


Display Pay in 3 in checkout

When the buyer selects Pay in 3 as the payment method, your checkout should render the Pay in 3 plan values and collect the required payment data.

Checkout UI should include

  • credit term values for the selected plan
  • instalment amount breakdown
  • date of birth input
  • IBAN input
  • bank account owner input
  • SEPA mandate text and consent checkbox
  • Terms of Payment and Privacy / Risk Check links near the order button

The legal requirements for what must be shown at checkout are defined on the Pay in 3 legal requirements page.

By default, checkout should avoid fixed due dates because the actual schedule depends on shipment timing. A buyer-friendly simplified breakdown is acceptable, or you may show estimated due dates only if they are based on a reliable shipment date.

Example UI

Checkout compact viewCheckout expanded view
Pay in 3 — Checkout examplePay in 3 — Checkout example

Map values into PAYMENT_REQUEST

After the buyer selects Pay in 3 and provides the required data, send PAYMENT_REQUEST.

Mapping from client-side calculation result

PAYMENT_REQUEST fieldSource from calculatePayIn3()
<installment-number>repaymentPlan.numberOfInstallments
<installment-amount>repaymentPlan.regularInstallmentAmount
<last-installment-amount>repaymentPlan.finalInstallmentAmount
<interest-rate>creditTerms.nominalInterestRatePercentage
<payment-firstday>Constant value 2
<amount>creditTerms.totalPayableAmount

Mapping from CALCULATION_REQUEST response

PAYMENT_REQUEST fieldSource from XML response
<installment-number><number-of-rates>
<installment-amount><rate>
<last-installment-amount><last-rate>
<interest-rate><interest-rate>
<payment-firstday><payment-firstday>
<amount><total-amount>

Submit PAYMENT_REQUEST

PAYMENT_REQUEST is the main checkout operation. It sends the customer details, basket data, and selected Pay in 3 payment details to Ratepay.

See also: PAYMENT_REQUEST

Main request areas

AreaExamples
Customer dataName, gender, date of birth, IP address, email, phone
AddressesBilling and shipping addresses
Bank accountIBAN, BIC, account holder
Shopping basketItems, discounts, shipping, total amount
PaymentInstallment details and debit pay type
<?xml version="1.0" encoding="UTF-8"?>
<request version="1.0" xmlns="urn://www.ratepay.com/payment/1_0">
  <head>
    <system-id>MyTestsystem</system-id>
    <transaction-id>xx-xxxxxxxxxxxxxx</transaction-id>
    <operation>PAYMENT_REQUEST</operation>
    <credential>
      <profile-id>INTEGRATION_TE_DACH</profile-id>
      <securitycode>4c0a11923fa3433fb168f9c7176429e9</securitycode>
    </credential>
    <external>
      <order-id>O-1234-HDZ</order-id>
      <merchant-consumer-id>12345</merchant-consumer-id>
    </external>
    <customer-device>
      <device-token>xxxxxxxxxxxxxxxxxxxxxxxx</device-token>
    </customer-device>
  </head>
  <content>
    <customer>
      <first-name>Max</first-name>
      <last-name>Mustermann</last-name>
      <gender>M</gender>
      <date-of-birth>1982-10-31</date-of-birth>
      <ip-address>127.0.0.1</ip-address>
      <contacts>
        <email>test@test.de</email>
        <phone>
          <direct-dial>030123456</direct-dial>
        </phone>
      </contacts>
      <addresses>
        <address type="BILLING">
          <street>Nicht-Versenden-Strasse</street>
          <street-number>1</street-number>
          <zip-code>12345</zip-code>
          <city>Testhausen</city>
          <country-code>DE</country-code>
        </address>
        <address type="DELIVERY">
          <street>Strasse der Lieferadresse</street>
          <street-number>2</street-number>
          <zip-code>54321</zip-code>
          <city>Testhausen</city>
          <country-code>DE</country-code>
        </address>
      </addresses>
      <bank-account>
        <owner>Max Mustermann</owner>
        <iban>DE44100500001654698497</iban>
        <bic-swift>BELADEBEXXX</bic-swift>
      </bank-account>
      <nationality>DE</nationality>
      <customer-allow-credit-inquiry>yes</customer-allow-credit-inquiry>
    </customer>

    <shopping-basket amount="200.00" currency="EUR">
      <items>
        <item article-number="A001" quantity="1" unit-price-gross="200.00" tax-rate="19">Example Product</item>
      </items>
      <shipping unit-price-gross="0.00" tax-rate="19">Versandkosten</shipping>
    </shopping-basket>

    <payment currency="EUR" method="INSTALLMENT">
      <amount>200.00</amount>
      <installment-details>
        <installment-number>3</installment-number>
        <installment-amount>66.67</installment-amount>
        <last-installment-amount>66.66</last-installment-amount>
        <interest-rate>0</interest-rate>
        <payment-firstday>2</payment-firstday>
      </installment-details>
      <debit-pay-type>DIRECT-DEBIT</debit-pay-type>
    </payment>
  </content>
</request>

Submit PAYMENT_CONFIRM

After a successful PAYMENT_REQUEST, finalize the transaction with PAYMENT_CONFIRM if this step is required for your integration setup.

See also: PAYMENT_CONFIRM

The necessity of PAYMENT_CONFIRM depends on your integration setup. Please confirm with your Ratepay counterpart whether this step is required.

<?xml version="1.0" encoding="UTF-8"?>
<request version="1.0" xmlns="urn://www.ratepay.com/payment/1_0">
  <head>
    <system-id>MyTestsystem</system-id>
    <transaction-id>xx-xxxxxxxxxxxxxx</transaction-id>
    <operation>PAYMENT_CONFIRM</operation>
    <credential>
      <profile-id>INTEGRATION_TE_DACH</profile-id>
      <securitycode>4c0a11923fa3433fb168f9c7176429e9</securitycode>
    </credential>
    <external>
      <order-id>O-1234-HDZ</order-id>
    </external>
  </head>
</request>

If you want a pragmatic setup with low complexity, use this pattern:

StageSuggested implementation
Product pageClient-side calculation + teaser + “Learn more” modal
Cart pageReuse the same function with cart total
Checkout displayReuse the same function with final basket amount
Checkout API flowPAYMENT_INITPAYMENT_REQUESTPAYMENT_CONFIRM if required
Legal complianceKeep the displayed fields aligned with the legal requirements page

Further resources