Documentation API Reference
Introduction

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.

πŸ“˜
Concepts
Understand borrowers, loans, KYC, and how they relate to each other in Finfra's data model.
πŸ—ΊοΈ
Integration guides
End-to-end step-by-step flows from authentication through disbursement and repayment.
πŸ”—
RESTful API
All operations use standard HTTPS with JSON bodies. No bulk operations every action is per object.
πŸ””
Real-time callbacks
Finfra pushes status changes to your webhook endpoint so you don't need to poll.
Overview

Core Concepts

Three primary objects make up the Finfra data model. Everything else relates to or extends one of these.

πŸ‘€
Borrower
A person or business entity who takes out a loan. Must pass KYC verification before any loan can be created for them.
πŸ“„
Document
A KYC document (e.g. ID card, selfie) uploaded during borrower onboarding. Required before a borrower can be approved.
πŸ’°
Loan
A credit product issued to an approved borrower. Can be a single-payment loan or an installment (BNPL) loan.
πŸ””
Callback
A webhook Finfra sends to your server when a borrower or loan status changes. Use these to keep your system in sync.
Environments

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.

SANDBOX
sandbox-partner-service.elp.finfra.io
  • No real banking connections
  • Use for development & testing
  • Data resets periodically
  • Use sk_sandbox_ API keys
PRODUCTION
partner-service.elp.finfra.io
  • Connected to real banking infrastructure
  • Real money moves no undo
  • Requires partner approval
  • Use sk_prod_ API keys
⚠️Never use production API keys in development. Keep all keys out of source control. Rotate immediately if compromised via your Finfra dashboard.
Concepts

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.

💡You create the borrower object in Finfra. Finfra does not directly interact with the borrower your platform handles the borrower-facing experience and calls the Finfra API on their behalf.
Concepts

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.

PERSONAL
Individual borrower

A natural person. KYC requires a national identity card (KTP) and biometric verification (productionness check).

BUSINESS
Business entity borrower

A registered legal entity. KYC requires business registration documents and director identity verification.

POST /api/core/users β†’
Concepts

Borrower status lifecycle

A borrower moves through a set of statuses as they progress through the onboarding and KYC process.

StatusMeaningWhat 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
Only borrowers in APPROVED status can have loans created for them. Attempting to create a loan for a non-approved borrower returns a 400 error.
Concepts

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.

Concepts

Loan types

Finfra supports two loan repayment structures.

πŸ’΅
Single Payment Loan

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} β†’
πŸ“…
Installment Loan (BNPL)

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 β†’
Concepts

Loan status lifecycle

A loan moves through the following statuses from creation to full repayment.

StatusMeaningTriggered by
PENDINGLoan created, awaiting agreement signingLoan creation API
SIGNINGAgreement sent to borrower for signaturePOST /loans/signing/initiate
ACTIVESigned and awaiting disbursementBorrower completes signing
DISBURSEDFunds sent to borrower's bank accountPOST /loans/{id}/disbursement
REPAIDLoan fully repaidFinal payment processed
REJECTEDLoan rejected before disbursementPOST /loans/{id}/reject
Concepts

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:

  1. Create a document object call POST /api/documents to register the document and get a presigned upload URL.
  2. Upload the file PUT the file binary directly to the presigned URL returned in step 1.
⚠️The presigned URL expires after a short window. Complete the file upload immediately after creating the document object.

Supported KYC providers

Finfra integrates with multiple identity data providers. You specify which to use via the data-source header on relevant endpoints.

Providerdata-source valueType
izidataizidataOCR + identity data
VERIHUBSVERIHUBSIdentity verification
ASLIRIASLIRIIdentity verification
VIDAVIDADigital signature + identity
Integration Guide Step 1

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.

1
Get your credentials Dashboard
Log in to the Finfra dashboard and copy your clientId and clientSecret. Use sandbox credentials during development.
2
Exchange for a token POST /api/auth/token/v2
Base64-encode clientId:clientSecret and pass it as a Basic authorization header. The response contains an access_token and refresh_token.
3
Use the token on every request
Pass the access_token as Authorization: Bearer <token> on all subsequent API calls. Use POST /api/auth/refresh to renew before expiry.
cURL
# 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')
Full auth reference β†’
Integration Guide Step 2

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.

1
Fetch consent list GET /api/core/kyc/consent-list
Retrieve the list of consent items to display to the borrower in your UI. The borrower must explicitly accept each item.
2
Record consent POST /api/core/users/consent
After the borrower accepts, call the consent endpoint to record their agreement. This must happen before any KYC or credit check.
3
Create the borrower POST /api/core/users
Create the borrower record with their personal data. Specify PERSONAL or BUSINESS as the borrower_type. Returns a userId.
4
Upload KYC documents POST /api/documents
For each document (KTP, selfie, etc.): create a document object, then PUT the file to the returned presigned URL. Repeat for each required document type.
5
Run OCR & biometric POST /api/core/users/ocr
Submit the uploaded documents to OCR to extract identity data. Then run biometric verification (productionness check) using the borrower's selfie.
6
Submit KYC POST /api/core/kyc/{kycIdPath}/submit
Finalise the KYC session. Finfra processes the submission and sends a callback to your registered endpoint when the status changes to APPROVED or REJECTED.
💡Do not poll for borrower status. Instead, listen for the user_created and user_verify callbacks on your webhook endpoint.
Integration Guide Step 3

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.

1
Check credit score POST /api/core/users/score-report
Optionally run a credit score check before originating. Use the credit-source header to specify afpi, clik, or both.
2
Create the loan POST /api/core/loans/{userId} or POST /api/core/loans/{userId}/bnpl
Create either a single-payment or installment loan. The loan is created in PENDING status and a loanUniqueId is returned.
3
Initiate agreement signing POST /api/core/loans/signing/initiate
Trigger the loan agreement signing flow. The borrower receives the agreement and must sign before funds can be disbursed.
Integration Guide Step 4

Disbursement

Once the loan agreement is signed, you can initiate disbursement. Finfra will transfer funds directly to the borrower's registered bank account.

⚠️Disbursement is irreversible. Once initiated, it cannot be cancelled. Always confirm the loan details and signing status before calling the disbursement endpoint.
1
Confirm loan is signed
Listen for the signing callback or call GET /api/core/loans/details/{uniqueId} to confirm the loan is in ACTIVE status.
2
Disburse POST /api/core/loans/{loanUniqueId}/disbursement
Finfra transfers the loan principal to the borrower's bank account. A callback is sent to your webhook when disbursement completes.
Disbursement API reference β†’
Integration Guide Step 5

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.

🔗 Payment Link

Generate a URL the borrower opens in their browser to pay online. Best for direct-to-borrower flows.

POST .../payment-link β†’
🏭 Virtual Account

Generate a bank transfer number the borrower pays to via internet banking or ATM. Best for older or non-smartphone users.

POST .../virtual-account β†’
Integration Guide Step 6

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

EventWhen it firesEndpoint receives
user_createdBorrower successfully createdPOST /api/core/ftm/users/{callbackTitle}/status
user_verifyKYC verification resultPOST /api/core/ftm/users/{callbackTitle}/status
user_credit_scoreCredit score resultPOST /api/core/ftm/users/{callbackTitle}/status
loanLoan status changePOST /api/core/ftm/users/{callbackTitle}/status
bnplBNPL installment statusPOST /api/core/ftm/users/{callbackTitle}/status
Payment gatewayInvoice or VA payment receivedPOST /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.

JavaScript Express example
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 });
});
Always return a 200 response quickly. If your processing takes time, acknowledge the callback immediately and handle the work asynchronously in a queue.
Callback API reference β†’