Phần trước ta gọi Odoo bằng XML-RPC — chuẩn, chạy mọi ngôn ngữ, nhưng payload XML cồng kềnh và không tự nhiên với JavaScript. Khi client là web/JS (một app React đọc điểm thành viên, một trang tự viết gọi Odoo), có lựa chọn gọn hơn: JSON-RPC. Cùng khả năng — đăng nhập, search_read, create, gọi mọi method — nhưng gói tin là JSON, gọi thẳng từ fetch() không cần thư viện. Bài này chỉ endpoint /jsonrpc, cấu trúc gói tin, và chạy thật bằng curl trên Odoo 19.
Endpoint /jsonrpc: một POST JSON
Thay vì hai địa chỉ như XML-RPC, JSON-RPC dùng đúng một endpoint /jsonrpc, nhận một POST JSON. Trong params, service chọn common (đăng nhập) hay object (gọi model), và args là danh sách tham số y hệt execute_kw.

Hình 1: Gói tin /jsonrpc. params.service = common/object, params.method = authenticate/execute_kw, params.args chứa [db, uid, pass, model, method, [args], {kwargs}]. Phản hồi luôn bọc trong {"jsonrpc","id","result"} (hoặc "error"). Phần dưới: gọi thẳng từ fetch() — đây là lý do JSON-RPC hợp JavaScript.
Chạy thật bằng curl
curl -X POST với thân JSON, đây là kết quả sống trên Odoo 19:

Hình 2: Thật. (1) authenticate → "result": 2 (uid). (2) execute_kw/search_read → "result" là mảng 4 thẻ. (3) version → 19.0-20260908. Khác XML-RPC ở chỗ mọi thứ là JSON, và kết quả nằm trong khoá "result" của phong bì.
Hai kiểu gọi: stateless và session
JSON-RPC Odoo có hai cách, dùng cho hai bối cảnh khác nhau:
- Stateless —
/jsonrpc(như trên): mỗi lời gọi tự mangdb,uid,password. Hợp cho tích hợp máy-gọi-máy từ backend khác. Không dùng cookie. - Session —
/web/session/authenticate+/web/dataset/call_kw: đăng nhập một lần, server đặt cookie session, các lời gọi sau đi kèm cookie (không phải gửi lại password). Đây là cách front-end OWL của Odoo nói chuyện với server (nhớrpc()gọi qua @web/core/network/rpc). Hợp cho một web app đã đăng nhập trong cùng phiên trình duyệt.
Chọn stateless cho script/tích hợp ngoài; session cho giao diện web có người dùng đăng nhập.
Lưu ý khi gọi từ trình duyệt
- Same-origin. Trình duyệt chặn gọi
/jsonrpcsang domain khác (CORS) — JS trênmyapp.comkhông tự gọi đượcodoo.com/jsonrpcbằng request đơn giản. Với session-based, đây là tính năng (chống CSRF, nhớ phần CSRF —jsonrpcan toàn nhờ Content-Type JSON + same-origin). Muốn gọi chéo domain thì cần backend trung gian hoặc cấu hình CORS. - Đừng nhét password vào JS chạy trên trình duyệt. Code JS ai cũng đọc được; stateless
/jsonrpcvớidb/uid/passwordchỉ nên chạy ở server-side (Node, backend). Front-end thì dùng session (đăng nhập, cookie). - Kiểm
errortrong phản hồi. JSON-RPC trả 200 kể cả khi lỗi nghiệp vụ — lỗi nằm trong khoá"error", không phải mã HTTP. Luôn kiểmif (data.error).
XML-RPC hay JSON-RPC — chốt lại
| XML-RPC | JSON-RPC | |
|---|---|---|
| Payload | XML (nặng) | JSON (nhẹ) |
| Thư viện | Có sẵn mọi ngôn ngữ | Chỉ cần JSON + HTTP |
| Hợp nhất | Backend đa ngôn ngữ (Python/PHP/Java) | Web/JavaScript, fetch |
| Endpoint | /xmlrpc/2/common, /xmlrpc/2/object |
/jsonrpc (stateless) hoặc session |
Cùng model, cùng execute_kw, cùng cơ chế quyền — chỉ khác định dạng và bối cảnh dùng.
Ba ý mang về
- JSON-RPC gọi Odoo qua một POST JSON tới
/jsonrpc—params.service(common/object) +method+args([db, uid, pass, model, method, args, kwargs]); phản hồi bọc trong{"jsonrpc","id","result"}(hoặc"error"). Gọi thẳng từfetch(), không cần thư viện. - Hai kiểu: stateless
/jsonrpc(mỗi lời gọi mang db/uid/password — cho tích hợp server-side) và session (/web/session/authenticate+/web/dataset/call_kw, dùng cookie — cho front-end web đã đăng nhập). - Từ trình duyệt cẩn thận: same-origin chặn gọi chéo domain; đừng nhét password vào JS client (dùng session); và luôn kiểm khoá
"error"vì lỗi nghiệp vụ vẫn trả HTTP 200.
Ta đã cho bên ngoài gọi vào Odoo. Chiều ngược lại: Odoo gọi ra một API khác. Phần sau mổ xẻ gọi API ngoài từ Odoo bằng requests — cách một model/controller Odoo gửi HTTP tới dịch vụ thứ ba (thanh toán, SMS, giao vận), và những lưu ý về timeout, lỗi, và không chặn luồng.