Envía dinero a una tarjeta

Sending funds to cards involves processing payments to a debit or credit card. This can be done in two ways: Through a 100% API direct integration (only available for PCI-compliant merchants). By performing prior card tokenization using the Hosted Fields library. The flow you will integrate is as follows:

En Flujo pago push funds to a card

Direct Integration (100% API)

1. (Optional) Obtain a one-time or subscription payment token

Before requesting the transfer of funds, you can tokenize the recipient’s card. This can be done through the following services:

Note: If your merchant not PCI Compliance, you must use Kushki JS Hosted Fields to obtain a token from the front-end without handling sensitive data.

2. Request the Transfer of Funds to a Card

To send funds to a card, you must provide the card and recipient details, the amount, and the clientTransactionId , a unique identifier on your side. Check here for the full structure in our API reference.

Examples

  • Javascript
  • Python
  • PHP
const axios = require("axios");
const options = {
method: 'POST',
url: 'https://api-uat.kushkipagos.com/payouts/card/v1/pushFunds',
headers: {
'Private-Merchant-Id': 'YOUR_PRIVATE_MERCHANT_ID',
'Content-Type': 'application/json'
},
data: {
"card": {
"name": "John Doe",
"number": "5102589999999913"
},
"clientTransactionId": "1234567890",
"amount": {
"currency": "CLP",
"totalAmount": 0.25
},
"fullResponse": "v2",
"paymentType": "GMR",
"metadata": {
"key1": "key1"
},
"recipient": {
"address": "Lima Callse S/N",
"city": "Chicago",
"country": "PER",
"zipCode": "63368"
}
}
};
axios.request(options)
.then(response => console.log(response.data))
.catch(error => console.error("Error:", error));
import requests
import json
url = "https://api-uat.kushkipagos.com/payouts/card/v1/pushFunds"
payload = {
"card": {
"name": "John Doe",
"number": "5102589999999913"
},
"clientTransactionId": "1234567890",
"amount": {
"currency": "CLP",
"totalAmount": 0.25
},
"fullResponse": "v2",
"paymentType": "GMR",
"metadata": {
"key1": "key1"
},
"recipient": {
"address": "Lima Callse S/N",
"city": "Chicago",
"country": "PER",
"zipCode": "63368"
}
}
headers = {
'Content-Type': 'application/json',
'Private-Merchant-Id': 'YOUR_PRIVATE_MERCHANT_ID' # Reemplaza con tu ID
}
response = requests.post(url, data=json.dumps(payload), headers=headers)
print(response.status_code)
print(response.json())
<?php
$url = "https://api-uat.kushkipagos.com/payouts/card/v1/pushFunds";
$data = [
"card" => [
"name" => "John Doe",
"number" => "5102589999999913"
],
"clientTransactionId" => "1234567890",
"amount" => [
"currency" => "CLP",
"totalAmount" => 0.25
],
"fullResponse" => "v2",
"paymentType" => "GMR",
"metadata" => [
"key1" => "key1"
],
"recipient" => [
"address" => "Lima Callse S/N",
"city" => "Chicago",
"country" => "PER",
"zipCode" => "63368"
]
];
$payload = json_encode($data);
$headers = [
"Private-Merchant-Id: YOUR_PRIVATE_MERCHANT_ID",
"Content-Type: application/json"
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode == 200) {
echo "Success: " . $response;
} else {
echo "Error: HTTP Code " . $httpCode . " - " . $response;
}
?>

If the request is successful, you will receive the following response:

{
"responseCode": "00",
"responseText": "Approved and completed successfully",
"ticketNumber": "XXXXXXX",
"transactionReference": "XXXXXXXX",
"otherDetails": {}
}

In case of an error, you will receive a response containing the code field and the details object, where you can check the reason for the rejection.

{
"code": "E001",
"details": {
"Origin": "PushFundsService",
"Message": "paymentType: must be a valid value."
}
}

3. Check the Transaction Status

You can verify the status of a transaction in two ways:

1. Check via the API Get Transaction Status You only need to send the transactionReference or clientTransactionId. The response will include the following information:

{
"amount": 13,
"processor": {
"code": "00",
"message": "Approved and completed successfully"
},
"ticketNumber": "951738256068368362",
"transactionReference": "763274a1-b47b-493f-934f-047801cc04a0",
"transactionStatus": "APPROVAL"
}

2. Webhook Configuration You can set up a webhook to receive notifications for approved or declined transactions. Check here for the full webhook structure.

Integration via Kushki.js Hosted Fields

With Hosted Fields, you can securely collect card and cardholder information through fields hosted on Kushki’s infrastructure. It returns a payout token that allows you to continue with the payment flow from the back-end

With the implementation of this library, you can obtain two types of tokens:

  • One-time payment token:: for making a single payment to a card
  • Subscription token: can be reused for multiple payments to a credit or debit card. You will receive a suscriptionId instead of a token.

1. Import Kushki.js Hosted Fields into your application

Option 1 - CDN

Import the Kushki.js Hosted Fields library into your application via a <script> tag within the <body> tag. Once imported, you will be able to access the resources described later to create a card payout flow with Kushki..

You need to import both the kushki.min.js library (which contains the code necessary to store your merchant credentials) and the card.min.js library (which contains the functionality needed for the card payout flow).

<script src="https://cdn.kushkipagos.com/js/latest/kushki.min.js"></script>
<script src="https://cdn.kushkipagos.com/js/latest/card.min.js"></script>

Option 2 - NPM

Install the Kushki.js Hosted Fields library as an npm package inside your application with the following code:

npm install --save @kushki/js-sdk

Option 3 - YARN

yarn install @kushki/js-sdk

Create an instance of KushkiOptions

To use the Kushki.js Hosted Fields library, you first need to create an instance of KushkiOptionswhich allows you to declare the merchant’s public key and select the environment (test or production) using the init() method.

Add the following code to your application:

import { IKushki, init, KushkiError , KushkiOptions} from "@kushki/js-sdk";
const kushkiOptions : KushkiOptions = {
publicCredentialId: '<public-credential-id>', // This corresponds to the public credential of the merchant
inTest: true
};
const buildKushkiInstance = async () => {
try {
const kushkiInstance : Ikushki = await init(kushkiOptions);
} catch (e: KushkiError) {
console.error(e.message);
}
}

Check the reference for more information about the KushkiOptions instance.

2. Initialize the Form on the Front-End

Follow the steps below to render server-side fields on your site. This way, your users will be able to send money to cards.

Step 1. Define containers for the server-side fields.

Before calling the initCardPayoutToken(), method, it is required to place the necessary elements to render each field server-side.

<!DOCTYPE html>
<html lang="en">
<body>
<form>
<div id="cardHolderName_id"/>
<div id="cardNumber_id"/>
<div id="isSubscription_id"/>
</form>
</body>
</html>

Step 2. Create an instance of CardPayoutOptions with the transaction information

import { IKushki, init, KushkiError } from "@kushki/js-sdk";
import {
CardPayoutOptions,
ICardPayouts,
initCardPayoutToken
} from "@kushki/js-sdk/CardPayouts";
const kushkiOptions : KushkiOptions = {
publicCredentialId: 'public-merchant-id',
inTest: true
};
const options : CardPayoutOptions = {
fields: {
cardholderName: {
selector: "cardholderName_id"
},
cardNumber: {
selector: "cardNumber_id"
},
isSubscription: {
selector: "isSubscription_id"
}
}
}

Render Server-Side Fields with the initCardPayoutToken Method

After creating an instance of kushkiOptions, you need to call the initCardPayoutToken() function to initialize an instance of ICardPayouts

const buildCardPayoutInstance = async () => {
try {
const kushkiInstance : Ikushki = await init(kushkiOptions);
const cardPayoutInstance: ICardPayouts = await initCardPayoutToken(kushkiInstance, options)
} catch (e: KushkiError) {
console.error(e.message);
}
}

Check the reference for the hosted fields library for more information on form initialization.

Styles

Follow the same methodology used in Estilos de Token de Tarjeta. he key difference is that these styles specifically apply to the fields required for this tokenization method. Also, note that the isSubscription field is a checkbox, so specific styles must be applied for this type of input. For more details, click here.

Events

Use the same approach as in Eventos de Token de Tarjeta. However, these events apply to the specific fields required for this tokenization method. For more details, clic here.

3. Request a Card Payout Token

To obtain a card payment token, call th requestCardPayoutToken method on the previously initialized ICardPayouts instance. This method will also validate whether the fields contain valid values; if not, it will throw an exception.

This method returns a CardPayoutTokenResponse, object, which you must send to your backend to proceed with the fund transfer.

4. Configure Your Backend

The backend is responsible for receiving the token (or subscription ID) obtained from your front-end and initiating the payment process with Kushki.

When the user submits the card and cardholder details through the form you’ve specified, your front-end will return a token or a suscriptionId. With this token, you will need to call our Push Funds endpoints to process the payment to the card.

One-Time Payment Token

If it is a one-time payment token, you should call the payouts/card/v1/pushFunds. service. Make sure you include the token in the body, along with the amount and other necessary information.

  • Javascript
  • Python
  • PHP
const fetch = require('node-fetch'); // Si usas Node.js, instala con: npm install node-fetch
const url = "https://api-uat.kushkipagos.com/payouts/card/v1/pushFunds";
const headers = {
"Private-Merchant-Id": "your-private-merchat-id",
"Content-Type": "application/json"
};
const data = {
token: "74378g3yg4387437878387",
amount: {
currency: "PEN",
totalAmount: 19
},
clientTransactionId: crypto.randomUUID(), // Si usas Node.js 16+ o en navegador moderno
paymentType: "OG",
metadata: {
key1: "key1"
},
recipient: {
address: "Lima Callse S/N",
city: "Ambato",
zipCode: "123456"
},
fullResponse: "v2",
webhooks: [
{
events: ["approvedTransaction"],
urls: ["https://webhook.site/3aa8868d-43c8-4fc0-bcbf-a96f7e89a371"],
headers: [
{
label: "foo",
value: "bar"
}
]
}
]
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(data)
})
.then(response => response.json())
.then(responseData => console.log(responseData))
.catch(error => console.error("Error:", error));
import requests
import uuid
url = "https://api-uat.kushkipagos.com/payouts/card/v1/pushFunds"
headers = {
"Private-Merchant-Id": "your-private-merchat-id",
"Content-Type": "application/json"
}
data = {
"token": "74378g3yg4387437878387",
"amount": {
"currency": "PEN",
"totalAmount": 19
},
"clientTransactionId": str(uuid.uuid4()),
"paymentType": "OG",
"metadata": {
"key1": "key1"
},
"recipient": {
"address": "Lima Callse S/N",
"city": "Ambato",
"zipCode": "123456"
},
"fullResponse": "v2",
"webhooks": [
{
"events": ["approvedTransaction"],
"urls": ["https://webhook.site/3aa8868d-43c8-4fc0-bcbf-a96f7e89a371"],
"headers": [
{
"label": "foo",
"value": "bar"
}
]
}
]
}
response = requests.post(url, json=data, headers=headers)
print(response.json())
<?php
$url = "https://api-uat.kushkipagos.com/payouts/card/v1/pushFunds";
$headers = [
"Private-Merchant-Id: your-private-merchat-id",
"Content-Type: application/json"
];
$data = [
"token" => "74378g3yg4387437878387",
"amount" => [
"currency" => "PEN",
"totalAmount" => 19
],
"clientTransactionId" => uniqid(),
"paymentType" => "OG",
"metadata" => [
"key1" => "key1"
],
"recipient" => [
"address" => "Lima Callse S/N",
"city" => "Ambato",
"zipCode" => "123456"
],
"fullResponse" => "v2",
"webhooks" => [
[
"events" => ["approvedTransaction"],
"urls" => ["https://webhook.site/3aa8868d-43c8-4fc0-bcbf-a96f7e89a371"],
"headers" => [
[
"label" => "foo",
"value" => "bar"
]
]
]
]
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
$response = curl_exec($ch);
curl_close($ch);
echo $response;

Subscription Token

If it is a subscription token, you should call the service /payouts/card/subscriptions/pushFunds/{subscriptionId}. Make sure to include the subscriptionId as a path parameter and in the body, provide the amount and other information as shown in the following example.

  • Javascript
  • Python
  • PHP
const fetch = require('node-fetch'); // Si usas Node.js, instala con: npm install node-fetch
const subscriptionId = "your-subscription-id"; // Reemplazar con el ID de la suscripción
const url = `https://api-uat.kushkipagos.com/payouts/card/subscriptions/pushFunds/${subscriptionId}`;
const headers = {
"Private-Merchant-Id": "your-private-merchat-id",
"Content-Type": "application/json"
};
const data = {
amount: {
currency: "PEN",
totalAmount: 0
},
clientTransactionId: crypto.randomUUID(), // Si usas Node.js 16+ o en navegador moderno
paymentType: "OG",
metadata: {
key1: "string"
},
recipient: {
address: "string",
city: "string",
zipCode: "string"
},
fullResponse: "v2",
webhooks: {
webhooks: [
{
events: ["approvedTransaction", "declinedTransaction"],
headers: [
{
label: "json",
value: "12"
}
],
urls: ["https://eof2hhkrta4ooo1.m.pipedream.net"]
}
]
}
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(data)
})
.then(response => response.json())
.then(responseData => console.log(responseData))
.catch(error => console.error("Error:", error));
import requests
import uuid
subscription_id = "your-subscription-id" # Reemplazar con el ID de la suscripción
url = f"https://api-uat.kushkipagos.com/payouts/card/subscriptions/pushFunds/{subscription_id}"
headers = {
"Private-Merchant-Id": "your-private-merchat-id",
"Content-Type": "application/json"
}
data = {
"amount": {
"currency": "PEN",
"totalAmount": 0
},
"clientTransactionId": str(uuid.uuid4()),
"paymentType": "OG",
"metadata": {
"key1": "string"
},
"recipient": {
"address": "string",
"city": "string",
"zipCode": "string"
},
"fullResponse": "v2",
"webhooks": {
"webhooks": [
{
"events": ["approvedTransaction", "declinedTransaction"],
"headers": [
{
"label": "json",
"value": "12"
}
],
"urls": ["https://eof2hhkrta4ooo1.m.pipedream.net"]
}
]
}
}
response = requests.post(url, json=data, headers=headers)
print(response.json())
<?php
$subscriptionId = "your-subscription-id"; // Reemplazar con el ID de la suscripción
$url = "https://api-uat.kushkipagos.com/payouts/card/subscriptions/pushFunds/$subscriptionId";
$headers = [
"Private-Merchant-Id: your-private-merchat-id",
"Content-Type: application/json"
];
$data = [
"amount" => [
"currency" => "PEN",
"totalAmount" => 0
],
"clientTransactionId" => uniqid(),
"paymentType" => "OG",
"metadata" => [
"key1" => "string"
],
"recipient" => [
"address" => "string",
"city" => "string",
"zipCode" => "string"
],
"fullResponse" => "v2",
"webhooks" => [
"webhooks" => [
[
"events" => ["approvedTransaction", "declinedTransaction"],
"headers" => [
[
"label" => "json",
"value" => "12"
]
],
"urls" => ["https://eof2hhkrta4ooo1.m.pipedream.net"]
]
]
]
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
$response = curl_exec($ch);
curl_close($ch);
echo $response;
Optional: Delete a Subscribed Card

This step allows you to remove a previously subscribed card by sending the subscriptionId. Once deleted, no further fund transfers can be made to that card. More information here.

Test Your Integration

There are test cards you can use in the UAT environment to ensure your integration is ready.

Visa

Valid Card

  • Declines: 4957030420210470
  • Approves: 4957030420210454

Invalid Card: 4104920120500001

Mastercard

  • Valid Card:5102589999999913

  • Invalid Card:5204750000000003

Simulate response scenarios using specific amounts

During testing, you can simulate different error scenarios by sending specific values in the totalAmount field. This applies to both the Push Funds operation and Push Funds in subscriptions.

The following table shows the behavior by brand and amount:

BrandAmount (totalAmount)ResponseCodeMessageNote
VISA10DECLINE501Transaction declined. Please contact your card issuer.
MASTERCARD10DECLINE501Transaction declined. Please contact your card issuer.
VISA20DECLINE504The entered card has been reported.
MASTERCARD20DECLINE514The entered card number is not valid.
VISA30DECLINE541This card has been reported as lost.
MASTERCARD30DECLINE543This card has been reported as stolen.
VISA40ERRORE027A timeout occurred when sending the request to the card network.Timeout with declined transaction
MASTERCARD40ERRORE027A timeout occurred when sending the request to the card network.Timeout with declined transaction
VISA50ERRORE027A timeout occurred when sending the request to the card network.Timeout with approved transaction
MASTERCARD50ERRORE027A timeout occurred when sending the request to the card network.Timeout with approved transaction