Finfra Documentation
Finfra is a lending infrastructure platform. This documentation is for your business and product team it explains how Finfra works conceptually, and walks through the full integration journey step by step. For exact endpoint parameters, see the API Reference.
Core Concepts
Three primary objects make up the Finfra data model. Everything else relates to or extends one of these.
Environments
Finfra provides two isolated environments. Which one your API calls hit depends entirely on the API key you use there is no separate URL switch required in your code.
- No real banking connections
- Use for development & testing
- Data resets periodically
- Use
sk_sandbox_API keys
- Connected to real banking infrastructure
- Real money moves no undo
- Requires partner approval
- Use
sk_prod_API keys
What is a borrower?
A borrower is any person or business entity that you onboard onto Finfra's platform to receive credit. Before a borrower can take out a loan, they must complete KYC (Know Your Customer) verification this is a legal requirement for lending operations in Indonesia.
Think of the borrower object as the central record that links together identity documents, credit history, consent records, and loans.
Borrower types
When creating a borrower, you must specify one of two types. The type drives a different KYC workflow and document set, so providing the correct value is critical.
A natural person. KYC requires a national identity card (KTP) and biometric verification (productionness check).
A registered legal entity. KYC requires business registration documents and director identity verification.
Borrower status lifecycle
A borrower moves through a set of statuses as they progress through the onboarding and KYC process.
| Status | Meaning | What happens next |
|---|---|---|
| PENDING | Borrower created, KYC not yet started | Submit KYC documents and run verification |
| VERIFIED | KYC documents submitted and under review | Finfra reviews and approves or rejects |
| APPROVED | KYC passed borrower can receive loans | Create a loan for this borrower |
| BLOCKED | Borrower is suspended from the platform | No loans can be created until unblocked |
400 error.What is a loan?
A loan is a credit product issued to an approved borrower. Finfra manages the full loan lifecycle: origination, agreement signing, disbursement, and repayment tracking.
Loans are always tied to exactly one borrower. A borrower can have multiple loans, but each loan is independent.
Loan types
Finfra supports two loan repayment structures.
The entire principal plus interest is repaid in one lump sum at the loan's maturity date. Best for project financing or short-term cash loans.
POST /api/core/loans/{userId} βRepaid in regular scheduled installments weekly, biweekly, or monthly. Each payment covers both principal and interest. Ideal for Buy Now, Pay Later flows.
POST /api/core/loans/{userId}/bnpl βLoan status lifecycle
A loan moves through the following statuses from creation to full repayment.
| Status | Meaning | Triggered by |
|---|---|---|
| PENDING | Loan created, awaiting agreement signing | Loan creation API |
| SIGNING | Agreement sent to borrower for signature | POST /loans/signing/initiate |
| ACTIVE | Signed and awaiting disbursement | Borrower completes signing |
| DISBURSED | Funds sent to borrower's bank account | POST /loans/{id}/disbursement |
| REPAID | Loan fully repaid | Final payment processed |
| REJECTED | Loan rejected before disbursement | POST /loans/{id}/reject |
Documents & KYC
KYC (Know Your Customer) is the process of verifying a borrower's identity before lending to them. Finfra handles this in two parts: document upload and biometric verification.
Document upload flow
Uploading a document is always a two-step process:
- Create a document object call
POST /api/documentsto register the document and get a presigned upload URL. - Upload the file PUT the file binary directly to the presigned URL returned in step 1.
Supported KYC providers
Finfra integrates with multiple identity data providers. You specify which to use via the data-source header on relevant endpoints.
| Provider | data-source value | Type |
|---|---|---|
| izidata | izidata | OCR + identity data |
| VERIHUBS | VERIHUBS | Identity verification |
| ASLIRI | ASLIRI | Identity verification |
| VIDA | VIDA | Digital signature + identity |
Authentication
Before you can call any Finfra endpoint, you need a JWT access token. You get one by exchanging your Basic credentials (clientId + clientSecret) via the token endpoint.
clientId:clientSecret and pass it as a Basic authorization header. The response contains an access_token and refresh_token.access_token as Authorization: Bearer <token> on all subsequent API calls. Use POST /api/auth/refresh to renew before expiry.# Encode credentials CREDS=$(echo -n 'clientId:clientSecret' | base64) # Get token TOKEN=$(curl -s -X POST \ https://sandbox-partner-service.elp.finfra.io/api/auth/token/v2 \ -H "Authorization: Basic $CREDS" \ | jq -r '.access_token')
KYC flow
The KYC flow onboards a new borrower and verifies their identity. Follow these steps in order skipping any step will result in the borrower being stuck in PENDING status.
PERSONAL or BUSINESS as the borrower_type. Returns a userId.APPROVED or REJECTED.user_created and user_verify callbacks on your webhook endpoint.Loan origination
Once a borrower is APPROVED, you can create a loan for them. Choose between a single-payment loan or a BNPL installment loan based on your product.
credit-source header to specify afpi, clik, or both.PENDING status and a loanUniqueId is returned.Disbursement
Once the loan agreement is signed, you can initiate disbursement. Finfra will transfer funds directly to the borrower's registered bank account.
GET /api/core/loans/details/{uniqueId} to confirm the loan is in ACTIVE status.Repayment
Finfra supports two repayment collection methods: a hosted payment link or a virtual account (bank transfer). Both methods notify you via webhook when a payment is received.
Generate a URL the borrower opens in their browser to pay online. Best for direct-to-borrower flows.
POST .../payment-link βGenerate a bank transfer number the borrower pays to via internet banking or ATM. Best for older or non-smartphone users.
POST .../virtual-account βWebhooks & callbacks
Finfra does not require polling. Instead, Finfra pushes status changes to your registered HTTPS endpoint using callbacks. You must expose a public HTTPS endpoint and register it in your Finfra dashboard.
Callback types
| Event | When it fires | Endpoint receives |
|---|---|---|
user_created | Borrower successfully created | POST /api/core/ftm/users/{callbackTitle}/status |
user_verify | KYC verification result | POST /api/core/ftm/users/{callbackTitle}/status |
user_credit_score | Credit score result | POST /api/core/ftm/users/{callbackTitle}/status |
loan | Loan status change | POST /api/core/ftm/users/{callbackTitle}/status |
bnpl | BNPL installment status | POST /api/core/ftm/users/{callbackTitle}/status |
| Payment gateway | Invoice or VA payment received | POST /api/core/payment-gateway/*/status |
Securing callbacks
All callbacks from Finfra include a finfra-auth-key header. Validate this header on every incoming request before processing it to prevent spoofed callbacks.
app.post('/callbacks/finfra', (req, res) => { // Validate the auth key const key = req.headers['finfra-auth-key']; if (key !== process.env.FINFRA_CALLBACK_KEY) { return res.status(401).json({ error: 'Unauthorized' }); } // Process the event const { type, status, data } = req.body; console.log(`Event: ${type}, status: ${status}`); res.status(200).json({ received: true }); });
200 response quickly. If your processing takes time, acknowledge the callback immediately and handle the work asynchronously in a queue.