Simulate installments, formalize the loan, sign the contract, and track through to disbursement.
From the moment the customer has a credit offer available, the flow goes through three steps on your platform (simulate, create, sign) while Dinie processes each phase and notifies via webhooks.
| Status | Description |
|---|---|
available | Offer ready for simulation |
awaiting_signatures | Loan created, awaiting CCB contract signatures |
processing | All signatures collected, processing disbursement |
active | Funds deposited, payment cycle started |
finished | Loan fully paid |
cancelled | Loan cancelled |
error | Processing error |
When the customer opens the app to take out a loan, retrieve the available offers:
const offers = await client.customers.listCreditOffers(
"cust_550e8400...",
{ status: "available" }
);
const offer = offers.data[0];
console.log(`R$ ${offer.approvedAmount} at ${offer.interestRate}% per month`);Simulate a loan scenario by providing the desired amount and number of installments. Each call returns a simulation with the calculated terms. The customer can simulate as many times as they want -- only the latest simulation is valid for loan origination.
const simulation = await client.creditOffers.simulate(offer.id, {
requestedAmount: 25000.00,
installmentCount: 4,
});
console.log(`${simulation.installmentCount}x of R$ ${simulation.installmentAmount}`);
console.log(`Total: R$ ${simulation.totalAmount} | CET: ${simulation.cetRate}% p.a.`);
console.log(`First due date: ${simulation.firstDueDate}`);The simulation returns installment_amount, total_amount, requested_amount (requested value), principal_amount, iof_amount, fee_amount, interest_rate, and cet_rate (annualized Total Effective Cost (CET)).
Info: The
installment_countfield depends on the offer. Some offers allow the customer to choose between different terms -- in that case, you can simulate with different values. If the offer defines a fixed term, use theinstallmentsreturned in the offer.
Tip: Monetary values and rates are JSON numbers (e.g.,
25000.00), both in the SDKs and via HTTP directly.
When the customer chooses the desired simulation, formalize the loan. The installment_count, installment_amount, and first_due_date fields must match the referenced simulation exactly.
const loan = await client.loans.create({
creditOfferId: offer.id,
simulationId: simulation.id,
installmentCount: simulation.installmentCount,
installmentAmount: simulation.installmentAmount,
firstDueDate: simulation.firstDueDate,
});
console.log(loan.id); // "ln_550e8400..."
console.log(loan.status); // "awaiting_signatures"Warning: If
installment_count,installment_amount, orfirst_due_datedo not match the simulation values, the request is rejected with asimulation_mismatcherror. Always use the exact values returned by the simulation.
When the loan is created, the signing_url is immediately available in the response. Present it to the customer:
// After creating the loan, the signing_url is available immediately:
const loan = await client.loans.create({ /* ... */ });
if (loan.signingUrl) {
// Open loan.signingUrl in the customer's browser
// The customer signs the CCB contract directly on this page
}After all signatures are collected, the loan advances automatically: awaiting_signatures -> processing -> active. You receive webhooks at each stage.
switch (event.type) {
case "loan.processing":
notifyCustomer(event.data.id,
"All signatures collected! We are processing the transfer.");
break;
case "loan.active":
notifyCustomer(event.data.id,
`R$ ${event.data.requested_amount} has been deposited into your account!`);
break;
}When your integration is working in sandbox, follow the Going to Production checklist.