# 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](/assets/credit-lifecycle.ab588fddf9f880344ac64e75f4eb8abf8c80bc732df82fd2f2637eb3fa4a7045.53e9d79f.svg) | Status | Description | | --- | --- | | `available` | Offer ready for simulation | | `processing` | Loan created, generating contract | | `awaiting_signatures` | CCB contract ready for signing | | `signed` | Contract signed, awaiting disbursement | | `disbursing` | Transfer in progress | | `active` | Funds deposited, payment cycle started | ## List Offers When the customer opens the app to take out a loan, retrieve the available offers: ```typescript Node.js 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`); ``` ```ruby Ruby offers = client.customers.list_credit_offers( "cust_550e8400...", status: "available" ) offer = offers.data.first puts "R$ #{offer.approved_amount} at #{offer.interest_rate}% per month" ``` ```python Python offers = client.customers.list_credit_offers( "cust_550e8400...", status="available", ) offer = offers.data[0] print(f"R$ {offer.approved_amount} at {offer.interest_rate}% per month") ``` ```bash cURL curl "https://sandbox.api.dinie.com.br/v3/customers/cust_550e8400.../credit-offers?status=available" \ -H "Authorization: Bearer dinie_at_..." ``` ## 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. ```typescript Node.js const simulation = await client.creditOffers.simulate(offer.id, { requestedAmount: "25000.00", installmentCount: 12, }); console.log(`${simulation.numberOfInstallments}x of R$ ${simulation.installmentsValue}`); console.log(`Total: R$ ${simulation.totalLoanAmount} | CET: ${simulation.cetPercentage}% p.a.`); console.log(`First due date: ${simulation.firstDueDate}`); ``` ```ruby Ruby simulation = client.credit_offers.simulate( offer.id, requested_amount: "25000.00", installment_count: 12 ) puts "#{simulation.number_of_installments}x of R$ #{simulation.installments_value}" puts "Total: R$ #{simulation.total_loan_amount} | CET: #{simulation.cet_percentage}% p.a." puts "First due date: #{simulation.first_due_date}" ``` ```python Python simulation = client.credit_offers.simulate( offer.id, requested_amount="25000.00", installment_count=12, ) print(f"{simulation.number_of_installments}x of R$ {simulation.installments_value}") print(f"Total: R$ {simulation.total_loan_amount} | CET: {simulation.cet_percentage}% p.a.") print(f"First due date: {simulation.first_due_date}") ``` ```bash cURL curl -X POST "https://sandbox.api.dinie.com.br/v3/credit-offers/${OFFER_ID}/simulations" \ -H "Authorization: Bearer dinie_at_..." \ -H "Content-Type: application/json" \ -d '{ "requested_amount": "25000.00", "installment_count": 12 }' ``` The simulation returns `installments_value`, `total_loan_amount`, `amount` (net amount), `iof_amount`, `fees_amount`, `interest_percentage`, and `cet_percentage` (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:** The SDKs convert monetary values to the language's numeric types. When using HTTP directly, values are strings with 2 decimal places (e.g., `"25000.00"`). ## Create a Loan When the customer chooses the desired simulation, formalize the loan. The `installments`, `installments_value`, and `first_due_date` fields must match the referenced simulation exactly. ```typescript Node.js const loan = await client.loans.create({ creditOfferId: offer.id, simulationId: simulation.id, installments: simulation.numberOfInstallments, installmentsValue: simulation.installmentsValue, firstDueDate: simulation.firstDueDate, }); console.log(loan.id); // "ln_550e8400..." console.log(loan.status); // "processing" ``` ```ruby Ruby loan = client.loans.create( credit_offer_id: offer.id, simulation_id: simulation.id, installments: simulation.number_of_installments, installments_value: simulation.installments_value, first_due_date: simulation.first_due_date ) puts loan.id # "ln_550e8400..." puts loan.status # "processing" ``` ```python Python loan = client.loans.create( credit_offer_id=offer.id, simulation_id=simulation.id, installments=simulation.number_of_installments, installments_value=simulation.installments_value, first_due_date=simulation.first_due_date, ) print(loan.id) # "ln_550e8400..." print(loan.status) # "processing" ``` ```bash cURL curl -X POST https://sandbox.api.dinie.com.br/v3/loans \ -H "Authorization: Bearer dinie_at_..." \ -H "Content-Type: application/json" \ -H "Idempotency-Key: create-loan-${OFFER_ID}" \ -d '{ "credit_offer_id": "co_550e8400...", "simulation_id": "sim_550e8400...", "installments": 12, "installments_value": "2291.67", "first_due_date": "2026-04-03" }' ``` > **Warning:** If `installments`, `installments_value`, 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 reaches `awaiting_signatures`, the signing URL is ready. Present it to the customer: ```typescript Node.js // In your webhook handler, upon receiving loan.awaiting_signatures: const loan = await client.loans.retrieve(event.data.id); if (loan.signingUrl) { // Open loan.signingUrl in the customer's browser // The customer signs the CCB contract directly on this page } ``` ```ruby Ruby # In your webhook handler, upon receiving loan.awaiting_signatures: loan = client.loans.retrieve(event.data["id"]) if loan.signing_url # Open loan.signing_url in the customer's browser # The customer signs the CCB contract directly on this page end ``` ```python Python # In your webhook handler, upon receiving loan.awaiting_signatures: loan = client.loans.retrieve(event.data["id"]) if loan.signing_url: # Open loan.signing_url in the customer's browser # The customer signs the CCB contract directly on this page pass ``` ```bash cURL # Retrieve the loan after receiving the loan.awaiting_signatures webhook curl "https://sandbox.api.dinie.com.br/v3/loans/${LOAN_ID}" \ -H "Authorization: Bearer dinie_at_..." # The response includes signing_url to redirect the customer ``` After signing, the loan advances automatically: `signed` -> `disbursing` -> `active`. You receive webhooks at each stage. ```typescript Node.js switch (event.type) { case "loan.signed": notifyCustomer(event.data.external_id, "Contract signed! We are processing the transfer."); break; case "loan.active": notifyCustomer(event.data.external_id, `R$ ${event.data.net_amount} has been deposited into your account!`); break; } ``` ```ruby Ruby case event["type"] when "loan.signed" notify_customer(event.dig("data", "external_id"), "Contract signed! We are processing the transfer.") when "loan.active" notify_customer(event.dig("data", "external_id"), "R$ #{event.dig('data', 'net_amount')} has been deposited into your account!") end ``` ```python Python match event["type"]: case "loan.signed": notify_customer(event["data"]["external_id"], "Contract signed! We are processing the transfer.") case "loan.active": notify_customer(event["data"]["external_id"], f"R$ {event['data']['net_amount']} has been deposited into your account!") ``` ```bash cURL # Webhooks are received via POST at your configured endpoint. # Example loan.signed payload: # { # "type": "loan.signed", # "data": { # "id": "ln_550e8400...", # "external_id": "partner-ref-123", # "status": "signed" # } # } ``` ## Next Step When your integration is working in sandbox, follow the [Going to Production](/guides/going-to-production) checklist.