Mở đầu — vì sao bài này quan trọng
Cách đây vài năm, một BA chỉ cần hiểu nghiệp vụ là đủ. Nhưng thế giới đã thay đổi. Hôm nay, gần như mọi hệ thống bạn phân tích đều "nói chuyện" với hệ thống khác qua API. Ứng dụng ngân hàng gọi API để lấy tỷ giá. App giao hàng gọi API bản đồ của Google. Ví điện tử MoMo gọi API của ngân hàng để trừ tiền. Khi bạn ngồi họp với team kỹ thuật và họ nói "cái này mình lấy qua API rồi map vào màn hình", nếu bạn gật gù mà không hiểu, bạn đang đánh mất quyền kiểm soát yêu cầu của chính mình.
Một sự thật phũ phàng: rất nhiều requirement defect (lỗi yêu cầu) trong các dự án tích hợp không nằm ở phần "màn hình hiển thị gì", mà nằm ở phần "hệ thống A gửi gì cho hệ thống B, và B trả về gì". Đó chính là tầng API. Nếu bạn không hiểu nó, bạn sẽ viết requirement mơ hồ kiểu "hệ thống lấy thông tin khách hàng", còn dev sẽ tự đoán — và họ thường đoán sai.
Tin tốt là: bạn KHÔNG cần biết lập trình để hiểu API ở mức của một BA giỏi. Bạn cần hiểu ba thứ cốt lõi mà bài này sẽ dạy: kiến trúc REST (cách hệ thống gọi nhau), định dạng JSON (cách dữ liệu được đóng gói), và HTTP status code (cách hệ thống báo thành công hay thất bại). Nắm vững ba thứ này, bạn sẽ đọc được tài liệu kỹ thuật, viết được requirement tích hợp rõ ràng, và quan trọng nhất: nói cùng ngôn ngữ với dev mà không bị "ngợp".
Khái niệm cốt lõi
API là gì — giải thích bằng ngôn ngữ đời thường
API (Application Programming Interface) là "hợp đồng giao tiếp" giữa hai phần mềm. Hãy tưởng tượng bạn vào một nhà hàng. Bạn không xông thẳng vào bếp để tự nấu. Bạn gọi món qua người phục vụ (waiter). Người phục vụ cầm order vào bếp, bếp nấu xong đưa món ra, người phục vụ mang ra cho bạn.
Trong câu chuyện này:
- Bạn = ứng dụng đang cần dữ liệu (client).
- Nhà bếp = hệ thống đang nắm dữ liệu (server).
- Người phục vụ = API.
- Thực đơn = tài liệu API (cho biết bạn được phép gọi món gì).
REST — kiến trúc API phổ biến nhất
REST viết tắt của REpresentational State Transfer. Đây không phải một công nghệ cụ thể mà là một phong cách thiết kế API, hiện chiếm đa số trên thị trường. Bạn sẽ gặp REST API trong 8/10 dự án.
Tư tưởng cốt lõi của REST: mọi thứ trong hệ thống đều là một resource (tài nguyên), và mỗi resource có một địa chỉ riêng gọi là endpoint (một URL). Ví dụ:
https://api.shop.vn/products— danh sách sản phẩmhttps://api.shop.vn/products/123— sản phẩm có mã 123https://api.shop.vn/customers/456/orders— các đơn hàng của khách hàng 456
| HTTP method | Hành động | Ý nghĩa | Ví dụ thực tế |
|---|---|---|---|
| GET | Đọc | Lấy dữ liệu, không thay đổi gì | Xem danh sách sản phẩm, xem chi tiết đơn hàng |
| POST | Tạo mới | Tạo một resource mới | Tạo đơn hàng mới, đăng ký tài khoản |
| PUT | Cập nhật toàn bộ | Thay thế toàn bộ một resource | Cập nhật toàn bộ hồ sơ khách hàng |
| PATCH | Cập nhật một phần | Sửa vài trường của resource | Đổi mỗi số điện thoại khách hàng |
| DELETE | Xóa | Xóa một resource | Hủy đơn hàng, xóa địa chỉ giao |
REST còn có một đặc tính quan trọng gọi là stateless (phi trạng thái): mỗi lời gọi API là độc lập, server không nhớ lời gọi trước đó. Mỗi lần gọi, client phải gửi đủ thông tin (kể cả token xác thực). Điều này ảnh hưởng đến cách bạn viết requirement về phiên đăng nhập và bảo mật.
JSON — ngôn ngữ đóng gói dữ liệu
Khi API trả dữ liệu về, nó phải đóng gói theo một định dạng. Định dạng phổ biến nhất hiện nay là JSON (JavaScript Object Notation). JSON dễ đọc cho cả người lẫn máy. Một BA cần đọc được JSON như đọc một cái form.
JSON có hai cấu trúc cơ bản:
- Object (đối tượng) — bọc trong dấu
{ }, gồm các cặp"khóa": giá trị. - Array (mảng/danh sách) — bọc trong dấu
[ ], chứa nhiều phần tử.
{
"customerId": 456,
"fullName": "Nguyễn Văn An",
"phone": "0901234567",
"isVerified": true,
"addresses": [
{ "city": "Hồ Chí Minh", "isDefault": true },
{ "city": "Hà Nội", "isDefault": false }
]
}
Cách đọc: khách hàng mã 456, tên "Nguyễn Văn An", đã xác thực (true), có 2 địa chỉ trong đó địa chỉ TP.HCM là mặc định. Các kiểu dữ liệu bạn cần phân biệt: chuỗi (trong nháy kép "..."), số (không nháy 456), boolean (true/false), null (rỗng), object lồng nhau và array.
Tại sao BA phải đọc được JSON? Vì khi bạn định nghĩa requirement "màn hình chi tiết khách hàng hiển thị tên, SĐT và địa chỉ mặc định", bạn cần đối chiếu xem API có trả về đủ các trường đó không. Nếu API không trả isDefault, dev không thể biết địa chỉ nào là mặc định — và đó là một lỗ hổng requirement bạn phải phát hiện sớm.
HTTP status code — hệ thống báo thành công hay thất bại thế nào
Mỗi lần gọi API, server trả về một mã số 3 chữ số gọi là status code, cho biết kết quả. BA phải hiểu các nhóm mã này để định nghĩa cách hệ thống xử lý lỗi và thông báo cho người dùng.
Các mã chia theo nhóm (chữ số đầu tiên):
- 2xx — Thành công.
200 OK(lấy/cập nhật thành công),201 Created(tạo mới thành công). - 3xx — Chuyển hướng.
301 Moved Permanently(resource đã chuyển địa chỉ). BA ít gặp nhóm này. - 4xx — Lỗi do phía client (người gọi sai).
400 Bad Request(dữ liệu gửi lên sai định dạng),401 Unauthorized(chưa đăng nhập/sai token),403 Forbidden(đã đăng nhập nhưng không có quyền),404 Not Found(không tìm thấy resource),409 Conflict(xung đột, ví dụ trùng dữ liệu),429 Too Many Requests(gọi quá nhiều, bị chặn). - 5xx — Lỗi do phía server.
500 Internal Server Error(server bị lỗi),503 Service Unavailable(server quá tải/bảo trì).
Tình huống thực tế
Tình huống 1 — Tiki tích hợp cổng thanh toán và bài học về status code
Một sàn TMĐT giả định lấy bối cảnh giống Tiki triển khai thanh toán qua ví điện tử. Luồng đặt hàng gọi API tạo giao dịch: POST /payments với JSON chứa số tiền và mã đơn hàng. Trong requirement ban đầu, BA chỉ viết: "Sau khi thanh toán, hiển thị màn hình thành công."
Khi vận hành thực tế, sự cố xảy ra. Có lúc API ví trả về 402 Payment Required (số dư không đủ), có lúc trả 409 Conflict (đơn này đã thanh toán rồi do khách bấm hai lần), có lúc trả 503 (ví đang bảo trì). Nhưng vì requirement chỉ định nghĩa trường hợp 200, hệ thống xử lý mọi lỗi giống nhau: hiện màn hình trắng. Khách hàng hoang mang, có người bị trừ tiền nhưng đơn báo thất bại, tổng đài nhận hàng trăm cuộc gọi.
Diễn giải: vấn đề không nằm ở dev. Dev làm đúng những gì requirement viết. Vấn đề là BA không liệt kê các status code mà API có thể trả về, nên không định nghĩa hành vi tương ứng.
Bài học: với mỗi lời gọi API quan trọng, BA phải lập một bảng "status code → hành vi hệ thống → thông báo cho người dùng". Ví dụ: 200 → ghi nhận, hiện màn hình thành công; 402 → "Số dư không đủ, vui lòng chọn phương thức khác"; 409 → kiểm tra trạng thái đơn, không trừ tiền lần hai; 503 → "Cổng thanh toán đang bảo trì, vui lòng thử lại sau 5 phút". Bảng này chính là phần "vàng" trong requirement tích hợp.
Tình huống 2 — Giao Hàng Nhanh và sự khác biệt POST vs PUT
Một công ty logistics giả định kiểu Giao Hàng Nhanh xây tính năng cho shop tạo và cập nhật đơn vận chuyển qua API. BA viết requirement: "Shop gọi API để lưu đơn vận chuyển." Từ "lưu" mơ hồ này gây ra rắc rối lớn.
Dev hiểu "lưu" là POST /shipments (tạo mới). Nhưng nghiệp vụ thực tế là: lần đầu shop tạo đơn (POST), nhưng sau đó shop có thể sửa địa chỉ người nhận nếu khách đổi ý (cập nhật). Vì requirement không phân biệt, mỗi lần shop bấm "lưu" sau khi sửa, hệ thống lại POST tạo ra một đơn vận chuyển MỚI. Kết quả: một khách hàng có 3 đơn trùng, shipper bối rối không biết giao đơn nào, kho bị nhân ba số liệu.
Diễn giải: ranh giới giữa "tạo mới" (POST) và "cập nhật" (PUT/PATCH) là ranh giới nghiệp vụ, không phải chuyện kỹ thuật thuần túy. BA là người phải vẽ ra ranh giới này.
Bài học: khi viết requirement tích hợp, đừng dùng từ chung chung như "lưu", "xử lý", "đẩy dữ liệu". Hãy chỉ rõ động từ HTTP tương ứng với hành động nghiệp vụ: "Khi shop tạo đơn lần đầu → POST /shipments. Khi shop sửa địa chỉ của đơn đã tạo → PATCH /shipments/{id}." Sự rõ ràng này loại bỏ hoàn toàn lỗi trùng dữ liệu.
Tình huống 3 — VPBank và bài học đọc JSON để phát hiện thiếu trường
Một ngân hàng giả định kiểu VPBank làm màn hình tổng quan tài khoản trong app mobile. Thiết kế UI yêu cầu hiển thị: số dư khả dụng, số dư bị phong tỏa, và ngày giao dịch gần nhất. BA cứ tưởng API core banking trả đủ, nên viết requirement và chuyển cho team mobile.
Đến sprint review, team mobile báo: API chỉ trả về JSON gồm availableBalance (số dư khả dụng) và accountNumber, KHÔNG có holdAmount (số dư phong tỏa) và lastTransactionDate. Hai trường UI cần thì API không cung cấp. Phải mở thêm yêu cầu cho team core banking, chờ thêm một sprint nữa, dự án trễ hạn.
Diễn giải: nếu BA đọc kỹ JSON response mẫu (sample response) ngay từ đầu và đối chiếu với từng phần tử trên màn hình thiết kế, lỗ hổng này được phát hiện ngay tuần đầu thay vì đến tận review.
Bài học: một kỹ thuật cực mạnh của BA giỏi là field-level traceability — đối chiếu từng trường trên UI với từng khóa trong JSON của API. Lập một bảng hai cột: "Trường hiển thị trên màn hình" và "Khóa JSON tương ứng trong response". Trường nào không tìm thấy khóa tương ứng chính là rủi ro, cần làm rõ với team backend trước khi bắt đầu code.
Hướng dẫn từng bước
Đây là quy trình một BA nên làm khi phân tích một requirement liên quan đến API:
- Xác định luồng nghiệp vụ cần dữ liệu gì. Bắt đầu từ màn hình hoặc hành động người dùng, hỏi: bước này cần đọc hay ghi dữ liệu gì? Dữ liệu đó nằm ở hệ thống nào?
- Map mỗi hành động nghiệp vụ thành một lời gọi API. Với mỗi hành động, xác định method + endpoint. "Xem chi tiết đơn" →
GET /orders/{id}. "Hủy đơn" →DELETE /orders/{id}hoặcPATCH /orders/{id}(đổi trạng thái). Ghi rõ trong requirement.
- Xác định request — dữ liệu gửi đi. Với POST/PUT/PATCH, liệt kê các trường cần gửi trong JSON, trường nào bắt buộc, trường nào tùy chọn, kiểu dữ liệu là gì.
- Xác định response — dữ liệu nhận về. Lấy sample JSON response từ team backend. Đối chiếu từng khóa với từng phần tử cần hiển thị. Lập bảng field-level traceability.
- Liệt kê các status code có thể xảy ra và định nghĩa hành vi. Với mỗi mã 2xx/4xx/5xx có khả năng, viết rõ hệ thống làm gì và hiển thị thông báo gì cho người dùng.
- Làm rõ xác thực và quyền. API có cần token không? Token lấy từ đâu? Lỗi
401/403xử lý ra sao? (Chi tiết về authentication/authorization sẽ học sâu ở bài bảo mật riêng.)
- Rà soát lại cùng dev. Mang bảng đã lập đi review với một developer. Đây là lúc bạn phát hiện những giả định sai trước khi chúng trở thành lỗi tốn kém.
Lỗi thường gặp & mẹo
Lỗi 1 — Viết requirement tích hợp bằng từ mơ hồ. "Hệ thống lấy thông tin khách hàng", "đẩy dữ liệu sang ERP". Những câu này khiến dev tự đoán. Mẹo: luôn cụ thể hóa thành method + endpoint + các trường JSON cụ thể.
Lỗi 2 — Chỉ định nghĩa happy path, bỏ quên error path. Đa số BA mới chỉ mô tả khi mọi thứ thành công (200). Mẹo: với mỗi lời gọi API, ép bản thân trả lời câu hỏi "nếu trả về 4xx thì sao? nếu 5xx thì sao?". Đây là nơi requirement chất lượng cao tỏa sáng.
Lỗi 3 — Nhầm 4xx và 5xx khi thiết kế thông báo. Đừng hiện "Bạn nhập sai dữ liệu" khi thực ra lỗi là 500 (server hỏng). Mẹo: nhớ câu thần chú 4xx-tại-bạn / 5xx-tại-server để chọn đúng thông điệp và đúng cơ chế xử lý (báo người dùng sửa input vs. tự retry).
Lỗi 4 — Không lấy sample response thật. Đọc tài liệu suông không bằng nhìn một JSON response thật. Mẹo: luôn xin team backend một file JSON mẫu, hoặc tự gọi thử API bằng công cụ (Postman — sẽ học ở bài kế tiếp).
Lỗi 5 — Bỏ qua phân trang (pagination). Khi API trả danh sách dài (ví dụ 10.000 sản phẩm), nó thường chia thành nhiều trang. Mẹo: hỏi rõ API có phân trang không, mỗi trang bao nhiêu phần tử, và định nghĩa cách màn hình "tải thêm" hoạt động.
Mẹo vàng: giữ một "cheat sheet" cá nhân gồm bảng HTTP method và bảng status code dán cạnh màn hình. Sau vài tuần, bạn sẽ thuộc lòng và đọc tài liệu API trôi chảy như đọc tiếng mẹ đẻ.
Bài tập thực hành
Bài tập 1 — Đọc và dịch lời gọi API. Cho các lời gọi sau, hãy viết bằng tiếng Việt ý nghĩa của chúng: (a) GET /customers/456/orders, (b) POST /orders, (c) PATCH /orders/789, (d) DELETE /addresses/12. Tự kiểm: bạn có ghép đúng động từ với danh từ không?
Bài tập 2 — Đọc JSON. Lấy đoạn JSON khách hàng ở phần Khái niệm cốt lõi. Trả lời: khách này đã xác thực chưa? Có mấy địa chỉ? Địa chỉ mặc định ở thành phố nào? Khóa nào là array, khóa nào là boolean?
Bài tập 3 — Lập bảng status code. Bạn đang làm tính năng "đăng ký tài khoản" qua POST /users. Hãy liệt kê ít nhất 4 status code có thể xảy ra (gợi ý: 201, 400, 409, 500) và với mỗi mã, viết hành vi hệ thống + thông báo hiển thị cho người dùng.
Bài tập 4 — Field-level traceability. Lấy một màn hình bất kỳ trong sản phẩm bạn đang làm (hoặc một app bạn dùng hằng ngày). Liệt kê tất cả thông tin hiển thị, rồi giả định JSON response cần có những khóa nào để màn hình đó hoạt động. Trường nào nếu thiếu sẽ làm hỏng màn hình?
Bài tập 5 — Phân biệt POST/PUT/PATCH/DELETE. Với nghiệp vụ "quản lý giỏ hàng", hãy map các hành động sau thành method + endpoint phù hợp: thêm sản phẩm vào giỏ, đổi số lượng một sản phẩm, xóa một sản phẩm, xem giỏ hàng hiện tại.
Tóm tắt
API là tầng giao tiếp giữa các phần mềm, và ngày nay không một BA nào có thể né tránh nó. Bài này trang bị cho bạn ba trụ cột nền tảng. REST là phong cách thiết kế API phổ biến nhất, dựa trên ý tưởng resource (endpoint) cộng với HTTP method (GET đọc, POST tạo, PUT/PATCH sửa, DELETE xóa) — ghép động từ với danh từ là bạn đọc được mọi lời gọi. JSON là định dạng đóng gói dữ liệu, gồm object {} và array [], mà BA phải đọc trôi chảy để đối chiếu với từng phần tử trên giao diện. HTTP status code cho biết kết quả: 2xx thành công, 4xx lỗi tại client, 5xx lỗi tại server — ranh giới này quyết định cách bạn thiết kế xử lý lỗi và thông báo.
Quan trọng hơn cả việc thuộc lý thuyết là ba thói quen thực hành: cụ thể hóa requirement tích hợp thành method + endpoint + trường JSON cụ thể; luôn định nghĩa cả error path chứ không chỉ happy path; và áp dụng field-level traceability để đối chiếu UI với response thật. Ba thói quen này phân biệt một BA chỉ "biết về API" với một BA thực sự kiểm soát được chất lượng yêu cầu tích hợp. Ở bài tiếp theo, bạn sẽ học cách tự tay thử nghiệm và tài liệu hóa API bằng Postman và Swagger/OpenAPI — biến kiến thức lý thuyết hôm nay thành kỹ năng thao tác thực tế.