Documentation API Reference
Support Status
Sandbox
Introduction

Finfra API Reference

The Finfra API is a RESTful interface for managing borrower KYC, loan origination, disbursement, and repayment. It accepts JSON and form-encoded requests and returns JSON responses. All actions are performed per object - bulk operations are not supported. The API key type used determines whether requests hit the production environment or are restricted to test mode.

REST
Architecture
JSON responses
2
Environments
Sandbox + Production
JWT
Auth method
Bearer + Basic + ApiKey

Base URLs

Sandbox
https://sandbox-partner-service.elp.finfra.io
Production
https://partner-service.elp.finfra.io
💡 Use your sandbox credentials for all development and testing. Actions in sandbox do not connect to banking infrastructure and have no effect on real data.

Endpoints at a glance

Authentication

Authentication

Finfra uses three authentication schemes. Which one to use depends on the endpoint. Keep your API keys confidential - never expose them in public repositories or client-side code. All API interactions must be over HTTPS.

SchemeHeaderUsed for
BasicAuthAuthorization: Basic …Generating access tokens
BearerAuthAuthorization: Bearer JWTBorrower, document, and loan endpoints
ApiKeyAuthfinfra-auth-key: …Callback / webhook endpoints

Generate access token

POST/api/auth/token/v2200 OK
Exchange Basic credentials for a JWT access token. Include this token as a Bearer on all subsequent requests.
⚠️/api/auth/token (v1) is deprecated. Use /api/auth/token/v2 for all new integrations.

Request

curl -X POST https://sandbox-partner-service.elp.finfra.io/api/auth/token/v2 \
  -H "Authorization: Basic $(echo -n 'clientId:clientSecret' | base64)"

Response

JSON
{
  "access_token":  "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type":    "Bearer",
  "expires_in":    3600
}
Use POST /api/auth/refresh with headers x-access-token and x-refresh-token to refresh your session without re-authenticating with Basic credentials.
Errors & Health

Error Handling & Healthcheck

All errors return a consistent JSON body. Use the healthcheck endpoints to verify service availability before integration testing.

Error response format

JSON
{
  "status":  400,
  "error":   "Bad Request",
  "message": "Validation failed: email is required"
}

HTTP status codes

CodeMeaning
200Success
201Resource created
400Validation error - check request body or params
401Unauthorized - invalid or missing token
403Forbidden - insufficient permissions
409Conflict - resource already exists
415Unsupported media type
429Rate limited - slow down and retry
500Internal server error

Healthcheck

GET/healthcheck/productionness200 OK
Returns 200 if the service process is aproduction. No authentication required.
GET/healthcheck/readiness200 OK
Returns 200 if the service is ready to handle traffic and all dependencies are connected. No authentication required.
Borrower

Create Borrower

Finfra supports two borrower types: PERSONAL (individual) and BUSINESS (entity). The type provided drives a different KYC procedural workflow, so ensure the correct value is supplied.

POST/api/core/users200 OK
Creates a partner borrower profile. Requires Bearer token authentication.

Headers

HeaderTypeRequiredDescription
AuthorizationstringrequiredBearer JWT from /api/auth/token/v2
kyc-idstringoptionalKYC session token for linking existing KYC context

Request body (JSON)

Top-level fields

FieldTypeRequiredDescription
typestringrequiredPERSONAL or BUSINESS. Determines the KYC workflow applied to this borrower.
entityobjectoptionalBusiness entity details. Required when type is BUSINESS.
authorised_signatoryobjectrequiredIndividual person details. For PERSONAL borrowers this is the borrower themselves. For BUSINESS borrowers this is the authorised signatory of the entity.

entity object

FieldTypeRequiredDescription
namestringrequiredRegistered company name
addressobjectrequiredCompany registered address. See address object below.
phone_numberstringrequiredCompany phone number in international format, e.g. +6287711998822
faxstringoptionalCompany fax number in international format
emailstringrequiredCompany email address
business_typestringrequiredType of business. e.g. OTHER
industrystringrequiredIndustry classification. e.g. PRIVATE_PERSON_NAME
nationalitystringrequiredISO 3166-1 alpha-2 country code of company nationality, e.g. ID
residencestringrequiredISO 3166-1 alpha-2 country code of company residence, e.g. ID
npwpstringrequiredCompany tax identification number (NPWP)
phone_extstringoptionalAdditional phone number or extension
legal_entitystringrequiredLegal entity type, e.g. PT, CV
establishment_datestringrequiredDate of establishment in YYYY-MM-DD format
establishment_placestringrequiredCity or place of establishment
deed_datestringrequiredDate of the establishment deed in YYYY-MM-DD format
deed_numberstringrequiredEstablishment deed reference number
managementsarrayrequiredList of company management personnel. See management object below.

entity.managements[] object

FieldTypeRequiredDescription
namestringrequiredFull name of the management person
positionstringrequiredRole in the company, e.g. OWNER_MANAGEMENT
email_addressstringrequiredEmail address
mobile_numberstringrequiredMobile number in international format
addressstringrequiredResidential address
genderstringrequiredMALE or FEMALE
identity_numberstringrequiredNIK (national identity number), 16 digits

authorised_signatory object

FieldTypeRequiredDescription
first_namestringrequiredFirst name
last_namestringrequiredLast name
birth_datestringrequiredDate of birth in YYYY-MM-DD format
birth_placestringrequiredCity or place of birth
emailstringrequiredEmail address
mother_maiden_namestringrequiredMother's maiden name
marital_statusstringrequiredMARRIED, SINGLE, DIVORCED, or WIDOWED
genderstringrequiredMALE or FEMALE
titlestringrequiredSalutation, e.g. BPK (Bapak), IBU
domicilestringrequiredISO 3166-1 alpha-2 country code of domicile
religionstringrequiredReligion, e.g. ISLAM, CHRISTIAN, CATHOLIC, HINDU, BUDDHIST, CONFUCIAN
jobstringrequiredOccupation type, e.g. PRIVATE_SECTOR_EMPLOYEE
educationstringrequiredHighest education level, e.g. ELEMENTARY_SCHOOL
addressobjectrequiredResidential address. See address object below. Also accepts country field (ISO 3166-1 alpha-2).
mobile_numberstringrequiredMobile number in international format
bank_accountarrayoptionalList of bank accounts. See bank_account object below.
documentsobjectrequiredKYC documents. See documents object below.
business_typestringoptionalType of business (if self-employed), e.g. OTHER
monthly_income_rangestringrequiredMonthly income bracket, e.g. LESS_THAN_3_MILLION
emergency_contact_namestringrequiredEmergency contact full name
emergency_contact_numberstringrequiredEmergency contact phone number
housing_statusstringrequiredHousing ownership status, e.g. OWN_HOME
source_of_fundstringrequiredPrimary source of income, e.g. SALARY
place_of_workstringrequiredEmployer or company name
work_addressstringrequiredWorkplace address
number_of_dependentsintegeroptionalNumber of financial dependents
spouse_identification_numberstringoptionalSpouse NIK. Applicable when marital_status is MARRIED.
spouse_namestringoptionalSpouse full name
spouse_date_of_birthstringoptionalSpouse date of birth in YYYY-MM-DD format
prenuptial_agreementstringoptionaltrue or false. Whether a prenuptial agreement exists.

address object

FieldTypeRequiredDescription
street_addressstringrequiredFull street address
rtstringrequiredRT (neighbourhood unit) number
rwstringrequiredRW (community unit) number
provincestringrequiredProvince code, e.g. JAWA_BARAT, DKI_JAKARTA
citystringrequiredCity or regency name
districtstringrequiredDistrict (kecamatan) name
villagestringrequiredVillage (kelurahan) name
postal_codestringrequiredPostal code
countrystringoptionalISO 3166-1 alpha-2 country code. Used in authorised_signatory.address.

bank_account[] object

FieldTypeRequiredDescription
holder_namestringrequiredAccount holder full name
numberstringrequiredBank account number
swift_codestringrequiredBank SWIFT/BIC code

documents object

FieldTypeRequiredDescription
ktpobjectrequiredIndonesian national ID card (KTP). Contains number (16-digit NIK), file (base64 or URL), issuing_city, and expiry_date (YYYY-MM-DD).
selfieobjectrequiredSelfie photo. Contains file (base64 or URL).
npwpobjectoptionalTax ID document. Contains number (NPWP number) and file (base64 or URL).
selfie_with_ktpobjectoptionalSelfie holding KTP. Contains file (base64 or URL).
stock_imagesobjectoptionalBusiness stock/inventory images. Contains file (base64 or URL).
finance_reportobjectoptionalFinancial report document. Contains file (base64 or URL).

Example request body

JSON
{
  "type": "PERSONAL",
  "authorised_signatory": {
    "first_name": "Budi",
    "last_name": "Santoso",
    "birth_date": "1995-11-01",
    "birth_place": "Jakarta",
    "email": "budi@example.com",
    "mother_maiden_name": "Sari",
    "marital_status": "MARRIED",
    "gender": "MALE",
    "title": "BPK",
    "domicile": "ID",
    "religion": "ISLAM",
    "job": "PRIVATE_SECTOR_EMPLOYEE",
    "education": "ELEMENTARY_SCHOOL",
    "address": {
      "street_address": "Jl. Sudirman No. 1",
      "rt": "01",
      "rw": "01",
      "province": "JAWA_BARAT",
      "city": "Bandung",
      "district": "Coblong",
      "village": "Dago",
      "postal_code": "40135",
      "country": "ID"
    },
    "mobile_number": "+6281234567890",
    "bank_account": [
      {
        "holder_name": "Budi Santoso",
        "number": "123123123213",
        "swift_code": "BNINIDJA"
      }
    ],
    "documents": {
      "ktp": {
        "number": "3275062009921981",
        "file": "base64_or_url",
        "issuing_city": "Jakarta",
        "expiry_date": "2099-11-01"
      },
      "selfie": { "file": "base64_or_url" }
    },
    "monthly_income_range": "LESS_THAN_3_MILLION",
    "emergency_contact_name": "Humairah",
    "emergency_contact_number": "08123456789",
    "housing_status": "OWN_HOME",
    "source_of_fund": "SALARY",
    "place_of_work": "Finfra",
    "work_address": "Mega Kuningan",
    "number_of_dependents": 3,
    "spouse_name": "Mia",
    "spouse_identification_number": "3275062309984412",
    "spouse_date_of_birth": "1999-03-01",
    "prenuptial_agreement": "true"
  }
}

Response

💡Borrower creation is processed asynchronously. The response confirms the request was accepted. The borrower status update will be delivered via webhook to your registered callback URL.
JSON
{
  "status": "success",
  "message": "Borrower creation request accepted"
}
Borrower

Create Borrower (KYC Path)

POST/api/core/{kycIdPath}/users200 OK
Creates a borrower profile directly linked to a KYC session via the path parameter. Identical request body to POST /api/core/users.

Path Parameters

ParameterTypeRequiredDescription
kycIdPathstringrequiredJWT-formatted KYC session ID e.g. eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
Borrower

Get Borrower

GET/api/core/users/{userId}200 OK
Returns a single borrower profile by user ID.

Path Parameters

ParameterTypeRequiredDescription
userIdstringrequiredBorrower user ID

Response fields

FieldTypeDescription
idstringUnique borrower identifier
partner_idstringPartner identifier (UUID) the borrower belongs to
statusstringCurrent borrower status, e.g. PENDING, APPROVED_BY_PARTNER, BLOCKED
typestringPERSONAL or BUSINESS
authorised_signatoryobjectIndividual person details. Same structure as the Create Borrower request. Includes all personal info, address, bank accounts, documents, employment, and spouse details.
created_atstringISO 8601 timestamp of when the borrower was created

Response

JSON
{
  "id": "6a41ff87dda4eefd0b7b0300",
  "partner_id": "1507b694-e78e-4fc9-ac28-68d72fba45e9",
  "status": "APPROVED_BY_PARTNER",
  "type": "PERSONAL",
  "authorised_signatory": {
    "first_name": "FERDIAN",
    "last_name": "HENDRI SISWORO",
    "birth_date": "1987-11-23T00:00:00.000Z",
    "birth_place": "MALANG",
    "email": "sarengmalang@gmail.com",
    "mother_maiden_name": "Lilik Ariani",
    "documents": {
      "ktp": {
        "number": "3573032311870003",
        "file": "6a41fddddda4eefd0b7b0274"
      },
      "selfie": {},
      "npwp": {},
      "selfie_with_ktp": {}
    },
    "marital_status": "MARRIED",
    "domicile": "ID",
    "religion": "CHRISTIAN",
    "gender": "MALE",
    "job": "BUSINESS_OWNER",
    "education": "BACHELORS_DEGREE",
    "address": {
      "street_address": "JL. DANDELION D2 PERUM DE GREEN PAVILLION",
      "city": "MALANG",
      "district": "LOWOKWARU",
      "postal_code": "65142",
      "province": "JAWA_TIMUR",
      "rt": "002",
      "rw": "003",
      "village": "TUNGGULWULUNG"
    },
    "mobile_number": "+6281339933711",
    "bank_account": [
      {
        "holder_name": "FERDIAN HENDRI SISWORO",
        "number": "7353740141",
        "swift_code": "BBIJIDJA"
      }
    ],
    "business_type": "RESTAURANT",
    "monthly_income_range": "GTE_20_AND_LT_50_MILLION",
    "emergency_contact_name": "Doni",
    "emergency_contact_number": "+6287854595905",
    "housing_status": "OWN_HOME",
    "source_of_fund": "SALARY",
    "place_of_work": "Sareng Indonesian Culinary & Coffee Space",
    "work_address": "",
    "number_of_dependents": 2,
    "spouse_identification_number": "3573012208890003",
    "spouse_name": "Yessi Puspitasari",
    "spouse_date_of_birth": "1989-08-22T00:00:00.000Z",
    "prenuptial_agreement": false
  },
  "created_at": "2026-06-29T05:15:51.591Z"
}
Borrower

Update Borrower

PATCH/api/core/users/{userId}200 OK
Partially updates a borrower profile. Only include fields you wish to change.

Path Parameters

ParameterTypeRequiredDescription
userIdstringrequiredBorrower user ID to update
Borrower

Approve Borrower

POST/api/core/users/{userId}/approve200 OK
Approves a borrower after KYC verification is complete. No auth required on this endpoint.

Path Parameters

ParameterTypeRequiredDescription
userIdstringrequiredBorrower user ID to approve
💡A borrower must be in APPROVED status before a loan can be created for them.
Borrower

Block Borrower

POST/api/core/users/{userId}/block200 OK
Blocks a borrower, preventing them from accessing loan services. No auth required.

Path Parameters

ParameterTypeRequiredDescription
userIdstringrequiredBorrower user ID to block
Borrower

Credit Score Report

POST/api/core/users/score-report200 OK
Requests a credit score report for a borrower from the configured credit bureau.

Headers

HeaderTypeRequiredDescription
credit-sourcestringoptionalComma-separated sources: afpi, clik, or afpi,clik
Borrower

Credit History

GET/api/core/users/{identityNumber}/credit-history200 OK
Returns the credit history for a borrower identified by their national identity number (NIK).

Path Parameters

ParameterTypeRequiredDescription
identityNumbernumberrequiredBorrower NIK (national identity number)
Borrower

Verify Borrower Biometric (RDF)

POST/api/core/users/{userId}/rdf/verify-biometric200 OK
Initiates biometric verification for a borrower through the RDF provider.

Path Parameters

ParameterTypeRequiredDescription
userIdstringrequiredBorrower user ID
Borrower

Check Borrower with Hub

GET/api/core/users/{userId}/status/{callbackTitle}200 OK
Checks the borrower's status against an external hub (e.g. VERIHUBS, ASLIRI). The callbackTitle specifies which check type to run.

Path Parameters

ParameterTypeRequiredDescription
userIdstringrequiredBorrower user ID
callbackTitlestringrequiredType of hub check to perform
e-KYC

OCR Documents

POST/api/core/users/ocr200 OK
Performs OCR on uploaded KYC documents (e.g. KTP/ID card) to extract borrower data automatically.

Headers

HeaderTypeRequiredDescription
data-sourcestringoptionalizidata | VERIHUBS | ASLIRI | VIDA
kyc-idstringoptionalKYC session token
e-KYC

Biometric KYC

POST/api/core/users/biometric200 OK
Submits biometric data (productionness / face match) for KYC verification.

Headers

HeaderTypeRequiredDescription
kyc-idstringoptionalKYC session token
e-KYC

CLIK Credit Report

POST/api/core/users/clik/credit-report200 OK
Requests a credit report from AFPI/CLIK for a borrower. Returns either an individual or company credit report depending on the borrower type.
e-KYC

AFPI Credit History

GET/api/core/users/{identityNumber}/{reffid}/afpi/credit-report200 OK
Retrieves the AFPI credit history for a borrower by identity number and reference ID. No auth required.

Path Parameters

ParameterTypeRequiredDescription
identityNumbernumberrequiredBorrower NIK
reffidstringrequiredReference ID from AFPI
e-KYC

Get KYC Submission

GET/api/core/kyc/{kycIdPath}/submission200 OK
Returns the KYC submission status and data for a given KYC session.

Path Parameters

ParameterTypeRequiredDescription
kycIdPathstringrequiredKYC session JWT token
e-KYC

Submit KYC

POST/api/core/kyc/{kycIdPath}/submit200 OK
Finalizes and submits a KYC session for processing.

Path Parameters

ParameterTypeRequiredDescription
kycIdPathstringrequiredKYC session JWT token
Documents

Create Document

The KYC document flow is two steps: (1) create a document object to receive a presigned upload URL, then (2) upload the file content to that URL. These steps must be executed in sequence.

POST/api/documents201 Created
Creates a document object and returns a presigned URL for file upload. No auth required.

Request body: multipart/form-data with document metadata and the file.

After creating the document object, PUT the file content directly to the returned presigned_url. The document is not usable until the file upload is complete.

Response

JSON
{
  "id":            "doc_01j4abc",
  "type":          "KTP",
  "presigned_url": "https://storage.finfra.io/upload?token=...",
  "expires_at":    "2025-06-29T09:00:00Z"
}
Documents

Get Document

GET/api/documents/{documentId}200 OK
Returns document metadata by document ID.

Path Parameters

ParameterTypeRequiredDescription
documentIdstringrequiredDocument ID (min 6 chars)
Documents

Get Document File

GET/api/documents/{documentId}/file200 OK
Streams the raw file binary for a document. Returns application/octet-stream.

Path Parameters

ParameterTypeRequiredDescription
documentIdstringrequiredDocument ID (min 6 chars)
Documents

Update Documents

PATCH/api/documents200 OK
Updates the description and type of multiple documents in a single request. Returns an array of updated document objects.
Loan Services

List Loans

GET/api/core/loans200 OK
Returns a paginated list of loans with optional filters by borrower, amount range, and date range.

Query Parameters

ParameterTypeRequiredDescription
userIdstringoptionalFilter by borrower user ID
uniqueIdstringoptionalFilter by loan unique ID (min 6 chars)
pageNumberintegeroptionalPage number (default: 1)
pageSizeintegeroptionalResults per page
startDatestringoptionalFilter from date
endDatestringoptionalFilter to date
startRangeAmountstringoptionalMinimum loan amount filter
endRangeAmountstringoptionalMaximum loan amount filter
Loan Services

Create Single Payment Loan

POST/api/core/loans/{userId}200 OK
Creates a single-repayment loan. Ideal for project financing or cash loans repaid in one lump sum at maturity.

Path Parameters

ParameterTypeRequiredDescription
userIdstringrequiredApproved borrower user ID
💡The borrower must be in APPROVED status before a loan can be created. Call POST /api/core/users/{userId}/approve first if needed.
Loan Services

Create BNPL (Installment Loan)

POST/api/core/loans/{userId}/bnpl200 OK
Creates an installment loan repaid in regular weekly, biweekly, or monthly payments. Each payment covers both principal and interest. Ideal for Buy Now, Pay Later (BNPL) flows.

Path Parameters

ParameterTypeRequiredDescription
userIdstringrequiredApproved borrower user ID
Loan Services

Loan Detail

GET/api/core/loans/details/{uniqueId}200 OK
Returns full loan details including repayment schedule by loan unique ID.

Path Parameters

ParameterTypeRequiredDescription
uniqueIdstringrequiredLoan unique ID (min 6 chars)
Loan Services

Initiate Loan Signing

POST/api/core/loans/signing/initiate200 OK
Initiates the loan agreement signing process. Must be completed before disbursement.
⚠️Signing must be completed before calling the disbursement endpoint. Disbursement will fail if the agreement is unsigned.
Loan Services

Disburse Loan

POST/api/core/loans/{loanUniqueId}/disbursement200 OK
Initiates disbursement of loan funds to the borrower's registered bank account.

Path Parameters

ParameterTypeRequiredDescription
loanUniqueIdstringrequiredLoan unique ID
⚠️Disbursement is irreversible once initiated. Ensure the loan agreement has been signed via POST /api/core/loans/signing/initiate before proceeding.
Loan Services

Reject Loan

POST/api/core/loans/{loanUniqueId}/reject200 OK
Rejects a pending loan application. Provide a rejection reason in the request body.

Path Parameters

ParameterTypeRequiredDescription
loanUniqueIdstringrequiredLoan unique ID
Loan Services

Create Virtual Account

POST/api/core/virtual-account/request200 OK
Generates a virtual account number for loan repayment via bank transfer.
Callbacks

Borrower Status Callback

Finfra sends callbacks to your registered endpoint when borrower status, credit score, loan, or BNPL status changes. Secure these endpoints with the finfra-auth-key header.

POST/api/core/ftm/users/{callbackTitle}/status200 OK
Receives real-time status updates for user creation, verification, credit score, loan, and BNPL events.

Path Parameters

ParameterTypeRequiredDescription
callbackTitlestringrequiredEvent type identifier (e.g. user_created, loan_disbursed)

Headers

HeaderTypeRequiredDescription
finfra-auth-keystringrequiredAPI key for callback authentication (from dashboard)
Callbacks

Payment Gateway Invoice Webhook

POST/api/core/payment-gateway/invoices/status200 OK
Receives payment status updates from the payment gateway for invoice-based repayments.
Callbacks

Virtual Account Webhook

POST/api/core/payment-gateway/virtual-account/status200 OK
Receives payment notifications from Xendit when a borrower completes a repayment via virtual account.
Callbacks

Didit Session Callback

POST/api/core/users/didit/session/callback200 OK
Receives the result of an active productionness check from the Didit third-party provider.

Query Parameters

ParameterTypeRequiredDescription
verificationSessionIdstringoptionalDidit verification session ID
statusstringoptionalDidit verification status (default: 0)