Installments with interest (MCI)
On this page
Monthly payments with interest is a payment option that allows your customers to divide the cost of a purchase into several monthly installments, with interest applied to the outstanding balance.
With MCI, a customer pays an additional interest rate for dividing the purchase cost into monthly installments.
When a customer chooses to pay through Monthly payments with interest, the total cost of the purchase is divided into monthly installments and interest rates are applied to the balance remaining in each period.
How MCI works#
Here's how an MCI flow works:
- The store configures the different monthly payment options by PSP in the DEUNA Admin.
- The following is taken into account:
- The credit card franchise to which it applies.
- The respective minimum amount for each configured installment.
- The interest that applies to each franchise.
- The store checkout shows MCI availability when a customer enters the BIN of a card.
- The customer selects the monthly payment from a list shown in the checkout.
- The transaction is sent to the PSP to be processed.
Implement MCI#
To use MSI or MCI, configure at least one installments campaign.
To offer installment options:
- Generate the campaign options
installments_type.
curl --location --request POST 'https://apigw.getduna.com/merchants/{merchant_id}/installments/campaigns' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {merchant_auth_token}' \
--data '{
"name": "new campaign",
"description": "testing campaign MCI",
"status": "active",
"processors": [
{
"id": {processor_id},
"name": {processor_name}
}
],
// display_label_template is optional; that configuration allows you to
// change the format of the field "display_label_amount" of each available
'// option when you generate an installment plan. If you don`t configurate this'
'// field, the template will be the default one.'
"display_label_template": {
"language": "es",
"MSI": "{installments} meses sin intereses de ${amount}",
"MCI": "{installments} meses de ${amount}"
},
"options": [
{
"installments": 3,
"installments_type": "MCI",
"currency": "MXN",
"card_branch": [
{
// minimum amount for installment amount in the plan, this option
// will be valid to generate installment plan only in that case;
// For example, with a total amount of $2100; in 3 installments the amount
// will be of $700, so $700 >= $500, then the option is valid to
// generate an installment plan of $2100 (you can offer 3 installments
// to pay $2100). In the case of having intallments_rate greater than 0,
// first the interest is applied to the amount and then it is compared with the min_amount.
"amount_min": 500,
// optional, the same example than amount_min but with the maximum value.
"amount_max": 2000,
"name": "visa",
// is the percentage applied to the amount in order to generate the options for the plan.
"installment_rate": 1.5,
// use the operators "amount", "rate" and "installments" when calculate the new amount;
// if it's not specified, the calculation is the default for interests: "amount+(amount*(rate/100))"
"installments_interest_formula": "amount+((amount*rate*installments)/100)"
}
]
},
{
"installments": 6,
"installments_type": "MCI",
"currency": "MXN",
"card_branch": [
{
"amount_min": 250,
"amount_max": 1000,
"name": "visa",
}
]
}
// you can offer more options, the installments quantity must be divisible by 3.
]
}'const response = await fetch("https://apigw.getduna.com/merchants/{merchant_id}/installments/campaigns", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer {merchant_auth_token}"
},
body: "{\n \"name\": \"new campaign\",\n \"description\": \"testing campaign MCI\",\n \"status\": \"active\",\n \"processors\": [\n {\n \"id\": {processor_id},\n \"name\": {processor_name}\n }\n ],\n\t\t// display_label_template is optional; that configuration allows you to \n\t\t// change the format of the field \"display_label_amount\" of each available \n \t//"
});
if (!response.ok) throw new Error(`Request failed: ${response.status}`);
const data = await response.json();import requests
response = requests.request(
"POST",
"https://apigw.getduna.com/merchants/{merchant_id}/installments/campaigns",
headers={
"Content-Type": "application/json",
"Authorization": "Bearer {merchant_auth_token}"
},
data="{\n \"name\": \"new campaign\",\n \"description\": \"testing campaign MCI\",\n \"status\": \"active\",\n \"processors\": [\n {\n \"id\": {processor_id},\n \"name\": {processor_name}\n }\n ],\n\t\t// display_label_template is optional; that configuration allows you to \n\t\t// change the format of the field \"display_label_amount\" of each available \n \t//",
)
response.raise_for_status()
data = response.json()<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://apigw.getduna.com/merchants/{merchant_id}/installments/campaigns",
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"Authorization: Bearer {merchant_auth_token}"
],
CURLOPT_POSTFIELDS => "{\n \"name\": \"new campaign\",\n \"description\": \"testing campaign MCI\",\n \"status\": \"active\",\n \"processors\": [\n {\n \"id\": {processor_id},\n \"name\": {processor_name}\n }\n ],\n\t\t// display_label_template is optional; that configuration allows you to \n\t\t// change the format of the field \"display_label_amount\" of each available \n \t//"
]);
$response = curl_exec($curl);
curl_close($curl);import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class Example {
public static void main(String[] args) throws Exception {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://apigw.getduna.com/merchants/{merchant_id}/installments/campaigns"))
.header("Content-Type", "application/json")
.header("Authorization", "Bearer {merchant_auth_token}")
.method("POST", HttpRequest.BodyPublishers.ofString("{\n \"name\": \"new campaign\",\n \"description\": \"testing campaign MCI\",\n \"status\": \"active\",\n \"processors\": [\n {\n \"id\": {processor_id},\n \"name\": {processor_name}\n }\n ],\n\t\t// display_label_template is optional; that configuration allows you to \n\t\t// change the format of the field \"display_label_amount\" of each available \n \t//"))
.build();
HttpResponse<String> response = HttpClient.newHttpClient().send(
request, HttpResponse.BodyHandlers.ofString()
);
System.out.println(response.body());
}
}package main
import (
"fmt"
"io"
"net/http"
"strings"
)
func main() {
request, err := http.NewRequest("POST", "https://apigw.getduna.com/merchants/{merchant_id}/installments/campaigns", strings.NewReader("{\n \"name\": \"new campaign\",\n \"description\": \"testing campaign MCI\",\n \"status\": \"active\",\n \"processors\": [\n {\n \"id\": {processor_id},\n \"name\": {processor_name}\n }\n ],\n\t\t// display_label_template is optional; that configuration allows you to \n\t\t// change the format of the field \"display_label_amount\" of each available \n \t//"))
if err != nil { panic(err) }
request.Header.Set("Content-Type", "application/json")
request.Header.Set("Authorization", "Bearer {merchant_auth_token}")
response, err := http.DefaultClient.Do(request)
if err != nil { panic(err) }
defer response.Body.Close()
body, _ := io.ReadAll(response.Body)
fmt.Println(string(body))
}- Enable your store's payment processors to perform transactions with the flag
allow_installments: true. The flag behavior is as follows:"MCI" or null: The amount that goes to the processor does not have interest applied and the transaction must be updated after being processed with the interest applied by the processor. The fields that are updated based on the processor response are:amountinstallments_amountinstallments_rate
"MSI": A transaction without interest is performed against the processor that carries out the transaction. The amount reaches the processor with calculated interest. The amount is updated before carrying out the transaction and being sent to the processor.
Example to create the processor
curl --location --request POST 'https://apigw.getduna.com/merchants/{merchant_id}/stores/{store_code}/processors' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {merchant_auth_token}' \
--data '{
"name": {processor_name},
"payment_processor_id": {processor_id},
"enabled": true,
"currency_iso3": "MXN",
"external_merchant_id": "your merchant id in payment processor",
"public_api_key": "your public key in payment processor",
"private_api_key": "your private key in payment processor",
"allow_installments": true,
"mci_to_psp_as": "MCI"|"MSI"
}'curl --location --request POST 'https://apigw.getduna.com/merchants/{merchant_id}/stores/{store_code}/processors' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {merchant_auth_token}' \
--data '{
"name": {processor_name},
"payment_processor_id": {processor_id},
"enabled": true,
"currency_iso3": "MXN",
"external_merchant_id": "your merchant id in payment processor",
"public_api_key": "your public key in payment processor",
"private_api_key": "your private key in payment processor",
"allow_installments": true,
"mci_to_psp_as": "MCI"|"MSI"
}'import requests
response = requests.request(
"POST",
"https://apigw.getduna.com/merchants/{merchant_id}/stores/{store_code}/processors",
headers={
"Content-Type": "application/json",
"Authorization": "Bearer {merchant_auth_token}"
},
data="{\n \"name\": {processor_name},\n \"payment_processor_id\": {processor_id},\n \"enabled\": true,\n \"currency_iso3\": \"MXN\",\n \"external_merchant_id\": \"your merchant id in payment processor\",\n \"public_api_key\": \"your public key in payment processor\",\n\t\t\"private_api_key\": \"your private key in payment processor\",\n \"allow_installments\": true,\n\t\t\"mci_to_psp_as\": \"MCI\"|\"MSI\"\n}",
)
response.raise_for_status()
data = response.json()<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://apigw.getduna.com/merchants/{merchant_id}/stores/{store_code}/processors",
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"Authorization: Bearer {merchant_auth_token}"
],
CURLOPT_POSTFIELDS => "{\n \"name\": {processor_name},\n \"payment_processor_id\": {processor_id},\n \"enabled\": true,\n \"currency_iso3\": \"MXN\",\n \"external_merchant_id\": \"your merchant id in payment processor\",\n \"public_api_key\": \"your public key in payment processor\",\n\t\t\"private_api_key\": \"your private key in payment processor\",\n \"allow_installments\": true,\n\t\t\"mci_to_psp_as\": \"MCI\"|\"MSI\"\n}"
]);
$response = curl_exec($curl);
curl_close($curl);import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class Example {
public static void main(String[] args) throws Exception {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://apigw.getduna.com/merchants/{merchant_id}/stores/{store_code}/processors"))
.header("Content-Type", "application/json")
.header("Authorization", "Bearer {merchant_auth_token}")
.method("POST", HttpRequest.BodyPublishers.ofString("{\n \"name\": {processor_name},\n \"payment_processor_id\": {processor_id},\n \"enabled\": true,\n \"currency_iso3\": \"MXN\",\n \"external_merchant_id\": \"your merchant id in payment processor\",\n \"public_api_key\": \"your public key in payment processor\",\n\t\t\"private_api_key\": \"your private key in payment processor\",\n \"allow_installments\": true,\n\t\t\"mci_to_psp_as\": \"MCI\"|\"MSI\"\n}"))
.build();
HttpResponse<String> response = HttpClient.newHttpClient().send(
request, HttpResponse.BodyHandlers.ofString()
);
System.out.println(response.body());
}
}package main
import (
"fmt"
"io"
"net/http"
"strings"
)
func main() {
request, err := http.NewRequest("POST", "https://apigw.getduna.com/merchants/{merchant_id}/stores/{store_code}/processors", strings.NewReader("{\n \"name\": {processor_name},\n \"payment_processor_id\": {processor_id},\n \"enabled\": true,\n \"currency_iso3\": \"MXN\",\n \"external_merchant_id\": \"your merchant id in payment processor\",\n \"public_api_key\": \"your public key in payment processor\",\n\t\t\"private_api_key\": \"your private key in payment processor\",\n \"allow_installments\": true,\n\t\t\"mci_to_psp_as\": \"MCI\"|\"MSI\"\n}"))
if err != nil { panic(err) }
request.Header.Set("Content-Type", "application/json")
request.Header.Set("Authorization", "Bearer {merchant_auth_token}")
response, err := http.DefaultClient.Do(request)
if err != nil { panic(err) }
defer response.Body.Close()
body, _ := io.ReadAll(response.Body)
fmt.Println(string(body))
}Example to update the processor
curl --location --request PATCH 'https://apigw.getduna.com/merchants/{merchant_id}/stores/{store_code}/processors/{merchant_payment_processor_id}' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {merchant_auth_token}' \
--data '{
"allow_installments": true,
"mci_to_psp_as": "MCI"|"MSI"
}'curl --location --request PATCH 'https://apigw.getduna.com/merchants/{merchant_id}/stores/{store_code}/processors/{merchant_payment_processor_id}' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {merchant_auth_token}' \
--data '{
"allow_installments": true,
"mci_to_psp_as": "MCI"|"MSI"
}'import requests
response = requests.request(
"PATCH",
"https://apigw.getduna.com/merchants/{merchant_id}/stores/{store_code}/processors/{merchant_payment_processor_id}",
headers={
"Content-Type": "application/json",
"Authorization": "Bearer {merchant_auth_token}"
},
data="{\n \"allow_installments\": true,\n\t\t\"mci_to_psp_as\": \"MCI\"|\"MSI\"\n}",
)
response.raise_for_status()
data = response.json()<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://apigw.getduna.com/merchants/{merchant_id}/stores/{store_code}/processors/{merchant_payment_processor_id}",
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"Authorization: Bearer {merchant_auth_token}"
],
CURLOPT_POSTFIELDS => "{\n \"allow_installments\": true,\n\t\t\"mci_to_psp_as\": \"MCI\"|\"MSI\"\n}"
]);
$response = curl_exec($curl);
curl_close($curl);import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class Example {
public static void main(String[] args) throws Exception {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://apigw.getduna.com/merchants/{merchant_id}/stores/{store_code}/processors/{merchant_payment_processor_id}"))
.header("Content-Type", "application/json")
.header("Authorization", "Bearer {merchant_auth_token}")
.method("PATCH", HttpRequest.BodyPublishers.ofString("{\n \"allow_installments\": true,\n\t\t\"mci_to_psp_as\": \"MCI\"|\"MSI\"\n}"))
.build();
HttpResponse<String> response = HttpClient.newHttpClient().send(
request, HttpResponse.BodyHandlers.ofString()
);
System.out.println(response.body());
}
}package main
import (
"fmt"
"io"
"net/http"
"strings"
)
func main() {
request, err := http.NewRequest("PATCH", "https://apigw.getduna.com/merchants/{merchant_id}/stores/{store_code}/processors/{merchant_payment_processor_id}", strings.NewReader("{\n \"allow_installments\": true,\n\t\t\"mci_to_psp_as\": \"MCI\"|\"MSI\"\n}"))
if err != nil { panic(err) }
request.Header.Set("Content-Type", "application/json")
request.Header.Set("Authorization", "Bearer {merchant_auth_token}")
response, err := http.DefaultClient.Do(request)
if err != nil { panic(err) }
defer response.Body.Close()
body, _ := io.ReadAll(response.Body)
fmt.Println(string(body))
}- Confirm whether the store can use pre-configured installments supplied by VTEX.
- When supported, the installments obtained from VTEX must match the campaign options and must already include the applicable interest.
- Otherwise, DEUNA builds the MCI installment plan from the campaign configuration. The amount depends on:
installments_rate: Applies to the amount directly if noinstallments_interest_formulais defined.installments_interest_formula: If specified, then defines the interest calculation based on:amountrateinstallments
- Configure the DEUNA endpoint according to the installments enabled in VTEX.
- Create an external endpoint, specifying that it is for MCI.
- If you don't configure the endpoint, then a default endpoint is used for the case.
curl --location 'https://apigw.getduna.com/merchants/{merchant_id}/external-endpoints' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {merchant_auth_token}' \
--data '{
"url": "https://middleware.deuna.io/api/v1/merchants/{merchant_id}/transactions/{transaction_id}/installments/mci?bin={bin}&salesChannel=1&paymentProcessors=t1pagos",
"http_method": "GET",
"headers": [
{
"key": "vtex-key-header",
"value": "vtex-value-header"
}
],
"config_type": "MCI"
}'curl --location 'https://apigw.getduna.com/merchants/{merchant_id}/external-endpoints' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {merchant_auth_token}' \
--data '{
"url": "https://middleware.deuna.io/api/v1/merchants/{merchant_id}/transactions/{transaction_id}/installments/mci?bin={bin}&salesChannel=1&paymentProcessors=t1pagos",
"http_method": "GET",
"headers": [
{
"key": "vtex-key-header",
"value": "vtex-value-header"
}
],
"config_type": "MCI"
}'import requests
response = requests.request(
"POST",
"https://apigw.getduna.com/merchants/{merchant_id}/external-endpoints",
headers={
"Content-Type": "application/json",
"Authorization": "Bearer {merchant_auth_token}"
},
json={
"url": "https://middleware.deuna.io/api/v1/merchants/{merchant_id}/transactions/{transaction_id}/installments/mci?bin={bin}&salesChannel=1&paymentProcessors=t1pagos",
"http_method": "GET",
"headers": [
{
"key": "vtex-key-header",
"value": "vtex-value-header"
}
],
"config_type": "MCI"
},
)
response.raise_for_status()
data = response.json()<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://apigw.getduna.com/merchants/{merchant_id}/external-endpoints",
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"Authorization: Bearer {merchant_auth_token}"
],
CURLOPT_POSTFIELDS => json_encode([
"url" => "https://middleware.deuna.io/api/v1/merchants/{merchant_id}/transactions/{transaction_id}/installments/mci?bin={bin}&salesChannel=1&paymentProcessors=t1pagos",
"http_method" => "GET",
"headers" => [
[
"key" => "vtex-key-header",
"value" => "vtex-value-header"
]
],
"config_type" => "MCI"
])
]);
$response = curl_exec($curl);
curl_close($curl);import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class Example {
public static void main(String[] args) throws Exception {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://apigw.getduna.com/merchants/{merchant_id}/external-endpoints"))
.header("Content-Type", "application/json")
.header("Authorization", "Bearer {merchant_auth_token}")
.method("POST", HttpRequest.BodyPublishers.ofString("{\n \"url\": \"https://middleware.deuna.io/api/v1/merchants/{merchant_id}/transactions/{transaction_id}/installments/mci?bin={bin}&salesChannel=1&paymentProcessors=t1pagos\",\n \"http_method\": \"GET\",\n \"headers\": [\n {\n \"key\": \"vtex-key-header\",\n \"value\": \"vtex-value-header\"\n }\n ],\n \"config_type\": \"MCI\"\n }"))
.build();
HttpResponse<String> response = HttpClient.newHttpClient().send(
request, HttpResponse.BodyHandlers.ofString()
);
System.out.println(response.body());
}
}package main
import (
"fmt"
"io"
"net/http"
"strings"
)
func main() {
request, err := http.NewRequest("POST", "https://apigw.getduna.com/merchants/{merchant_id}/external-endpoints", strings.NewReader("{\n \"url\": \"https://middleware.deuna.io/api/v1/merchants/{merchant_id}/transactions/{transaction_id}/installments/mci?bin={bin}&salesChannel=1&paymentProcessors=t1pagos\",\n \"http_method\": \"GET\",\n \"headers\": [\n {\n \"key\": \"vtex-key-header\",\n \"value\": \"vtex-value-header\"\n }\n ],\n \"config_type\": \"MCI\"\n }"))
if err != nil { panic(err) }
request.Header.Set("Content-Type", "application/json")
request.Header.Set("Authorization", "Bearer {merchant_auth_token}")
response, err := http.DefaultClient.Do(request)
if err != nil { panic(err) }
defer response.Body.Close()
body, _ := io.ReadAll(response.Body)
fmt.Println(string(body))
}- Query installment options.
curl --location --request GET 'https://apigw.getduna.com/merchants/transactions/orders/{orden_token}/installments?bin={card_bin}'
--header 'x-api-key: {x_api_key}'
--header 'Authorization: Bearer {merchant_auth_token}'curl --location --request GET 'https://apigw.getduna.com/merchants/transactions/orders/{orden_token}/installments?bin={card_bin}'
--header 'x-api-key: {x_api_key}'
--header 'Authorization: Bearer {merchant_auth_token}'import requests
response = requests.request(
"GET",
"https://apigw.getduna.com/merchants/transactions/orders/{orden_token}/installments?bin={card_bin}",
headers={
"x-api-key": "{x_api_key}",
"Authorization": "Bearer {merchant_auth_token}"
},
)
response.raise_for_status()
data = response.json()<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://apigw.getduna.com/merchants/transactions/orders/{orden_token}/installments?bin={card_bin}",
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"x-api-key: {x_api_key}",
"Authorization: Bearer {merchant_auth_token}"
]
]);
$response = curl_exec($curl);
curl_close($curl);import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class Example {
public static void main(String[] args) throws Exception {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://apigw.getduna.com/merchants/transactions/orders/{orden_token}/installments?bin={card_bin}"))
.header("x-api-key", "{x_api_key}")
.header("Authorization", "Bearer {merchant_auth_token}")
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
HttpResponse<String> response = HttpClient.newHttpClient().send(
request, HttpResponse.BodyHandlers.ofString()
);
System.out.println(response.body());
}
}package main
import (
"fmt"
"io"
"net/http"
)
func main() {
request, err := http.NewRequest("GET", "https://apigw.getduna.com/merchants/transactions/orders/{orden_token}/installments?bin={card_bin}", nil)
if err != nil { panic(err) }
request.Header.Set("x-api-key", "{x_api_key}")
request.Header.Set("Authorization", "Bearer {merchant_auth_token}")
response, err := http.DefaultClient.Do(request)
if err != nil { panic(err) }
defer response.Body.Close()
body, _ := io.ReadAll(response.Body)
fmt.Println(string(body))
}- Select an installment option.
- Make the purchase with the installment option.
curl --location --request POST 'https://api.sandbox.deuna.io/v2/merchants/orders/purchase' \
--header 'x-api-key: {x_api_key}' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {user_auth_token}' \
--data-raw '{
"order_token": "{order_token}",
"payer_info": {
"email": "test123@testuser.com"
},
"payment_source": {
"method_type": "credit_card",
"processor": "{processor_name}",
"card_info": {
"expiry_month": "11",
"expiry_year": "2028",
"card_holder": "DEUNA Developers",
"card_holder_dni": "185396924",
"card_number": "4111111111111111",
"card_cvv": "123",
"address1": "Vergara 548",
"zip": "001100",
"city": "Santiago",
"state": "RM",
"country": "CL",
"phone": "12345755",
"installment": {
"plan_option_id": "{plan_option_id}"
}
}
}
}'curl --location --request POST 'https://api.sandbox.deuna.io/v2/merchants/orders/purchase' \
--header 'x-api-key: {x_api_key}' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {user_auth_token}' \
--data-raw '{
"order_token": "{order_token}",
"payer_info": {
"email": "test123@testuser.com"
},
"payment_source": {
"method_type": "credit_card",
"processor": "{processor_name}",
"card_info": {
"expiry_month": "11",
"expiry_year": "2028",
"card_holder": "DEUNA Developers",
"card_holder_dni": "185396924",
"card_number": "4111111111111111",
"card_cvv": "123",
"address1": "Vergara 548",
"zip": "001100",
"city": "Santiago",
"state": "RM",
"country": "CL",
"phone": "12345755",
"installment": {
"plan_option_id": "{plan_option_id}"
}
}
}
}'import requests
response = requests.request(
"POST",
"https://api.sandbox.deuna.io/v2/merchants/orders/purchase",
headers={
"x-api-key": "{x_api_key}",
"Content-Type": "application/json",
"Authorization": "Bearer {user_auth_token}"
},
json={
"order_token": "{order_token}",
"payer_info": {
"email": "test123@testuser.com"
},
"payment_source": {
"method_type": "credit_card",
"processor": "{processor_name}",
"card_info": {
"expiry_month": "11",
"expiry_year": "2028",
"card_holder": "DEUNA Developers",
"card_holder_dni": "185396924",
"card_number": "4111111111111111",
"card_cvv": "123",
"address1": "Vergara 548",
"zip": "001100",
"city": "Santiago",
"state": "RM",
"country": "CL",
"phone": "12345755",
"installment": {
"plan_option_id": "{plan_option_id}"
}
}
}
},
)
response.raise_for_status()
data = response.json()<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.sandbox.deuna.io/v2/merchants/orders/purchase",
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"x-api-key: {x_api_key}",
"Content-Type: application/json",
"Authorization: Bearer {user_auth_token}"
],
CURLOPT_POSTFIELDS => json_encode([
"order_token" => "{order_token}",
"payer_info" => [
"email" => "test123@testuser.com"
],
"payment_source" => [
"method_type" => "credit_card",
"processor" => "{processor_name}",
"card_info" => [
"expiry_month" => "11",
"expiry_year" => "2028",
"card_holder" => "DEUNA Developers",
"card_holder_dni" => "185396924",
"card_number" => "4111111111111111",
"card_cvv" => "123",
"address1" => "Vergara 548",
"zip" => "001100",
"city" => "Santiago",
"state" => "RM",
"country" => "CL",
"phone" => "12345755",
"installment" => [
"plan_option_id" => "{plan_option_id}"
]
]
]
])
]);
$response = curl_exec($curl);
curl_close($curl);import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class Example {
public static void main(String[] args) throws Exception {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.sandbox.deuna.io/v2/merchants/orders/purchase"))
.header("x-api-key", "{x_api_key}")
.header("Content-Type", "application/json")
.header("Authorization", "Bearer {user_auth_token}")
.method("POST", HttpRequest.BodyPublishers.ofString("{\n \"order_token\": \"{order_token}\",\n \"payer_info\": {\n \"email\": \"test123@testuser.com\"\n },\n \"payment_source\": {\n \"method_type\": \"credit_card\",\n \"processor\": \"{processor_name}\",\n \"card_info\": {\n \"expiry_month\": \"11\",\n \"expiry_year\": \"2028\",\n \"card_holder\": \"DEUNA Developers\",\n \"card_holder_dni\": \"185396924\",\n \"card_number\": \"4111111111111111\",\n \"card_cvv\": \"123\",\n \"address1\": \"Vergara 548\",\n \"zip\": \"001100\",\n \"city\": \"Santiago\",\n \"state\": \"RM\",\n \"country\": \"CL\",\n \"phone\": \"12345755\",\n \"installment\": {\n \"plan_option_id\": \"{plan_option_id}\"\n }\n }\n }\n}"))
.build();
HttpResponse<String> response = HttpClient.newHttpClient().send(
request, HttpResponse.BodyHandlers.ofString()
);
System.out.println(response.body());
}
}package main
import (
"fmt"
"io"
"net/http"
"strings"
)
func main() {
request, err := http.NewRequest("POST", "https://api.sandbox.deuna.io/v2/merchants/orders/purchase", strings.NewReader("{\n \"order_token\": \"{order_token}\",\n \"payer_info\": {\n \"email\": \"test123@testuser.com\"\n },\n \"payment_source\": {\n \"method_type\": \"credit_card\",\n \"processor\": \"{processor_name}\",\n \"card_info\": {\n \"expiry_month\": \"11\",\n \"expiry_year\": \"2028\",\n \"card_holder\": \"DEUNA Developers\",\n \"card_holder_dni\": \"185396924\",\n \"card_number\": \"4111111111111111\",\n \"card_cvv\": \"123\",\n \"address1\": \"Vergara 548\",\n \"zip\": \"001100\",\n \"city\": \"Santiago\",\n \"state\": \"RM\",\n \"country\": \"CL\",\n \"phone\": \"12345755\",\n \"installment\": {\n \"plan_option_id\": \"{plan_option_id}\"\n }\n }\n }\n}"))
if err != nil { panic(err) }
request.Header.Set("x-api-key", "{x_api_key}")
request.Header.Set("Content-Type", "application/json")
request.Header.Set("Authorization", "Bearer {user_auth_token}")
response, err := http.DefaultClient.Do(request)
if err != nil { panic(err) }
defer response.Body.Close()
body, _ := io.ReadAll(response.Body)
fmt.Println(string(body))
}Test MCI#
To create the campaign it is necessary to:
- Be authenticated as merchant.
- Configure the processors that offer installments.
- The processors must have the id and name of the DEUNA ecosystem.
Example
{
"processors": [
{
"id": 39,
"name": "mercadopago"
}
]
}The same campaign must have its options with "installments_type": "MCI".
Example
{
"options": [
{
"installments": 3,
"installments_type": "MCI",
"currency": "MXN",
"card_branch": [
...
]
}
]
}Within card_branch, the "name" can be:
visamastercardamex
Expected response codes
- 201: Successful campaign creation.
- 401: Not authorized to create the campaign.
- 400: Invalid request.
To create merchant payment processors, you must:
- Authenticate as a merchant.
- Have the necessary credentials to perform installment transactions.
Installments with VTEX
Confirm MCI availability for the required VTEX store with your DEUNA TAM before testing installment retrieval.
The TAM will confirm the eligible store, campaign, processor connections, and whether the VTEX-provided installment values or the DEUNA campaign calculation is authoritative.
If you require any additional configuration to set up an endpoint with specific credentials for VTEX, you must create an external endpoint.
Expected response codes
- 200: Successful creation of external endpoint.
- 401: Not authorized to create external endpoint.
- 400: Invalid request.
Query installments
Query the installment plan with the card BIN after creating an order.
Expected response codes
- 200: Successful retrieval of installments plan.
- 401: Not authorized to create merchant payment processor.
- 400: Invalid request.
- 404: No merchant payment processors configured correctly.
Test cards
Provide all test card data from the processor.
In general the data is:
"card_number""card_cvv""expiry_year""expiry_month""card_holder"
Expected response codes
- 200: Successful transaction.
- 401: User not authorized to make the purchase.
- 400: Invalid request, such as the merchant not having enabled merchant payment processors.
- 422: The transaction could not be performed because the processor declined it.