Direct API
PayLater
Akulaku, Kredivo and Indodana: the buyer pays in instalments, you are paid in full.
Private preview. PayLater is open to selected accounts only. Want it on yours? Email halo@kasera.id. Until it is enabled, a create naming one of these codes is refused 422 payment_method_unavailable.
The buyer leaves your page, signs in to the lender, picks a tenor and is approved there, then comes back to your return_url. You receive the full amount like any other payment; the instalments are between the buyer and the lender.
Integration steps
- Create the payment request.
- Send the buyer to payment.redirect_url.
- Acknowledge the payment — the payment.paid webhook.
- Check status when you need certainty: GET /v1/transactions/:id.
What each lender needs
| Field | akulaku | kredivo | indodana |
|---|---|---|---|
customer.name | ✓ | ✓ | ✓ |
customer.email | ✓ | ✓ | ✓ |
customer.phone | ✓ | ✓ | ✓ |
customer.address | — | ✓ | ✓ |
customer.phonemust have 10 to 15 digits, country code included.081234567890and+6281234567890both work.customer.addressisline,cityandpostal_code. It counts only when all three are there; half an address is treated as no address.- On Direct API a missing or unusable field is refused
422 customer_required, with the field named. On Checkout you may leave them out and the page asks the buyer.
{
"error": {
"code": "customer_required",
"message": "...",
"fields": { "customer.address": "required" }
}
}1. Create the payment request
order_items is optional. The lender shows the buyer what they are paying for, so send it when you have it; the items must add up to amount or the create is refused 422 order_items_mismatch. Left out, the lender sees one line with your description.
curl https://pay.kasera.id/v1/transactions \
-H "Authorization: Bearer kp_live_..." \
-H "Idempotency-Key: order-1234" \
-H "Content-Type: application/json" \
-d '{
"amount": 1500000,
"external_id": "ORD-1234",
"payment_methods": ["kredivo"],
"return_url": "https://toko.example/selesai",
"customer": {
"name": "Budi Santoso",
"email": "budi@example.com",
"phone": "081234567890",
"address": {
"line": "Jl. Sudirman No. 1",
"city": "Kota Administrasi Jakarta Selatan",
"postal_code": "12190"
}
},
"order_items": [
{ "name": "Kursi kerja", "price": 1500000, "quantity": 1 }
]
}'{
"id": "payreq_9b2f...",
"status": "pending",
"payment_method": "kredivo",
"payment": {
"type": "redirect",
"redirect_url": "https://sandbox.kredivo.com/...",
"display_name": "Kredivo"
},
"expires_at": "2026-10-01T13:00:00+07:00"
}2. Send the buyer there
Navigate the browser to payment.redirect_url — not an iframe, not a popup. If the lender declines the buyer, the payment ends failed; create a new one so they can pay another way.
3. Acknowledge the payment
The buyer coming back to return_url is navigation, not proof — a buyer who gave up at the lender returns to the same URL. Fulfil on the payment.paid webhook, or retrieve the request server-side before you show anything final.
Refunds
Kasera Pay does not refund PayLater payments. Returns follow your own store policy, settled with the buyer directly.