Lỗi và mã lỗi

Request lỗi trả mã HTTP 4xx hoặc 5xx kèm một object error. Rẽ nhánh theo code; hiện message cho người đọc.

Định dạng lỗi

400 Bad Request
{
  "error": {
    "code": "INVALID_AMOUNT",
    "message": "Số tiền phải là số nguyên từ 1.000 đến 500.000.000 VND."
  }
}
  • code: mã lỗi viết hoa, cố định. Hệ thống của bạn so khớp theo chuỗi này.
  • message: câu tiếng Việt giải thích lỗi và việc cần làm. Câu chữ có thể được sửa cho rõ hơn, nên đừng so khớp theo message.

Mã HTTP

MãÝ nghĩa
200Thành công.
201Tạo mới thành công (tạo yêu cầu thanh toán).
400Request sai: body không phải JSON, tham số thiếu hoặc sai giá trị.
401Thiếu API key, khóa sai hoặc đã thu hồi.
404Không tìm thấy đối tượng (hoặc đối tượng thuộc tài khoản khác), hoặc sai đường dẫn.
409Thao tác không hợp với trạng thái hiện tại, ví dụ hủy yêu cầu đã nhận tiền.
422Request đúng nhưng chưa làm được, ví dụ chưa liên kết tài khoản ngân hàng nào.
429Gửi quá nhiều request. Đợi theo header Retry-After rồi gửi lại.
500Lỗi phía BankOpenAPI. Gửi lại sau ít phút.

Mã lỗi

codeHTTPKhi nàoCách xử lý
INVALID_JSON400Body không phải JSON object.Gửi body dạng JSON object kèm Content-Type: application/json.
INVALID_AMOUNT400amount không phải số nguyên từ 1.000 đến 500.000.000.Sửa số tiền (đơn vị VND, không có phần thập phân).
INVALID_ORDER_ID400orderId dài quá 64 ký tự hoặc có ký tự không cho phép.Chỉ dùng chữ, số và _ . : / # -
INVALID_EXPIRY400expiresInMinutes ngoài khoảng 5 đến 10.080 phút.Chọn thời hạn từ 5 phút tới 7 ngày.
INVALID_BANK_ACCOUNT400bankAccountId không thuộc tài khoản của bạn hoặc chưa liên kết xong.Bỏ trường này để dùng tài khoản liên kết gần nhất, hoặc kiểm tra lại ID trong app.
INVALID_CURSOR400starting_after không phải ID yêu cầu thanh toán của bạn.Dùng id của phần tử cuối ở trang trước.
INVALID_API_KEY401Thiếu, sai, đã thu hồi hoặc đã hết hạn API key.Đọc message để biết lý do; roll hoặc tạo khóa mới nếu cần.
INSUFFICIENT_PERMISSION403API key chỉ có quyền đọc mà gọi lệnh tạo, sửa hoặc hủy.Dùng khóa toàn quyền cho lệnh ghi dữ liệu.
IP_NOT_ALLOWED403API key có giới hạn IP mà request đến từ IP ngoài danh sách. Message ghi IP mà BankOpenAPI nhìn thấy.Không retry. Gọi từ hệ thống có IP đã khai báo, hoặc thêm IP đó ở mục "Giới hạn IP" của khóa.
NOT_FOUND404Không có đối tượng với ID này trong tài khoản của bạn, hoặc sai đường dẫn.Kiểm tra ID và đường dẫn (có /v1).
CANNOT_CANCEL409Yêu cầu thanh toán đã nhận tiền hoặc đã hủy.Không retry. Xử lý theo trạng thái hiện tại.
NO_BANK_ACCOUNT422Chưa liên kết tài khoản ngân hàng nào.Liên kết tài khoản trong app rồi gửi lại.
IDEMPOTENCY_KEY_REUSED422Idempotency-Key đã dùng cho một lệnh khác (khác đường dẫn hoặc body).Mỗi lệnh mới dùng một khóa mới; chỉ dùng lại khóa khi gửi lại đúng lệnh cũ.
IDEMPOTENCY_IN_PROGRESS409Lệnh với Idempotency-Key này đang được xử lý.Đợi vài giây rồi gửi lại cùng khóa.
RATE_LIMITED429Quá giới hạn request của API key, hoặc IP xác thực sai quá nhiều lần.Đợi số giây ghi ở Retry-After rồi gửi lại.
LIVE_MODE400Gọi /v1/test/* bằng API key thật, hoặc tạo tài khoản thử ở dữ liệu thật.Dùng API key sandbox (boa_test_…).
TEST_MODE400Liên kết ngân hàng thật khi đang ở sandbox.Tắt sandbox để liên kết tài khoản thật.
INTERNAL500Lỗi không lường trước phía BankOpenAPI.Gửi lại sau ít phút, có backoff.

Danh sách này có thể có thêm mã mới khi API có thêm endpoint. Gặp mã chưa biết thì xử lý theo mã HTTP: 4xx là lỗi của request, 5xx là lỗi tạm thời.

Khi nào nên retry

  • Nên retry: 429, 500 và lỗi mạng (timeout, mất kết nối). Đợi lâu dần giữa các lần gửi (backoff), có chút ngẫu nhiên.
  • Không retry: các lỗi 4xx còn lại. Gửi lại y nguyên vẫn nhận đúng lỗi đó.
Node.js
const res = await fetch(url, options);
const data = await res.json();

if (!res.ok) {
  const { code, message } = data.error;
  if (res.status === 429 || res.status >= 500) {
    // Lỗi tạm thời: đợi rồi gửi lại (xem Giới hạn tần suất)
  } else if (code === "NO_BANK_ACCOUNT") {
    // Báo người quản trị liên kết tài khoản ngân hàng
  } else {
    // Lỗi do request: sửa request, không retry
    throw new Error(`${code}: ${message}`);
  }
}

Bắt đầu với BankOpenAPI

Đăng ký tài khoản, liên kết tài khoản ngân hàng và nhận webhook báo có đầu tiên. Cần tư vấn thì nhắn chúng tôi.