Skip to content
Last updated

Simulation and Loan Origination

Simulate installments, formalize the loan, sign the contract, and track through to disbursement.

Flow Overview

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.

Credit lifecycle

StatusDescription
availableOffer ready for simulation
awaiting_signaturesLoan created, awaiting CCB contract signatures
processingAll signatures collected, processing disbursement
activeFunds deposited, payment cycle started
finishedLoan fully paid
cancelledLoan cancelled
errorProcessing error

List Offers

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 Terms

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_count field 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 the installments returned in the offer.

Tip: Monetary values and rates are JSON numbers (e.g., 25000.00), both in the SDKs and via HTTP directly.

Create a Loan

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, or first_due_date do not match the simulation values, the request is rejected with a simulation_mismatch error. Always use the exact values returned by the simulation.

Sign the Contract

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;
}

Next Step

When your integration is working in sandbox, follow the Going to Production checklist.