Files
bank-flow/docs/api-routes.md
2026-07-22 15:02:14 +03:30

507 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# BankFlow API Reference
This document describes the HTTP API contract for BankFlow. It is based on the requirements in [bank-flow.md](./bank-flow.md).
## Overview
All loan routes are versioned under `/api/v1`. The health-check route is not versioned.
### Routes
| Method | Route | Description | Success status |
|--------|----------------------------------|----------------------------|----------------|
| `POST` | `/api/v1/loans` | Create a loan application | `201 Created` |
| `POST` | `/api/v1/loans/{loanId}/process` | Process a loan application | `200 OK` |
| `GET` | `/api/v1/loans/{loanId}` | Get a loan application | `200 OK` |
| `GET` | `/api/v1/loans/{loanId}/history` | Get processing history | `200 OK` |
| `GET` | `/health` | Check service health | `200 OK` |
## General conventions
### Content type
Requests with a body must use JSON. Every response must include:
```http
Content-Type: application/json
```
### Timestamps
All timestamps use ISO 8601 format in UTC:
```text
2026-07-15T10:00:00Z
```
### Loan types
| Value | Description |
|------------|---------------|
| `PERSONAL` | Personal loan |
| `BUSINESS` | Business loan |
### Loan statuses
| Status | Description | Terminal for automatic processing |
|-----------------|----------------------------------------------------|-----------------------------------|
| `SUBMITTED` | The application has been created but not processed | No |
| `IN_PROGRESS` | The application is being processed | No |
| `MANUAL_REVIEW` | The application requires a manual decision | Yes |
| `APPROVED` | The application has been approved | Yes |
| `REJECTED` | The application has been rejected | Yes |
### Loan stages
| Stage | Description |
|--------------------|-----------------------------------------|
| `VALIDATION` | Validate the submitted application data |
| `FRAUD_CHECK` | Perform the mocked fraud check |
| `GUARANTOR_CHECK` | Check for a guarantor on business loans |
| `CREDIT_CHECK` | Evaluate the applicant's credit score |
| `MANAGER_APPROVAL` | Apply the mocked manager-approval rule |
### Stage result type
| Result | Effect |
|-----------------|------------------------------------------------------------|
| `PASS` | Continue to the next applicable stage |
| `FAIL` | Stop processing and set the loan status to `REJECTED` |
| `MANUAL_REVIEW` | Stop processing and set the loan status to `MANUAL_REVIEW` |
## Create a loan application
Creates and stores a new loan application. Creating an application does not execute its workflow.
```http
POST /api/v1/loans
```
### Request body
| Field | Type | Required | Rules |
|-----------------|-----------|----------|----------------------------------------------------|
| `customerId` | `string` | Yes | Must not be empty |
| `amount` | `integer` | Yes | Must be greater than `0` |
| `phone` | `string` | Yes | Must contain exactly 11 digits and start with `09` |
| `loanType` | `string` | Yes | Must be `PERSONAL` or `BUSINESS` |
| `monthlyIncome` | `integer` | Yes | Must be greater than or equal to `0` |
| `creditScore` | `integer` | Yes | Must be between `0` and `1000`, inclusive |
| `hasGuarantor` | `boolean` | Yes | Indicates whether the applicant has a guarantor |
```json
{
"customerId": "C-1001",
"amount": 400000000,
"phone": "09121234567",
"loanType": "PERSONAL",
"monthlyIncome": 50000000,
"creditScore": 720,
"hasGuarantor": false
}
```
### Processing rules
- The service generates a unique `loanId`.
- The initial status is `SUBMITTED`.
- The initial workflow stage is `VALIDATION`.
- Business validation is deferred until the workflow is processed.
- An invalid field value does not produce an HTTP `400` response during creation. It causes the `VALIDATION` stage to fail when the application is processed.
- A malformed JSON document produces an HTTP `400` response.
### Success response
```http
HTTP/1.1 201 Created
Content-Type: application/json
```
```json
{
"loanId": "L-10001",
"status": "SUBMITTED",
"currentStage": "VALIDATION"
}
```
#### Response fields
| Field | Type | Description |
|----------------|----------|------------------------------------------------|
| `loanId` | `string` | Unique identifier generated by the service |
| `status` | `string` | Current loan status; initially `SUBMITTED` |
| `currentStage` | `string` | Current workflow stage; initially `VALIDATION` |
### Malformed JSON response
```http
HTTP/1.1 400 Bad Request
Content-Type: application/json
```
```json
{
"error": "INVALID_REQUEST"
}
```
## Process a loan application
Processes an application from its current workflow stage until it reaches a terminal automatic-processing status.
```http
POST /api/v1/loans/{loanId}/process
```
### Path parameters
| Parameter | Type | Required | Description |
|-----------|----------|----------|------------------------------------|
| `loanId` | `string` | Yes | Unique loan application identifier |
This route does not accept a request body.
### Workflow rules
All applications begin with the following stages:
```text
VALIDATION → FRAUD_CHECK
```
The remaining route depends on the loan type:
```text
PERSONAL:
VALIDATION → FRAUD_CHECK → CREDIT_CHECK → [MANAGER_APPROVAL] → APPROVED
BUSINESS:
VALIDATION → FRAUD_CHECK → GUARANTOR_CHECK → CREDIT_CHECK
→ [MANAGER_APPROVAL] → APPROVED
```
`MANAGER_APPROVAL` runs only when `amount` is greater than the configured `managerApprovalThreshold`.
Processing stops immediately when a stage returns `FAIL` or `MANUAL_REVIEW`.
### Idempotency rules
This operation must be idempotent.
If the application is already `APPROVED`, `REJECTED`, or `MANUAL_REVIEW`:
- no workflow stage is executed again;
- no duplicate history record is created;
- the existing status is not changed;
- the current application state is returned with `200 OK`.
### Approved response
```http
HTTP/1.1 200 OK
Content-Type: application/json
```
```json
{
"loanId": "L-10001",
"status": "APPROVED",
"currentStage": null
}
```
### Rejected response
```http
HTTP/1.1 200 OK
Content-Type: application/json
```
```json
{
"loanId": "L-10001",
"status": "REJECTED",
"currentStage": null
}
```
### Manual-review response
```http
HTTP/1.1 200 OK
Content-Type: application/json
```
```json
{
"loanId": "L-10001",
"status": "MANUAL_REVIEW",
"currentStage": null
}
```
### Loan-not-found response
```http
HTTP/1.1 404 Not Found
Content-Type: application/json
```
```json
{
"error": "LOAN_NOT_FOUND"
}
```
## Get a loan application
Returns the submitted data and current processing state of a loan application.
```http
GET /api/v1/loans/{loanId}
```
### Path parameters
| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `loanId` | `string` | Yes | Unique loan application identifier |
### Success response
```http
HTTP/1.1 200 OK
Content-Type: application/json
```
```json
{
"loanId": "L-10001",
"customerId": "C-1001",
"amount": 400000000,
"phone": "09121234567",
"loanType": "PERSONAL",
"monthlyIncome": 50000000,
"creditScore": 720,
"hasGuarantor": false,
"status": "APPROVED",
"currentStage": null,
"createdAt": "2026-07-15T10:00:00Z",
"updatedAt": "2026-07-15T10:00:03Z"
}
```
### Response fields
| Field | Type | Nullable | Description |
|-----------------|-----------|----------|-------------------------------------------------------|
| `loanId` | `string` | No | Unique loan application identifier |
| `customerId` | `string` | No | Customer identifier |
| `amount` | `integer` | No | Requested loan amount |
| `phone` | `string` | No | Applicant's mobile number |
| `loanType` | `string` | No | Loan type |
| `monthlyIncome` | `integer` | No | Applicant's monthly income |
| `creditScore` | `integer` | No | Applicant's credit score |
| `hasGuarantor` | `boolean` | No | Whether the applicant has a guarantor |
| `status` | `string` | No | Current loan status |
| `currentStage` | `string` | Yes | Current workflow stage; `null` after processing stops |
| `createdAt` | `string` | No | Creation timestamp in ISO 8601 UTC format |
| `updatedAt` | `string` | No | Last-update timestamp in ISO 8601 UTC format |
### Loan-not-found response
```http
HTTP/1.1 404 Not Found
Content-Type: application/json
```
```json
{
"error": "LOAN_NOT_FOUND"
}
```
## Get processing history
Returns workflow stage executions in chronological order.
```http
GET /api/v1/loans/{loanId}/history
```
### Path parameters
| Parameter | Type | Required | Description |
|-----------|----------|----------|------------------------------------|
| `loanId` | `string` | Yes | Unique loan application identifier |
### History rules
- Records are ordered by `timestamp` from oldest to newest.
- A workflow stage is recorded at most once for an application.
- Reprocessing a terminal application does not add history records.
- `reason` contains `SUCCESS` for a successful stage or the applicable business error code for a failed validation.
### Success response
```http
HTTP/1.1 200 OK
Content-Type: application/json
```
```json
[
{
"stage": "VALIDATION",
"result": "PASS",
"timestamp": "2026-07-15T10:00:00Z",
"reason": "SUCCESS"
},
{
"stage": "FRAUD_CHECK",
"result": "PASS",
"timestamp": "2026-07-15T10:00:01Z",
"reason": "SUCCESS"
},
{
"stage": "CREDIT_CHECK",
"result": "PASS",
"timestamp": "2026-07-15T10:00:02Z",
"reason": "SUCCESS"
}
]
```
### History record fields
| Field | Type | Description |
|-------------|----------|----------------------------------------------------------|
| `stage` | `string` | Name of the executed workflow stage |
| `result` | `string` | `PASS`, `FAIL`, or `MANUAL_REVIEW` |
| `timestamp` | `string` | Execution time in ISO 8601 UTC format |
| `reason` | `string` | Reason or business error code associated with the result |
### Loan-not-found response
```http
HTTP/1.1 404 Not Found
Content-Type: application/json
```
```json
{
"error": "LOAN_NOT_FOUND"
}
```
## Health check
Reports whether the service is available.
```http
GET /health
```
### Success response
```http
HTTP/1.1 200 OK
Content-Type: application/json
```
```json
{
"status": "UP"
}
```
## Business rules
### Validation
The `VALIDATION` stage applies the following rules:
| Field | Rule | Failure reason |
|-----------------|---------------------------------------------------------------|--------------------------|
| `customerId` | Required and not empty | `INVALID_CUSTOMER_ID` |
| `amount` | Greater than `0` | `INVALID_AMOUNT` |
| `phone` | Exactly 11 digits, starts with `09`, and contains digits only | `INVALID_PHONE` |
| `loanType` | `PERSONAL` or `BUSINESS` | `INVALID_LOAN_TYPE` |
| `monthlyIncome` | Greater than or equal to `0` | `INVALID_MONTHLY_INCOME` |
| `creditScore` | Between `0` and `1000`, inclusive | `INVALID_CREDIT_SCORE` |
Any validation failure produces a `FAIL` stage result and changes the application status to `REJECTED`.
### Fraud check
The `FRAUD_CHECK` stage is mocked using `customerId`:
| Rule | Result |
|----------------------|-----------------|
| Starts with `FRAUD` | `FAIL` |
| Starts with `REVIEW` | `MANUAL_REVIEW` |
| Any other value | `PASS` |
### Guarantor check
The `GUARANTOR_CHECK` stage runs only for `BUSINESS` loans:
| Rule | Result |
|---------------------------|--------|
| `hasGuarantor` is `false` | `FAIL` |
| `hasGuarantor` is `true` | `PASS` |
### Credit check
The default credit-score rules are:
| Rule | Result |
|----------------------------|-----------------|
| `creditScore < 500` | `FAIL` |
| `500 <= creditScore < 650` | `MANUAL_REVIEW` |
| `creditScore >= 650` | `PASS` |
The score boundaries must be loaded from configuration and must not be hard-coded.
### Manager approval
`MANAGER_APPROVAL` runs when the requested amount is greater than the configured `managerApprovalThreshold`.
| Rule | Result |
|---------------------------------------------|--------|
| `amount > monthlyIncome × incomeMultiplier` | `FAIL` |
| Otherwise | `PASS` |
Both `managerApprovalThreshold` and `incomeMultiplier` must be loaded from configuration.
## Error codes
### HTTP errors
| HTTP status | Error code | Description |
|-------------------|-------------------|------------------------------------------------------|
| `400 Bad Request` | `INVALID_REQUEST` | The request body is not valid JSON |
| `404 Not Found` | `LOAN_NOT_FOUND` | No loan application exists for the supplied `loanId` |
HTTP error responses use this shape:
```json
{
"error": "LOAN_NOT_FOUND"
}
```
### Business validation errors
Business validation errors do not produce HTTP `400` responses during loan creation. They are recorded as the `reason` of the failed `VALIDATION` history entry.
| Error code | Description |
|--------------------------|------------------------------------|
| `INVALID_AMOUNT` | The requested amount is invalid |
| `INVALID_PHONE` | The mobile number is invalid |
| `INVALID_CUSTOMER_ID` | The customer identifier is invalid |
| `INVALID_LOAN_TYPE` | The loan type is invalid |
| `INVALID_CREDIT_SCORE` | The credit score is invalid |
| `INVALID_MONTHLY_INCOME` | The monthly income is invalid |