# 2. API Design & Response Standard

## 2.1. Mục Tiêu Chương

Chương này quy định cấu trúc chuẩn của mỗi integration flow và trách nhiệm của từng artifact layer nhằm:

- Tách biệt rõ ràng các tầng xử lý trong luồng tích hợp
- Giảm phụ thuộc giữa các thành phần artifact
- Dễ bảo trì, mở rộng và kiểm thử từng layer độc lập
- Đảm bảo tính nhất quán giữa các flow trong toàn hệ thống

## 2.2. Khái Niệm / Phạm Vi Áp Dụng

Quy tắc này áp dụng cho:

- Tất cả các integration flow trong thư mục `artifacts/**`
- Cả **Core Team** và **Partner Team**
- Tất cả các luồng tích hợp mới được phát triển

<span style="color: rgb(34, 34, 34); font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Oxygen, Ubuntu, Roboto, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; font-size: 2.333em; font-weight: 400;">Cấu Trúc Artifact Chuẩn</span>

Mỗi integration flow gồm các thành phần sau:[![image.png](https://docs.lifetex.vn/uploads/images/gallery/2026-02/scaled-1680-/F6Simage.png)](https://docs.lifetex.vn/uploads/images/gallery/2026-02/F6Simage.png)

##### Ý Nghĩa Từng Artifact Layer

<table border="1" id="bkmrk-layer-artifact-vai-t" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 25.0271%;"></col><col style="width: 25.0271%;"></col><col style="width: 25.0271%;"></col><col style="width: 25.0271%;"></col></colgroup><tbody><tr><th class="bg-gray-500/20 px-6 py-2 text-left font-medium">Layer</th><th class="bg-gray-500/20 px-6 py-2 text-left font-medium">Artifact</th><th class="bg-gray-500/20 px-6 py-2 text-left font-medium">Vai trò</th><th class="bg-gray-500/20 px-6 py-2 text-left font-medium">Ví dụ</th></tr><tr><td class="px-6 py-2">**API Layer**</td><td class="px-6 py-2">`apis/*.xml`</td><td class="px-6 py-2">Nhận request từ client và trả response</td><td class="px-6 py-2"><div>  
</div><span class="inline-flex items-center gap-0.5 rounded-md align-middle text-sm font-medium transition-[opacity,background-color] cursor-pointer hover:bg-gray-500/20 select-text translate-y-[-1px]" draggable="true"><span class="inline-flex break-all">KafkaProducerApi.xml</span></span>, <div>  
</div><span class="inline-flex items-center gap-0.5 rounded-md align-middle text-sm font-medium transition-[opacity,background-color] cursor-pointer hover:bg-gray-500/20 select-text translate-y-[-1px]" draggable="true"><span class="inline-flex break-all">PlanningDirectApi.xml</span></span></td></tr><tr><td class="px-6 py-2">**Mediation Layer**</td><td class="px-6 py-2">`sequences/*-inboundSequence.xml`</td><td class="px-6 py-2">Xử lý logic, điều phối luồng</td><td class="px-6 py-2"><div>  
</div><span class="inline-flex items-center gap-0.5 rounded-md align-middle text-sm font-medium transition-[opacity,background-color] cursor-pointer hover:bg-gray-500/20 select-text translate-y-[-1px]" draggable="true"><span class="inline-flex break-all">Load\_balance\_example-inboundSequence.xml</span></span></td></tr><tr><td class="px-6 py-2">**Error Layer**</td><td class="px-6 py-2">`sequences/*-inboundErrorSequence.xml`</td><td class="px-6 py-2">Xử lý và cô lập lỗi</td><td class="px-6 py-2"><div>  
</div><span class="inline-flex items-center gap-0.5 rounded-md align-middle text-sm font-medium transition-[opacity,background-color] cursor-pointer hover:bg-gray-500/20 select-text translate-y-[-1px]" draggable="true"><span class="inline-flex break-all">Load\_balance\_example-inboundErrorSequence.xml</span></span></td></tr><tr><td class="px-6 py-2">**Consumer Layer**</td><td class="px-6 py-2">`inbound-endpoints/*.xml`</td><td class="px-6 py-2">Nhận message từ Kafka topic</td><td class="px-6 py-2"><div>  
</div><span class="inline-flex items-center gap-0.5 rounded-md align-middle text-sm font-medium transition-[opacity,background-color] cursor-pointer hover:bg-gray-500/20 select-text translate-y-[-1px]" draggable="true"><span class="inline-flex break-all">Load\_balance\_example.xml</span></span></td></tr><tr><td class="px-6 py-2">**Connection Layer**</td><td class="px-6 py-2">`local-entries/*.xml`</td><td class="px-6 py-2">Cấu hình kết nối dùng chung</td><td class="px-6 py-2"><div>  
</div><span class="inline-flex items-center gap-0.5 rounded-md align-middle text-sm font-medium transition-[opacity,background-color] cursor-pointer hover:bg-gray-500/20 select-text translate-y-[-1px]" draggable="true"><span class="inline-flex break-all">KafkaConnection.xml</span></span></td></tr><tr><td class="px-6 py-2">**Endpoint Layer**</td><td class="px-6 py-2">`endpoints/*.xml`</td><td class="px-6 py-2">Định nghĩa backend endpoint</td><td class="px-6 py-2">Backend API address</td></tr></tbody></table>

## 2.3. Quy Định Chính

### Trách Nhiệm Từng Layer

#### API Layer (`apis/`)

- Nhận request HTTP từ client (hoặc từ WSO2 APIM Gateway)
- Gọi backend trực tiếp hoặc publish message lên Kafka
- Trả response chuẩn về client
- **Không** chứa logic nghiệp vụ phức tạp

#### Mediation Layer (`sequences/*-inboundSequence.xml`)

- Xử lý message nhận từ Kafka consumer
- Điều phối lời gọi đến backend API
- Phân loại kết quả theo HTTP status code (2xx / 4xx / 5xx)
- Publish kết quả vào `processed_topic` hoặc `error_topic`
- **Không** xử lý lỗi kỹ thuật (dành cho Error Layer)

#### Error Layer (`sequences/*-inboundErrorSequence.xml`)

- Bắt lỗi kỹ thuật khi consume message từ Kafka
- Log đầy đủ thông tin: `ERROR_CODE`, `ERROR_MESSAGE`, `ORIGINAL_PAYLOAD`
- Đóng gói và publish message lỗi vào `error_topic`
- **Không** retry — chỉ ghi nhận và chuyển sang error topic

#### Consumer Layer (`inbound-endpoints/`)

- Kết nối đến Kafka broker và subscribe topic
- Khai báo `sequence` (luồng thành công) và `onError` (luồng lỗi)
- **Không** chứa logic xử lý

#### Connection Layer (`local-entries/`)

- Lưu thông tin kết nối Kafka dùng chung toàn hệ thống
- Chỉ Core Team được phép chỉnh sửa

### Quy Tắc Bắt Buộc

<p class="callout info"> **API Layer không được chứa logic nghiệp vụ phức tạp**</p>

<p class="callout info">**Mọi response trả về client phải theo cấu trúc JSON chuẩn**</p>

<p class="callout info">**Error sequence phải luôn publish message vào `error_topic`**</p>

<p class="callout info">**Mediation sequence phải phân loại HTTP status (2xx / 4xx / 5xx)**</p>

### Cấu Trúc Response Chuẩn

**Thành công:**

```json
{
  "success": true,
  "message": "Hồ sơ đã được gửi thành công"
}

```

**Thành công kèm data:**

```json
{
  "eventType": "transaction",
  "source": "<sequence-name>",
  "data": { ... }
}

```

**Lỗi từ API Layer:**

```json
{
  "success": false,
  "httpStatus": "400",
  "error": { ... }
}

```

**Lỗi kỹ thuật (Error Sequence ghi vào `error_topic`):**

```json
{
  "errorSource": "Load_balance_example-inboundEndpoint",
  "sourceTopic": "test_topic_01",
  "errorType": "KAFKA_CONSUME_ERROR",
  "errorCode": "...",
  "errorMessage": "...",
  "originalPayload": { ... },
  "timestamp": "..."
}

```

## 2.4. Cách Thực Hiện / Quy Trình

### Quy Trình Phát Triển Một Integration Flow Mới

**Bước 1: Khai báo Connection (nếu chưa có)**

Tạo hoặc tái sử dụng <span class="inline-flex items-center gap-0.5 rounded-md align-middle text-sm font-medium transition-[opacity,background-color] cursor-pointer hover:bg-gray-500/20 select-text translate-y-[-1px]" draggable="true">`local-entries/KafkaConnection.xml`</span>.

<p class="callout warning">Chỉ Core Team thực hiện bước này.</p>

**Bước 2: Tạo Inbound Endpoint**

Tạo file `inbound-endpoints/<flow-name>.xml`:

- Khai báo Kafka broker, topic, group ID
- Trỏ `sequence` đến inbound sequence
- Trỏ `onError` đến error sequence

**Bước 3: Tạo Error Sequence**

Tạo file `sequences/<flow-name>-inboundErrorSequence.xml`:

- Log đầy đủ `ERROR_CODE`, `ERROR_MESSAGE`, `ORIGINAL_PAYLOAD`
- Build payload lỗi chuẩn
- Publish vào `error_topic`

**Bước 4: Tạo Inbound Sequence**

Tạo file `sequences/<flow-name>-inboundSequence.xml`:

- Log message nhận được
- Set header xác thực
- Gọi backend API (`<call>`)
- Phân loại theo HTTP status: 
    - `200 / 201` → publish vào `processed_topic`
    - `4xx` → đóng gói lỗi dữ liệu → publish vào `error_topic`
    - `5xx` → đóng gói lỗi backend → publish vào `error_topic`

**Bước 5: Tạo API (nếu cần điểm vào HTTP)**

Tạo file `apis/<flow-name>Api.xml`:

- Khai báo context path và method
- Set header, gọi backend hoặc publish Kafka
- Trả response chuẩn theo HTTP status

[![ho-so-core-flow (1).jpg](https://docs.lifetex.vn/uploads/images/gallery/2026-02/scaled-1680-/ho-so-core-flow-1.jpg)](https://docs.lifetex.vn/uploads/images/gallery/2026-02/ho-so-core-flow-1.jpg)

## 2.5. Ví Dụ Minh Họa

### Ví Dụ Đúng — Inbound Sequence phân loại HTTP Status

```xml
<!-- Thành công: publish vào processed_topic -->
<filter xpath="get-property('HTTP_STATUS') = '200' or get-property('HTTP_STATUS') = '201'">
    <then>
        <log level="custom">
            <property name="STATUS" value="[KafkaConsumer][SUCCESS] Backend xử lý thành công"/>
        </log>
        <payloadFactory media-type="json" template-type="default">
            <format>{
                "eventType": "transaction",
                "source": "Load_balance_example-inboundSequence",
                "data": ${payload}
            }</format>
        </payloadFactory>
        <kafkaTransport.publishMessages configKey="KafkaConnection">
            <topic>processed_topic</topic>
        </kafkaTransport.publishMessages>
    </then>
    <else>
        <!-- Lỗi: publish vào error_topic -->
        <kafkaTransport.publishMessages configKey="KafkaConnection">
            <topic>error_topic</topic>
        </kafkaTransport.publishMessages>
    </else>
</filter>

```

**Đúng vì:**

- Phân loại rõ 2xx (thành công) và lỗi
- Kết quả thành công đi vào `processed_topic`
- Lỗi được tách riêng vào `error_topic`
- Sequence không xử lý lỗi kỹ thuật (để cho Error Sequence)

<span style="color: rgb(34, 34, 34); font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Oxygen, Ubuntu, Roboto, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; font-size: 2.333em; font-weight: 400;">Ví Dụ Đúng — Error Sequence đóng gói lỗi chuẩn</span>

```xml
<sequence name="Load_balance_example-inboundErrorSequence">
    <!-- Bước 1: Lưu thông tin lỗi -->
    <property name="ERROR_CODE"      expression="get-property('ERROR_CODE')"    scope="default"/>
    <property name="ERROR_MESSAGE"   expression="get-property('ERROR_MESSAGE')" scope="default"/>
    <property name="ORIGINAL_PAYLOAD" expression="json-eval($)"                 scope="default"/>

    <!-- Bước 2: Log chi tiết -->
    <log level="custom">
        <property name="STATUS"         value="[KafkaConsumer][ERROR] Lỗi khi xử lý message"/>
        <property name="ERROR_CODE"     expression="get-property('ERROR_CODE')"/>
        <property name="ERROR_MESSAGE"  expression="get-property('ERROR_MESSAGE')"/>
    </log>

    <!-- Bước 3: Đóng gói payload lỗi -->
    <payloadFactory media-type="json">
        <format>{
            "errorSource": "Load_balance_example-inboundEndpoint",
            "sourceTopic": "test_topic_01",
            "errorType":   "KAFKA_CONSUME_ERROR",
            "errorCode":   "$1",
            "errorMessage":"$2",
            "originalPayload": $3
        }</format>
    </payloadFactory>

    <!-- Bước 4: Publish vào error_topic -->
    <kafkaTransport.publishMessages configKey="KafkaConnection">
        <topic>error_topic</topic>
    </kafkaTransport.publishMessages>
</sequence>

```

###  Ví Dụ Sai — Không phân loại HTTP Status

```xml
<!-- SAI: Không kiểm tra status, trả về luôn -->
<call>
    <endpoint>
        <address uri="http://192.168.0.133:8080/api/v1/plannings"/>
    </endpoint>
</call>
<respond/>

```

**Sai vì:**

- Không kiểm tra HTTP status code từ backend
- Lỗi 4xx / 5xx không được phân loại, không vào `error_topic`
- Không log trạng thái xử lý

###  Ví Dụ Sai — API trả về raw data không theo chuẩn

```xml
<!-- SAI: Không wrap response theo chuẩn -->
<payloadFactory media-type="json">
    <format>{"data": "ok"}</format>
</payloadFactory>
<respond/>

```

**Sai vì:**

- Response không nhất quán với chuẩn `success / error` toàn hệ thống

## 2.6. Checklist Áp Dụng

Trước khi commit integration flow mới:

- [ ]  Có đủ: `inbound-endpoint`, `inboundSequence`, `inboundErrorSequence`
- [ ]  Inbound Sequence có phân loại HTTP status (2xx / 4xx / 5xx)
- [ ]  Thành công publish vào `processed_topic`
- [ ]  Lỗi publish vào `error_topic`
- [ ]  Error Sequence log đầy đủ: `ERROR_CODE`, `ERROR_MESSAGE`, `ORIGINAL_PAYLOAD`
- [ ]  Error Sequence đóng gói payload lỗi theo cấu trúc chuẩn
- [ ]  API Layer trả response theo cấu trúc JSON chuẩn (`success`, `error`)
- [ ]  Không hardcode thông tin kết nối trong Sequence (dùng `local-entries`)
- [ ]  PR đã được Core Team review

*Tài liệu này thuộc phạm vi quản lý của **Core Team** — mọi thay đổi phải được Core Team phê duyệt.*

<div class="absolute select-none shadow rounded-md" id="bkmrk--1"></div><div align="left" dir="ltr" id="bkmrk--3"></div>