Installments (BNPL)
Split purchases into multiple payments with Buy Now, Pay Later (BNPL) installment plans.
How It Works
- Check customer eligibility for the purchase amount
- Create an installment plan with a saved card
- First payment is charged immediately
- Remaining payments are charged on schedule (weekly, biweekly, or monthly)
Check Eligibility
Before creating a plan, verify the customer is eligible:
JavaScript
javascript
const eligibility = await fyber.installments.checkEligibility({
customerId: 'cus_123',
amount: 50000, // $500.00
});
if (eligibility.eligible) {
console.log('Available options:', eligibility.availableOptions); // [3, 4, 6, 12]
console.log('Available credit:', eligibility.availableCredit / 100);
console.log('Min amount:', eligibility.minAmount / 100);
console.log('Max amount:', eligibility.maxAmount / 100);
}PHP
php
$eligibility = $fyber->installments->checkEligibility([
'customerId' => 'cus_123',
'amount' => 50000,
]);
if ($eligibility['eligible']) {
echo "Available options: " . implode(', ', $eligibility['availableOptions']);
}C#
csharp
var eligibility = await fyber.Installments.CheckEligibilityAsync(new CheckEligibilityRequest
{
CustomerId = "cus_123",
Amount = 50000
});
if (eligibility.Eligible)
{
Console.WriteLine($"Available options: {string.Join(", ", eligibility.AvailableOptions)}");
}Eligibility Response
| Field | Type | Description |
|---|---|---|
eligible | boolean | Whether customer can use installments |
availableCredit | integer | Available credit in cents |
availableOptions | array | Number of installments available (e.g., [3, 4, 6]) |
minAmount | integer | Minimum purchase amount |
maxAmount | integer | Maximum purchase amount |
reason | string | Reason if not eligible |
Create an Installment Plan
First, save a card using Hosted Checkout, then create the plan:
JavaScript
javascript
const plan = await fyber.installments.create({
customerId: 'cus_123',
tokenId: 'tok_123', // Saved card
totalAmount: 50000, // $500.00 total
installmentCount: 4, // 4 payments of $125
frequency: 'biweekly',
metadata: {
orderId: '1234',
},
});
console.log('First payment:', plan.installments[0].amount / 100);
console.log('Next payment date:', plan.installments[1].dueDate);PHP
php
$plan = $fyber->installments->create([
'customerId' => 'cus_123',
'tokenId' => 'tok_123',
'totalAmount' => 50000,
'installmentCount' => 4,
'frequency' => 'biweekly',
]);C#
csharp
var plan = await fyber.Installments.CreateAsync(new CreateInstallmentRequest
{
CustomerId = "cus_123",
TokenId = "tok_123",
TotalAmount = 50000,
InstallmentCount = 4,
Frequency = "biweekly"
});Installment Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
customerId | string | Yes | Customer ID |
tokenId | string | Yes | Saved card token |
totalAmount | integer | Yes | Total amount in cents |
installmentCount | integer | Yes | Number of payments |
frequency | string | Yes | Payment frequency |
metadata | object | No | Custom key-value data |
Frequencies
| Frequency | Description |
|---|---|
weekly | Every 7 days |
biweekly | Every 14 days |
monthly | Every 30 days |
Retrieve an Installment Plan
javascript
const plan = await fyber.installments.get('inst_123');
for (const installment of plan.installments) {
console.log(`${installment.number}: $${installment.amount / 100} - ${installment.status}`);
}List Installment Plans
javascript
const plans = await fyber.installments.list({
customerId: 'cus_123',
status: 'active',
limit: 20,
});Cancel an Installment Plan
javascript
await fyber.installments.cancel('inst_123');Canceling a plan does not refund payments already made. Only future payments are canceled.
Installment Stats
Get aggregate statistics:
javascript
const stats = await fyber.installments.stats();
console.log(`Active plans: ${stats.activeCount}`);
console.log(`Completed: ${stats.completedCount}`);
console.log(`Default rate: ${stats.defaultRate * 100}%`);
console.log(`Outstanding: $${stats.totalOutstanding / 100}`);Plan Object
json
{
"id": "inst_abc123",
"object": "installment_plan",
"status": "active",
"customerId": "cus_123",
"tokenId": "tok_456",
"totalAmount": 50000,
"installmentCount": 4,
"frequency": "biweekly",
"installments": [
{
"number": 1,
"amount": 12500,
"dueDate": "2024-01-15",
"status": "paid",
"paidAt": "2024-01-15T10:30:00Z"
},
{
"number": 2,
"amount": 12500,
"dueDate": "2024-01-29",
"status": "pending"
},
{
"number": 3,
"amount": 12500,
"dueDate": "2024-02-12",
"status": "pending"
},
{
"number": 4,
"amount": 12500,
"dueDate": "2024-02-26",
"status": "pending"
}
],
"metadata": {
"orderId": "1234"
},
"createdAt": "2024-01-15T10:30:00Z"
}Plan Status
| Status | Description |
|---|---|
active | Plan is active, payments ongoing |
completed | All payments made successfully |
canceled | Plan was canceled |
defaulted | Customer missed payments |
Webhooks
Listen for installment events:
javascript
switch (event.type) {
case 'installment.plan_created':
// Plan activated, first payment charged
fulfillOrder(event.data.object.metadata.orderId);
break;
case 'installment.payment_succeeded':
// Scheduled payment completed
break;
case 'installment.payment_failed':
// Payment failed, may retry
notifyCustomer(event.data.object.customerId);
break;
case 'installment.plan_completed':
// All payments completed
break;
case 'installment.plan_defaulted':
// Customer defaulted on payments
handleDefault(event.data.object);
break;
}Handling Defaults
When an installment payment fails:
- Fyber retries automatically (up to 3 times)
- You receive
installment.payment_failedwebhook - If all retries fail, plan moves to
defaulted - You receive
installment.plan_defaultedwebhook
Consider contacting the customer to update their payment method.