Private-Merchant-Id). Never expose it in client-side or frontend code — always call the token endpoint from your backend.| Mode | How it works |
|---|---|
| Scheduled | Kushki charges the card automatically based on the periodicity you configure (daily, monthly, yearly, etc.) |
| One-click (on-demand) | You trigger each charge manually via POST /subscriptions/v1/card/{subscriptionId}. Use periodicity: "custom" when creating the subscription. |
POST /subscriptions/v1/card/tokens from your backend with the customer's card data. Returns a one-time token.{
"card": {
"name": "Luis García",
"number": "4242424242424242",
"expiryMonth": "08",
"expiryYear": "28",
"cvv": "123"
},
"currency": "PEN"
}⚠️ Token expiry: Use the token immediately to create the subscription. Do not store it.
POST /subscriptions/v1/card with the token, plan details, and the recurring amount. The response returns a subscriptionId you store on your side.{
"token": "gV3ox6100000sAxClU033646vnnJsT83",
"planName": "Premium",
"periodicity": "monthly",
"startDate": "2026-06-01",
"contactDetails": {
"documentType": "DNI",
"documentNumber": "12345678",
"firstName": "Luis",
"lastName": "García",
"email": "user@example.com",
"phoneNumber": "+51912345678"
},
"amount": {
"subtotalIva": 0,
"subtotalIva0": 99.90,
"ice": 0,
"iva": 0,
"currency": "PEN"
}
}POST /subscriptions/v1/card/{subscriptionId} whenever you want to charge the customer.{
"amount": {
"subtotalIva": 0,
"subtotalIva0": 99.90,
"ice": 0,
"iva": 0,
"currency": "PEN"
},
"contactDetails": {
"documentType": "DNI",
"documentNumber": "12345678",
"firstName": "Luis",
"lastName": "García",
"email": "user@example.com",
"phoneNumber": "+51912345678"
}
}ticketNumber and transactionReference. Use "fullResponse": "v2" to get the full approval details.💡 Sandbox OTP: If OTP validation is triggered in sandbox, use 555for both PEN and USD.
| Value | Frequency |
|---|---|
daily | Every day |
weekly | Every week |
biweekly | Every two weeks |
monthly | Once a month |
threefortnights | Every three fortnights |
bimonthly | Every two months |
quarterly | Every three months |
fourmonths | Every four months |
halfYearly | Every six months |
yearly | Once a year |
custom | On-demand — you trigger each charge manually |
| Value | Description |
|---|---|
DNI | Documento Nacional de Identidad 🇵🇪 |
CE | Carné de Extranjería 🇵🇪 |
PAS | Pasaporte 🇵🇪 |
RUC | Registro Único de Contribuyentes 🇵🇪 |
deferred object in the charge request:months as a top-level field (not inside deferred):{
"amount": {
"subtotalIva": 0,
"subtotalIva0": 300.00,
"iva": 0,
"ice": 0,
"currency": "PEN"
},
"months": 3,
"contactDetails": {
"documentType": "DNI",
"documentNumber": "12345678",
"firstName": "Luis",
"lastName": "García",
"email": "user@example.com",
"phoneNumber": "+51912345678"
}
}| Operation | Endpoint | Description |
|---|---|---|
| Get info | GET /subscriptions/v1/card/search/{subscriptionId} | Retrieve subscription details, card info, and plan configuration |
| Update card | PUT /subscriptions/v1/card/{subscriptionId}/card | Replace the registered card with a new token |
| Update plan | PATCH /subscriptions/v1/card/{subscriptionId} | Modify amount, periodicity, or plan name |
| Add temp charge | PUT /subscriptions/v1/card/{subscriptionId} | Apply a one-time extra charge or discount on the next billing cycle |
| Cancel | DELETE /subscriptions/v1/card/{subscriptionId} | Cancel the subscription permanently |
POST /subscriptions/v1/card/{subscriptionId}/authorize — Reserves funds without charging. Returns a ticketNumber.POST /subscriptions/v1/card/{subscriptionId}/capture — Captures the reserved amount. Pass the ticketNumber from the authorization.{
"details": {
"amount": {
"subtotalIva": 0,
"subtotalIva0": 99.90,
"ice": 0,
"iva": 0,
"currency": "PEN"
},
"approvalCode": "000000",
"approvedTransactionAmount": 99.90,
"binInfo": {
"bindCard": "445652",
"cardCountry": "Peru",
"lastFourDigits": "9860",
"type": "credit"
},
"merchantName": "Mi Comercio Perú",
"paymentBrand": "Visa",
"responseCode": "000",
"responseText": "Transacción aprobada",
"transactionStatus": "APPROVAL",
"transactionType": "SALE",
"maskedCreditCard": "445652XXXXXX9860"
},
"ticketNumber": "028590538321035813"
}POST /subscriptions/v1/card/tokens), set isNetworkToken: true and include the networkToken object:| Field | Description |
|---|---|
deviceType | Type of device originating the tokenized transaction |
requestorId | Unique ID assigned to the token requestor by the card network |
source | Source of the token |
walletId | Digital wallet identifier — "01" for Apple Pay, "04" for other wallets |
authenticationLevel | Authentication level performed during token provisioning |
mvv | 10-digit Merchant Verification Value (Visa transactions only) |
⚠️ BETA: This feature is available in Peru and Chile only. Contact your Kushki account manager before enabling it.
https://api.kushkipagos.com/Got a suggestion on this documentation? Contact us.