# Dinie API Embedded credit API for Dinie partners. Enables customer registration, credit offer management, loan origination, and event delivery via webhooks. Version: 2026-03-01 License: Proprietary ## Servers Production ``` https://api.dinie.com.br/v3 ``` Sandbox ``` https://sandbox.api.dinie.com.br/v3 ``` ## Security ### bearerAuth JWT token obtained via OAuth2 Client Credentials. Send `POST /auth/token` with your credentials (`client_id` and `client_secret`) in the `Authorization: Basic base64(client_id:client_secret)` header to receive an access token. Include the token in all requests: `Authorization: Bearer `. The token expires in 1 hour (3600s). Prefixes: `dinie_cs_live_` (production), `dinie_cs_test_` (sandbox). The returned token is prefixed with `dinie_at_`. Type: http Scheme: bearer Bearer Format: JWT ### oauth2 OAuth2 Client Credentials flow for obtaining access tokens. Use `client_id` and `client_secret` to authenticate. Type: oauth2 ## Download OpenAPI description [Dinie API](https://dinie.redocly.app/_bundle/apis/openapi.yaml) ## Authentication OAuth2 Client Credentials authentication and API key management. Each `client_id` / `client_secret` pair represents an access credential. Exchange the credentials for a JWT token via `POST /auth/token` and send the token as Bearer in all requests. The token expires in 1 hour. You can create multiple credentials for different environments and revoke them individually. ### Exchange credentials for an access token - [POST /auth/token](https://dinie.redocly.app/apis/openapi/authentication/createtoken.md): Authenticates the partner using the OAuth2 Client Credentials flow. Send client_id and client_secret in the Authorization header (Basic Auth) to receive a JWT token. The token expires in 1 hour and must be sent as a Bearer token in all other requests. The SDKs handle token retrieval and renewal automatically. ### Create a new API key - [POST /auth/credentials](https://dinie.redocly.app/apis/openapi/authentication/createcredential.md): Creates a new credential pair (client_id + client_secret) for the partner. The client_secret is displayed only once in the response — store it securely. Use multiple credentials to separate environments (production, staging, development) or distinct internal systems. ### List API keys - [GET /auth/credentials](https://dinie.redocly.app/apis/openapi/authentication/listcredentials.md): Returns all API keys for the authenticated partner, including name, creation date, and status (active or revoked). For security, the client_secret is not returned in this listing — it is displayed only at creation time via POST /auth/credentials. ### Revoke an API key - [DELETE /auth/credentials/{client_id}](https://dinie.redocly.app/apis/openapi/authentication/revokecredential.md): Revokes an API key immediately and irreversibly. After revocation, no new tokens can be issued with this credential. Tokens already issued before revocation remain valid until they expire (maximum 1 hour). Use this endpoint when decommissioning an environment or in case of credential leakage. ## Customers The **Customer** resource (`cust_`) represents a credit borrower on the platform. The lifecycle follows: registration → KYC document submission → review → activation. Two processes happen in parallel: - **Credit analysis** — starts automatically upon registration - **KYC verification** — the customer completes at their own pace ## Lifecycle ``` pending_kyc → under_review → active ``` | Status | Description | Next Step | |---|---|---| | `pending_kyc` | Registered, awaiting documents | Submit documents and biometrics | | `under_review` | Documents submitted, under review | Wait for `customer.active` webhook | | `active` | Approved and eligible for credit | Check credit offers | ## Example: Complete Registration ```ruby # 1. Register the customer customer = client.customers.create( cpf: "123.456.789-00", cnpj: "12.345.678/0001-90", name: "João Silva", email: "joao@example.com", phone: "+5511999999999", trading_name: "Loja do João", external_id: "partner-ref-123" ) # customer.id => "cust_550e8400..." # customer.status => "pending_kyc" # customer.kyc => list of pending documents # 2. Submit each required document customer.kyc.each do |item| next unless item.status == "pending" client.customers.upload_document(customer.id, type: item.type, file: File.open("docs/#{item.type}.pdf") ) end # 3. Start biometric capture session = client.customers.create_biometrics_session(customer.id) # Redirect the customer to session.session_url # 4. Wait for customer.active webhook # When received, the customer is ready for credit ``` ## Registration Idempotency Creating a customer with the same CPF/CNPJ and `external_id` returns the existing customer (`200 OK`). This allows safely retrying the request in case of timeout or network failure. The `409 Conflict` error only occurs when the `external_id` differs. ## Search ```ruby # By CPF customers = client.customers.list(cpf: "123.456.789-00") # By partner ID customers = client.customers.list(external_id: "partner-ref-123") ``` ## Webhooks | Event | When it fires | |---|---| | `customer.created` | Customer registered via API | | `customer.under_review` | Documents submitted, KYC review started | | `customer.kyc_updated` | KYC item status updated (approved, rejected, correction) | | `customer.active` | Customer approved — eligible for credit offers | ### Register a new customer - [POST /customers](https://dinie.redocly.app/apis/openapi/customers/createcustomer.md): Registers a new customer (borrower) for the authenticated partner. The customer is created with status pending_kyc and the response includes the kyc array with the documents and verifications required for this profile. The next step is to submit documents via POST /customers/{id}/documents. Idempotent behavior: if the same CPF/CNPJ with the same external_id already exists, the existing customer is returned (200 OK). The 409 error occurs only when the external_id differs for the same CPF/CNPJ. See also the customer.* webhooks to track registration progress. ### List customers - [GET /customers](https://dinie.redocly.app/apis/openapi/customers/listcustomers.md): Lists and searches customers for the authenticated partner. Supports filters by cpf, external_id, and status to locate specific customers. Pagination uses cursor-based approach with the starting_after (last item ID) and limit (max 100) parameters. ### Retrieve a customer - [GET /customers/{customer_id}](https://dinie.redocly.app/apis/openapi/customers/getcustomer.md): Returns the complete customer object, including registration data, current status, and the kyc array with the progress of each verification requirement. Use this endpoint to check the customer state at any time or after receiving a customer.kyc_updated webhook. ### Update customer data - [PATCH /customers/{customer_id}](https://dinie.redocly.app/apis/openapi/customers/updatecustomer.md): Updates customer data fields. The main use case is correcting information rejected during KYC verification (items with pending_correction status), such as email, phone, or registration data. The cpf and external_id fields cannot be updated after creation. After correction, the KYC analysis resumes automatically and you will receive customer.kyc_updated webhooks with the progress. ### Upload a KYC document - [POST /customers/{customer_id}/documents](https://dinie.redocly.app/apis/openapi/customers/uploaddocument.md): Uploads a KYC document for the customer via file upload (multipart/form-data). The document type must match one of the types listed in the customer's kyc array (e.g., ccmei, selfie, cnh). After upload, the document undergoes asynchronous review. Track the result via the customer.kyc_updated webhook or by retrieving the customer with GET /customers/{customer_id}. ### Generate a biometric capture session - [POST /customers/{customer_id}/biometrics](https://dinie.redocly.app/apis/openapi/customers/createbiometricssession.md): Creates a biometrics capture session for the customer and returns a temporary URL. The partner should redirect the customer to this URL or embed it in a webview within their application. Biometrics is a KYC requirement of type biometrics and its progress is tracked in the customer's kyc array. This is an action endpoint that returns 200 OK (not 201 Created). See the customer.kyc_updated webhook to track the completion of the capture. ### Customer created - [POST customer.created](https://dinie.redocly.app/apis/openapi/customers/oncustomercreated.md): Fires immediately after a new customer is registered via POST /customers. Includes the customer's full registration data with pending_kyc status. Use it to confirm registration receipt and start the KYC document collection flow. ### Customer under review - [POST customer.under_review](https://dinie.redocly.app/apis/openapi/customers/oncustomerunderreview.md): Fires when all required KYC documents have been submitted and the credit review is started by Dinie. Includes the customer ID and under_review status. Use it to update the status in your system and inform the customer that the review is in progress. ### Customer KYC updated - [POST customer.kyc_updated](https://dinie.redocly.app/apis/openapi/customers/oncustomerkycupdated.md): Fires when any KYC requirement changes status (approved, rejected, or pending correction). Includes the full kyc array with the updated status of each item. Use it to identify rejected documents and request resubmission from the customer via PATCH /customers/{id} or POST /customers/{id}/documents. ### Customer active - [POST customer.active](https://dinie.redocly.app/apis/openapi/customers/oncustomeractive.md): Fires when the customer is fully verified (KYC approved) and eligible to receive credit offers. Includes the customer ID and active status. This is the time to query GET /customers/{id}/credit-offers to check for available pre-approved offers. ## Credit Offers The **CreditOffer** resource (`co_`) represents a pre-approved credit offer for a customer. Offers are automatically generated by Dinie when a Customer reaches the `active` status. You are notified via the `credit_offer.available` webhook. ## Flow: Offer → Simulation → Loan ``` CreditOffer (available) → Simulation → Loan ``` 1. **Check the offers** available for a customer 2. **Simulate different scenarios** of amount and term 3. **Create the loan** from the simulation chosen by the customer ## Example: Simulate a Loan ```ruby # 1. List available offers offers = client.customers.list_credit_offers("cust_abc123", status: "available" ) offer = offers.data.first # offer.id => "co_550e8400..." # offer.approved_amount => "50000.00" # offer.min_amount => "5000.00" # offer.interest_rate => 2.5 (% per month) # offer.valid_until => "2026-04-01T00:00:00Z" # 2. Simulate with different amounts sim_25k = client.credit_offers.simulate(offer.id, requested_amount: "25000.00", installment_count: 6 ) sim_40k = client.credit_offers.simulate(offer.id, requested_amount: "40000.00", installment_count: 12 ) # 3. Present options to the customer puts sim_25k.installments_value # "4550.00" per installment puts sim_25k.cet_percentage # 35.2% per year puts sim_40k.installments_value # "3800.00" per installment puts sim_40k.cet_percentage # 32.8% per year ``` ## Understanding the Simulation (`sim_`) The simulation calculates all loan costs before contracting: | Field | Description | |---|---| | `requested_amount` | Amount requested by the customer | | `amount` | Net amount the customer receives | | `interest_amount` | Total interest | | `fees_amount` | Total fees | | `iof_amount` | Calculated IOF | | `total_loan_amount` | Total amount (principal + interest + fees + IOF) | | `installments_value` | Fixed amount of each installment | | `cet_percentage` | Annualized Total Effective Cost | | `first_due_date` | Due date of the first installment | ## Webhooks | Event | When it fires | |---|---| | `credit_offer.available` | New offer generated for the customer | | `credit_offer.expired` | Offer expired (`valid_until` exceeded) | ### List credit offers for a customer - [GET /customers/{customer_id}/credit-offers](https://dinie.redocly.app/apis/openapi/credit-offers/listcustomercreditoffers.md): Lists the available credit offers for a specific customer. Filterable by status (available, accepted, expired). Use this endpoint after receiving the customer.active webhook to check for pre-approved offers. Pagination uses cursor with starting_after + limit. ### List credit offers - [GET /credit-offers](https://dinie.redocly.app/apis/openapi/credit-offers/listcreditoffers.md): Lists credit offers for all customers of the authenticated partner. Supports filters by customer_id and status to locate specific offers. Useful for dashboards and reports that need a consolidated view. For offers of a specific customer, prefer GET /customers/{customer_id}/credit-offers. ### Retrieve a credit offer - [GET /credit-offers/{credit_offer_id}](https://dinie.redocly.app/apis/openapi/credit-offers/getcreditoffer.md): Returns the complete credit offer object, including approved amount (approved_amount), minimum amount, interest rate (interest_rate), maximum number of installments, and expiration date (valid_until). Query the offer before creating a simulation to present the limits to the customer. ### Credit offer available - [POST credit_offer.available](https://dinie.redocly.app/apis/openapi/credit-offers/oncreditofferavailable.md): Fires when Dinie generates a new pre-approved credit offer for the customer. Includes approved amount, interest rate, installments, and offer expiration date. Use it to notify the customer about credit availability and start the simulation flow via POST /credit-offers/{id}/simulations. ### Credit offer expired - [POST credit_offer.expired](https://dinie.redocly.app/apis/openapi/credit-offers/oncreditofferexpired.md): Fires when a credit offer expires after exceeding its expiration date (valid_until). Includes the full offer data with expired status. Use it to remove the offer from the customer interface. New offers may be generated in the future via credit_offer.available. ## Loans The **Loan** resource (`ln_`) represents a loan originated from a CreditOffer and its Simulation. After creation, the loan goes through several automated steps until disbursement. ## Lifecycle ``` processing → contract_generated → awaiting_signatures → signed → disbursing → active → finished ↘ cancelled ↘ error ``` | Status | Description | Required Action | |---|---|---| | `processing` | Loan created, processing | Wait | | `contract_generated` | CCB generated | Wait | | `awaiting_signatures` | Contract ready for signing | Redirect customer to `signing_url` | | `signed` | Contract signed | Wait for disbursement | | `disbursing` | Disbursement in progress | Wait | | `active` | Disbursement completed, installments generated | Track payments | | `finished` | All installments paid | — | | `cancelled` | Cancelled before disbursement | — | | `error` | Processing error | Contact support | ## Example: Create and Track ```ruby # 1. Create the loan from the simulation loan = client.loans.create( credit_offer_id: "co_550e8400...", simulation_id: "sim_550e8400...", installments: 6, installments_value: "4550.00", first_due_date: "2026-04-15" ) # loan.id => "ln_550e8400..." # loan.status => "processing" # 2. After loan.awaiting_signatures webhook loan = client.loans.retrieve(loan.id) # loan.signing_url => ClickSign URL for signing # Redirect the customer to this URL # 3. After loan.active webhook — check installments transactions = client.loans.list_transactions(loan.id) transactions.data.each do |tx| puts "#{tx.due_date}: R$ #{tx.amount_due} (#{tx.status})" end # 2026-04-15: R$ 4550.00 (pending) # 2026-05-15: R$ 4550.00 (pending) # ... ``` ## Transactions (`tx_`) Each active loan has transactions of type `installment` — one per installment. Track payments via queries or webhooks. | Status | Description | |---|---| | `pending` | Installment not yet due | | `paid` | Installment fully paid | | `partially_paid` | Partial payment received | | `overdue` | Installment overdue (`days_overdue` > 0) | ## Webhooks | Event | When it fires | |---|---| | `loan.created` | Loan created, processing started | | `loan.contract_generated` | CCB generated, `ccb_number` available | | `loan.awaiting_signatures` | `signing_url` available for the customer | | `loan.signed` | Contract signed by all parties | | `loan.disbursing` | Disbursement via Pix started | | `loan.active` | Disbursement completed, installments created | | `loan.payment_received` | Installment payment detected | | `loan.finished` | All installments paid | | `loan.cancelled` | Loan cancelled | | `loan.error` | Processing error | ### Simulate a loan - [POST /credit-offers/{credit_offer_id}/simulations](https://dinie.redocly.app/apis/openapi/loans/createsimulation.md): Simulates a loan scenario for a specific credit offer. The customer can simulate multiple times with different amounts and terms before committing. The simulation is synchronous and returns installment amounts, fees, and total cost. The result is persisted and can be referenced when creating the loan via simulation_id. Only the latest simulation is valid for contracting (Last Write Record). ### Create a loan - [POST /loans](https://dinie.redocly.app/apis/openapi/loans/createloan.md): Creates a loan from a credit offer and a simulation accepted by the customer. The partner must include the simulation_id to link the agreed terms. The loan starts with status processing and automatically progresses through the cycle: contract_generated → awaiting_signatures → signed → disbursing → active. The signing_url for signing the CCB contract will be made available via webhook loan.contract_generated. Track the lifecycle via loan.* webhooks. ### Retrieve a loan - [GET /loans/{loan_id}](https://dinie.redocly.app/apis/openapi/loans/getloan.md): Returns the complete loan object with all lifecycle details. Important fields vary by status: signing_url is populated when awaiting_signatures, ccb_number when contract_generated, and net_amount after disbursement. Use together with loan.* webhooks to keep your system synchronized. ### List loan transactions - [GET /loans/{loan_id}/transactions](https://dinie.redocly.app/apis/openapi/loans/listtransactions.md): Lists the transactions (installments) of a loan. Each transaction represents an installment with due date (due_date), original amount, paid amount, and payment status (pending, paid, overdue). This is a read-only endpoint — payments are processed outside the API. Track payments in real time via webhook loan.payment_received. ### Loan created - [POST loan.created](https://dinie.redocly.app/apis/openapi/loans/onloancreated.md): Fires when the loan is created via POST /loans from an accepted offer. Includes the loan, offer, and customer IDs, as well as the requested amount and number of installments. The loan starts with processing status. Use it to register the loan in your system. ### Loan contract generated - [POST loan.contract_generated](https://dinie.redocly.app/apis/openapi/loans/onloancontractgenerated.md): Fires when the CCB (Cedula de Credito Bancario) contract is generated by Dinie. Includes the ClickSign signing_url for digital contract signing. Use it to present the signing link to the customer in your flow. ### Loan awaiting signatures - [POST loan.awaiting_signatures](https://dinie.redocly.app/apis/openapi/loans/onloanawaitingsignatures.md): Fires when the CCB contract is sent to ClickSign and awaits the customer's signature. Includes the updated signing_url. Use it to resend the signing link to the customer or display a reminder if the signature has not yet been completed. ### Loan signed - [POST loan.signed](https://dinie.redocly.app/apis/openapi/loans/onloansigned.md): Fires when the CCB contract is fully signed by all signatories on ClickSign. Includes the registered contract ccb_number. The next step is automatic disbursement. Use it to confirm to the customer that the contract has been successfully signed. ### Loan disbursing - [POST loan.disbursing](https://dinie.redocly.app/apis/openapi/loans/onloandisbursing.md): Fires when Dinie initiates the fund transfer to the customer's account. Includes the disbursement method used (e.g., pix). The transfer may take a few minutes. Use it to inform the customer that the amount is being transferred. ### Loan active - [POST loan.active](https://dinie.redocly.app/apis/openapi/loans/onloanactive.md): Fires when the disbursement is confirmed and the loan enters the repayment phase. Includes the requested amount (requested_amount) and the net amount received (net_amount). Use it to confirm to the customer that the funds have been credited and present the installment schedule. ### Loan payment received - [POST loan.payment_received](https://dinie.redocly.app/apis/openapi/loans/onloanpaymentreceived.md): Fires when an installment payment is recorded for the loan. Includes the amount paid, payment date, and corresponding installment number. Use it to update the outstanding balance in your system and notify the customer about the payment confirmation. ### Loan finished - [POST loan.finished](https://dinie.redocly.app/apis/openapi/loans/onloanfinished.md): Fires when all loan installments are paid off and the contract is closed. Includes the loan ID and finished status. Use it to mark the loan as completed in your system and check if new credit offers are available. ### Loan cancelled - [POST loan.cancelled](https://dinie.redocly.app/apis/openapi/loans/onloancancelled.md): Fires when the loan is cancelled before disbursement is completed. Includes the loan ID and cancelled status. Use it to update the status in your system and inform the customer. The original credit offer may still be available for a new request. ### Loan error - [POST loan.error](https://dinie.redocly.app/apis/openapi/loans/onloanerror.md): Fires when an unrecoverable error occurs in the loan, such as a disbursement failure or contract generation error. Includes the error code and message in the error field. Use it to alert your team, log the issue, and inform the customer about the situation. ## Webhooks Manage the endpoints that receive event notifications (`we_`). Dinie follows the [Standard Webhooks](https://www.standardwebhooks.com/) specification. Events for each resource are documented in the **Customers**, **Credit Offers**, and **Loans** sections. This section covers only endpoint management. ## Configuration ```ruby endpoint = client.webhooks.create_endpoint( url: "https://partner.example.com/webhooks/dinie", events: ["customer.active", "credit_offer.available", "loan.*"], description: "Production webhook" ) # endpoint.secret => "whsec_xxxx..." # ⚠️ Store the secret — shown only at creation! ``` ## Event Patterns Use `*` for all events, or `resource.*` for all events of a resource. | Pattern | Included Events | |---|---| | `customer.*` | `created`, `under_review`, `kyc_updated`, `active` | | `credit_offer.*` | `available`, `expired` | | `loan.*` | `created`, `contract_generated`, `awaiting_signatures`, `signed`, `disbursing`, `active`, `payment_received`, `finished`, `cancelled`, `error` | | `*` | All events | ## Secret Rotation Rotate the secret periodically. The previous secret remains valid for the specified time, allowing a seamless transition. ```ruby result = client.webhooks.rotate_secret("we_abc123", expire_current_in: 3600 # previous valid for 1 more hour ) # result.secret => "whsec_yyyy..." (new secret) ``` ### Create a webhook endpoint - [POST /webhooks/endpoints](https://dinie.redocly.app/apis/openapi/webhooks/createwebhookendpoint.md): Creates a new webhook endpoint to receive Dinie events. The HMAC signing secret (secret) is returned only in this response — store it securely to validate the signatures of received events. Use event patterns like loan., customer., or * to subscribe to entire categories. Each endpoint can subscribe to multiple event patterns. ### List webhook endpoints - [GET /webhooks/endpoints](https://dinie.redocly.app/apis/openapi/webhooks/listwebhookendpoints.md): Lists all webhook endpoints configured by the partner, including URL, subscribed events, and status (active/disabled). The signing secret is not returned in this listing. Use to audit and manage your webhook integrations. ### Retrieve a webhook endpoint - [GET /webhooks/endpoints/{webhook_endpoint_id}](https://dinie.redocly.app/apis/openapi/webhooks/getwebhookendpoint.md): Returns the details of a specific webhook endpoint, including URL, list of subscribed events, and current status (active/disabled). The signing secret (secret) is not returned — use POST .../secret/rotate if you need to generate a new one. ### Update a webhook endpoint - [PATCH /webhooks/endpoints/{webhook_endpoint_id}](https://dinie.redocly.app/apis/openapi/webhooks/updatewebhookendpoint.md): Updates the configuration of a webhook endpoint. Allows changing the destination URL, the list of subscribed events, the description, and the status (active/disabled). Use disabled to temporarily pause deliveries without deleting the endpoint. Only the submitted fields are updated. ### Delete a webhook endpoint - [DELETE /webhooks/endpoints/{webhook_endpoint_id}](https://dinie.redocly.app/apis/openapi/webhooks/deletewebhookendpoint.md): Deletes a webhook endpoint. Stops all deliveries. ### Rotate the signing secret - [POST /webhooks/endpoints/{webhook_endpoint_id}/secret/rotate](https://dinie.redocly.app/apis/openapi/webhooks/rotatewebhooksecret.md): Rotates the HMAC signing secret of the endpoint. A new secret is generated and returned in the response. The previous secret remains valid during the grace period defined by expire_current_in (default: 3600 seconds). During this period, deliveries include signatures with both secrets, allowing a gradual migration in your system without losing events.