Mở đầu — vì sao bài này quan trọng
Ở bài trước bạn đã làm quen với Postman — một công cụ giao diện đẹp, dễ dùng để test API. Câu hỏi rất tự nhiên là: "Đã có Postman rồi, học curl làm gì cho cực thân?". Tôi xin trả lời thẳng: vì thực tế công việc của một BA không chỉ xoay quanh công cụ bạn chọn, mà còn xoay quanh ngôn ngữ chung mà cả đội đang dùng.
Hãy hình dung một buổi sáng thứ Hai điển hình. Bạn nhận được một ticket trên Jira từ một bạn dev, kèm dòng mô tả: "API login trả về 401, em đã thử lại bằng curl -X POST https://api.shop.vn/v1/auth/login -d '{...}' mà vẫn lỗi, BA confirm lại spec giúp em". Nếu bạn không đọc được dòng lệnh curl đó, bạn sẽ không hiểu bạn dev đang gửi gì, gửi tới đâu, và lỗi nằm ở đâu. Bạn buộc phải nhắn lại "anh/chị giải thích giúp em" — và uy tín kỹ thuật của bạn trong mắt đội kỹ thuật giảm đi một chút.
curl (đọc là "cơ-lờ" hoặc "see-URL") là công cụ dòng lệnh phổ biến nhất thế giới để gửi HTTP request. Nó có mặt sẵn trên gần như mọi máy Mac, Linux và Windows hiện đại. Quan trọng hơn, nó là "ngôn ngữ viết" mặc định của giới developer: khi dev viết tài liệu kỹ thuật, dán ví dụ trong Slack, hay đưa hướng dẫn tích hợp cho đối tác, họ gần như luôn dùng cú pháp curl. Tài liệu của Stripe, của các cổng thanh toán Việt Nam như VNPay, MoMo, hay tài liệu API của Viettel đều có ví dụ curl.
Với BA, curl không thay thế Postman mà bổ sung cho nó ở ba tình huống: (1) đọc hiểu lệnh dev/đối tác gửi, (2) test nhanh một endpoint mà không cần mở cả phần mềm nặng, và (3) chia sẻ một bug có thể tái hiện được chỉ bằng một dòng text gọn gàng. Bài này sẽ giúp bạn tự tin làm cả ba việc đó.
Khái niệm cốt lõi
curl là gì và nó hoạt động ra sao
curl là viết tắt của "Client URL". Bản chất nó chỉ làm một việc: gửi một HTTP request tới một địa chỉ và in ra phản hồi nhận được. Mọi thứ bạn từng cấu hình trong Postman — phương thức (method), header, body, xác thực (auth) — đều có thể diễn đạt bằng curl thông qua các "cờ" (flag, các tham số bắt đầu bằng dấu gạch ngang).
Một lệnh curl đầy đủ trông như sau:
curl -X POST https://api.shop.vn/v1/orders \
-H "Content-Type: application/json" \
-H "Authorization: Bearer eyJhbGci..." \
-d '{"product_id": 123, "quantity": 2}'
Đọc lệnh này từ trên xuống, bạn sẽ thấy nó tương ứng chính xác với những gì bạn làm trong Postman.
Các cờ (flag) BA cần thuộc lòng
Bạn không cần nhớ hàng trăm tùy chọn của curl. Chỉ cần nắm vững khoảng sáu cờ dưới đây là đủ đọc và viết 95% lệnh trong công việc hằng ngày:
-X(hoặc--request): chỉ định HTTP method. Ví dụ-X POST,-X PUT,-X DELETE. Nếu không ghi gì, mặc định là GET.-H(hoặc--header): thêm một header. Một lệnh có thể có nhiều-H. Đây là nơi đặtContent-Type,Authorization,Accept...-d(hoặc--data): gửi dữ liệu trong body của request. Khi có-dmà không ghi-X, curl tự hiểu là POST.-u(hoặc--user): dùng cho Basic Authentication, viết dạng-u username:password.-i(hoặc--include): in cả phần header của response, không chỉ body. Rất hữu ích để xem status code và header trả về.-v(hoặc--verbose): chế độ "nói nhiều" — in ra toàn bộ quá trình, gồm cả request gửi đi và response nhận về. Đây là cờ quan trọng nhất để debug.
-o ten_file.json để lưu phản hồi ra file, -s (silent) để ẩn thanh tiến trình cho output gọn, và -L để tự động đi theo redirect.Dấu gạch chéo ngược và dấu nháy
Hai chi tiết nhỏ nhưng hay làm BA bối rối khi đọc lệnh. Thứ nhất, dấu \ ở cuối dòng chỉ có nghĩa là "lệnh còn tiếp ở dòng dưới" — nó giúp lệnh dài dễ đọc chứ không thay đổi gì về mặt logic. Thứ hai, phần body trong -d thường được bọc bằng dấu nháy đơn '...'. Lý do là JSON dùng dấu nháy kép "..." bên trong, nên ta phải bọc ngoài bằng nháy đơn để terminal không hiểu nhầm. Khi đọc lệnh, bạn cứ "lột" lớp nháy đơn ngoài cùng ra là thấy được nội dung JSON thật.
Quan hệ với những gì bạn đã học
Hãy nhớ lại cấu trúc HTTP request mà bạn đã học: một request gồm method, URL, headers và body. curl chính là cách viết lại bốn thành phần đó dưới dạng một dòng text. Nắm được điều này, bạn sẽ thấy curl không phải kiến thức mới mà chỉ là một "cách ghi" khác cho thứ bạn đã hiểu.
Tình huống thực tế
Tình huống 1 — Đọc lệnh trong ticket lỗi tích hợp VNPay
Một sàn thương mại điện tử ở TP.HCM, tạm gọi là ShopViet, đang tích hợp cổng thanh toán VNPay. Bạn dev backend gặp lỗi và để lại ticket cho bạn — BA của dự án:
> "Khi tạo URL thanh toán, VNPay trả về lỗi code 70 - sai chữ ký. Em test bằng lệnh này, nhờ BA đối chiếu spec xem field nào sai:
>
> curl -X POST https://sandbox.vnpayment.vn/paymentv2/create \
> -H "Content-Type: application/json" \
> -d '{"vnp_Amount": 5000000, "vnp_OrderInfo": "Thanh toan don 8842", "vnp_TxnRef": "8842"}'
> "Ba tháng trước, một dòng lệnh như vậy có thể khiến bạn hoang mang. Nhưng giờ bạn đọc được: đây là một request POST tới endpoint tạo thanh toán của VNPay sandbox, gửi body JSON với số tiền 5.000.000 (lưu ý VNPay quy ước nhân 100, nên đây là 50.000 đồng), mã đơn 8842. Bạn mở tài liệu VNPay ra đối chiếu và phát hiện ngay vấn đề: body thiếu hẳn các trường bắt buộc vnp_TmnCode, vnp_SecureHash và vnp_CreateDate. Thiếu vnp_SecureHash chính là lý do báo "sai chữ ký".
Bạn phản hồi lại ticket trong mười phút thay vì phải hẹn họp. Bài học: đọc được curl giúp BA tham gia trực tiếp vào việc gỡ lỗi tích hợp, biến mình từ người trung gian thụ động thành người giải quyết vấn đề.
Tình huống 2 — Test nhanh API khi không tiện mở Postman
Bạn đang ở phòng họp với khách hàng, dùng laptop công ty đã cài sẵn nhiều thứ nhưng chưa có Postman, và đường truyền chậm để cài đặt. Khách hàng — một chuỗi cà phê tên The Daily, đang nghi ngờ API danh sách cửa hàng trả sai dữ liệu giá. Bạn cần kiểm tra ngay.
Bạn mở Terminal có sẵn và gõ:
curl -i "https://api.thedaily.vn/v1/stores?city=hanoi&limit=3"
Cờ -i cho bạn thấy ngay dòng đầu phản hồi là HTTP/1.1 200 OK, nghĩa là API hoạt động bình thường, và body JSON liệt kê ba cửa hàng đầu tiên ở Hà Nội kèm trường price_tier. Bạn phát hiện trường price_tier đang trả về "standard" cho một cửa hàng đáng lẽ phải là "premium". Vấn đề không nằm ở app mà nằm ở dữ liệu backend.
Bài học: curl luôn có sẵn, không cần cài đặt, không cần đăng nhập tài khoản, không cần mạng để tải phần mềm. Trong những tình huống "cần ngay tại chỗ", nó là công cụ nhanh nhất để xác nhận một giả thuyết và khoanh vùng lỗi đúng người.
Tình huống 3 — Chia sẻ bug tái hiện được cho đội QA
Một ngân hàng số ở Singapore mở rộng sang thị trường Việt Nam, đội của bạn phụ trách API truy vấn số dư. QA báo "đôi khi API trả lỗi 500" nhưng không nói rõ trường hợp nào. Là BA, bạn ngồi cùng QA, thử nghiệm và tìm ra: lỗi chỉ xảy ra khi tài khoản có ký tự đặc biệt trong mã. Bạn ghi lại bằng curl để đính kèm vào báo cáo:
curl -i -X GET "https://api.smartbank.sg/v2/accounts/AC%23123/balance" \
-H "Authorization: Bearer DEMO_TOKEN"
Bạn dán đúng dòng này vào Jira kèm ghi chú "chạy lệnh trên sẽ tái hiện lỗi 500 — nghi do mã AC#123 chưa được mã hóa URL đúng cách". Bất kỳ dev nào nhận ticket đều có thể copy, dán vào terminal của họ và thấy y hệt lỗi bạn thấy.
Bài học: một bug được mô tả bằng curl là một bug "tái hiện được" (reproducible). Đây là khác biệt giữa một báo cáo lỗi mơ hồ tốn ba ngày qua lại và một báo cáo lỗi được fix trong buổi chiều. curl biến mô tả bằng lời thành bằng chứng có thể chạy.
Hướng dẫn từng bước
Hãy cùng đi qua quy trình một BA thực hiện khi muốn test một endpoint bằng curl. Giả sử ta cần kiểm tra API tạo đơn hàng của ShopViet.
Bước 1 — Mở terminal. Trên macOS mở ứng dụng Terminal; trên Windows 10/11 mở PowerShell hoặc Windows Terminal; cả hai đều có sẵn curl. Gõ curl --version để xác nhận. Nếu hiện ra dòng phiên bản, bạn đã sẵn sàng.
Bước 2 — Bắt đầu từ request GET đơn giản nhất. Trước khi test cái phức tạp, hãy kiểm tra kết nối tới máy chủ:
curl -i https://api.shop.vn/v1/health
Nếu nhận được 200 OK, đường đi tới server thông suốt. Đây là thói quen tốt: luôn xác nhận "đường có thông" trước khi nghi ngờ logic.
Bước 3 — Thêm header. Hầu hết API yêu cầu xác thực. Thêm token bằng cờ -H:
curl -i https://api.shop.vn/v1/orders \
-H "Authorization: Bearer eyJhbGci..."
Bước 4 — Chuyển sang POST và gửi body. Khi cần tạo dữ liệu mới, dùng -X POST cùng -d:
curl -i -X POST https://api.shop.vn/v1/orders \
-H "Content-Type: application/json" \
-H "Authorization: Bearer eyJhbGci..." \
-d '{"product_id": 123, "quantity": 2}'
Lưu ý header Content-Type: application/json — nó báo cho server biết body là JSON. Quên header này là lỗi cực kỳ phổ biến.
Bước 5 — Đọc phản hồi. Nhờ cờ -i, bạn thấy dòng status đầu tiên. 201 Created nghĩa là đơn đã tạo thành công; 400 là body sai; 401 là token sai hoặc hết hạn; 500 là lỗi phía server. Phần JSON bên dưới cho bạn chi tiết.
Bước 6 — Khi có lỗi khó hiểu, bật -v. Thay -i bằng -v để thấy toàn bộ: curl gửi gì đi, server trả gì về, có redirect không, kết nối TLS ra sao. Các dòng bắt đầu bằng > là phần gửi đi, dòng bắt đầu bằng < là phần nhận về. Đây là kính lúp mạnh nhất của bạn.
Bước 7 — Mẹo chuyển đổi với Postman. Bạn không cần gõ tay từ đầu. Trong Postman, sau khi cấu hình xong request, bấm nút "Code" (biểu tượng </>) rồi chọn "cURL" — Postman tự sinh ra lệnh curl hoàn chỉnh để bạn copy. Ngược lại, Postman cũng cho phép "Import" một lệnh curl để biến nó thành request có giao diện. Hai chiều này giúp bạn linh hoạt giữa hai công cụ.
Lỗi thường gặp & mẹo
Quên Content-Type: application/json. Khi gửi body JSON mà thiếu header này, nhiều server hiểu nhầm dữ liệu thành dạng form và báo lỗi 400. Đây là lỗi số một. Cứ có -d chứa JSON là phải có -H "Content-Type: application/json".
Nháy đơn và nháy kép trên Windows. PowerShell xử lý dấu nháy khác với macOS/Linux. Một lệnh chạy ngon trên máy Mac của dev có thể báo lỗi cú pháp trên PowerShell của bạn. Mẹo an toàn: trên Windows, dùng Git Bash hoặc WSL để chạy curl giống hệt môi trường Linux, tránh đau đầu vì dấu nháy.
Nhầm -d mặc định thành POST. Nhiều người tưởng phải luôn ghi -X POST. Thực ra khi có -d, curl tự đặt method là POST. Nếu bạn muốn gửi body bằng method khác như PUT, phải ghi rõ -X PUT. Đọc lệnh của người khác cũng cần nhớ điều này để không hiểu sai method.
Token có khoảng trắng hoặc xuống dòng. Khi copy token dài từ email hay chat, đôi khi dính ký tự xuống dòng làm header sai. Nếu gặp 401 dù chắc token đúng, hãy thử dán lại token vào một dòng liền mạch.
Ký tự đặc biệt trong URL. Như tình huống 3, các ký tự #, &, khoảng trắng trong URL phải được mã hóa (# thành %23, khoảng trắng thành %20). Đây là nguồn lỗi tinh vi mà BA tinh ý có thể phát hiện sớm.
Mẹo bảo mật quan trọng. Token và mật khẩu thật xuất hiện trực tiếp trong lệnh curl. Khi chia sẻ lệnh trong ticket hay chat, hãy thay token thật bằng chữ giả như DEMO_TOKEN hoặc eyJhbGci.... Tôi từng thấy cả token production bị dán công khai trong một group chat — đó là sự cố an ninh nghiêm trọng mà BA hoàn toàn có thể nhắc nhở đội tránh.
Mẹo lưu kết quả. Khi phản hồi dài, thêm -o ketqua.json để lưu ra file rồi mở bằng trình xem JSON, dễ đọc hơn nhiều so với nhìn trên màn hình terminal.
Bài tập thực hành
- Đọc hiểu. Cho lệnh sau, hãy trả lời: method là gì, gửi tới đâu, body chứa gì, và có những header nào?
curl -X PUT https://api.shop.vn/v1/users/42 \
-H "Content-Type: application/json" \
-H "Authorization: Bearer abc123" \
-d '{"name": "Lan Anh", "city": "Da Nang"}'
- Tự viết. Hãy viết một lệnh curl thực hiện GET danh sách sản phẩm tại
https://api.shop.vn/v1/products, lọc theocategory=coffeevà giới hạn 5 kết quả, đồng thời in ra cả header phản hồi.
- Chuyển đổi. Mở Postman, tạo một request POST bất kỳ với body JSON, rồi dùng tính năng "Code → cURL" để sinh ra lệnh curl. So sánh lệnh sinh ra với những gì bạn học trong bài.
- Gỡ lỗi. Một bạn dev gửi lệnh sau và than "API báo 400 mà em không hiểu sao". Hãy chỉ ra lỗi:
curl -X POST https://api.shop.vn/v1/orders \
-d '{"product_id": 7}'
(Gợi ý: hãy nghĩ tới header còn thiếu.)- Thực địa. Tìm một API công khai miễn phí (ví dụ
https://api.github.com/users/torvalds), chạy thử bằngcurl -i, đọc status code và một vài trường trong JSON trả về.
Tóm tắt
curl là công cụ dòng lệnh để gửi HTTP request, và với BA nó không thay thế Postman mà bổ trợ ở ba việc cốt lõi: đọc hiểu lệnh dev và đối tác gửi, test nhanh một endpoint không cần cài đặt, và chia sẻ bug có thể tái hiện được. Bạn chỉ cần thuộc khoảng sáu cờ — -X cho method, -H cho header, -d cho body, -u cho Basic Auth, -i để xem header phản hồi, và -v để gỡ lỗi sâu — là đã đọc và viết được phần lớn lệnh trong công việc.
Hãy nhớ rằng curl chỉ là một "cách ghi" cho cấu trúc HTTP request bạn đã hiểu: method, URL, headers, body. Nắm chắc điều đó, mọi lệnh curl đều trở nên dễ đọc. Đừng quên những bẫy thường gặp: thiếu Content-Type, dấu nháy trên Windows, ký tự đặc biệt trong URL chưa mã hóa, và đặc biệt là không bao giờ để lộ token thật khi chia sẻ lệnh.
Khi bạn đọc trôi chảy một dòng curl trong ticket và phản hồi chính xác nơi sai sót, bạn không còn là BA "chỉ biết viết tài liệu" mà trở thành người đồng hành kỹ thuật thực thụ của đội. Đó chính là giá trị mà một dòng lệnh tưởng nhỏ này mang lại cho sự nghiệp của bạn.