Xác thực API ngân hàng MONA Pay: Bearer token và X-Client-Secret

Mọi lệnh gọi API MONA Pay cần header Authorization: Bearer <access_token>. Token lấy từ POST /api/v1/client/login bằng username và mật khẩu của tài khoản my.monapay.vn, hạn dùng 86.400 giây (24 giờ). Các lệnh ghi dữ liệu (POST, PUT, DELETE) gửi thêm header X-Client-Secret với secret sinh ở mục API keys. Mọi response đều bọc trong một khung chung {"success": true, "message": "...", "data": ...}.

Base URL

Môi trường URL
Production https://api.monapay.vn
Alias cũ (vẫn chạy, cho tích hợp trước 2026) https://ipn.mona.host

Tài khoản đăng ký xong dùng được ngay: đăng nhập, tạo API key, không cần ai duyệt. Sandbox tách riêng (dữ liệu giả lập, không đụng ngân hàng thật) đang triển khai.

Khung response chung

Mọi endpoint trả về cùng một khung, kể cả khi lỗi:

{
  "success": true,
  "message": "Success",
  "data": { }
}
Trường Kiểu Ý nghĩa
success boolean true khi xử lý xong, false khi lỗi nghiệp vụ
message string Thông điệp ngắn để log
data object / array / null Dữ liệu trả về, null nếu không có

Lỗi validate (thiếu trường, sai kiểu) trả HTTP 422 theo chuẩn FastAPI với detail[] liệt kê từng trường sai.

Hai lớp xác thực

Lớp Header Dùng khi Lấy ở đâu
Bearer token Authorization: Bearer <access_token> Mọi request (trừ đăng ký, đăng nhập) POST /api/v1/client/login
Client secret X-Client-Secret: <client_secret> POST, PUT, DELETE POST /api/v1/client-keys/generate

Giữ token và secret ở biến môi trường, không ghi cứng trong code, không commit lên git.

POST /api/v1/client/register-client

Tạo tài khoản mới. Không cần xác thực. Tài khoản tạo xong dùng được ngay, đăng nhập liền không cần duyệt. Đăng ký qua form tại my.monapay.vn/auth (tab Đăng ký) cũng đi qua đúng endpoint này.

Trường Kiểu Bắt buộc Ghi chú
username string (1-255) Tên đăng nhập, dùng để login
password string (1-255) Mật khẩu
name string (1-255) Tên doanh nghiệp / tên hiển thị
curl -X POST https://api.monapay.vn/api/v1/client/register-client \
  -H 'Content-Type: application/json' \
  -d '{"username":"shopabc","password":"MatKhauManh#2026","name":"Shop ABC"}'

Response 200/201:

{ "success": true, "message": "Client registered successfully", "data": {} }

POST /api/v1/client/login

Đổi username + mật khẩu lấy access_token. Không cần xác thực.

Trường Kiểu Bắt buộc
username string
password string

Response 200:

{
  "success": true,
  "message": "Login successful",
  "data": {
    "access_token": "Zx9...64-ky-tu-url-safe",
    "expires_in": 86400,
    "token_type": "Bearer"
  }
}

expires_in tính bằng giây. Hết hạn thì gọi login lại, không có refresh token. Nếu tài khoản bật 2FA trong dashboard, bước đăng nhập trên web sẽ hỏi thêm mã OTP; gọi API trực tiếp thì dùng tài khoản chưa bật 2FA hoặc liên hệ tụi em.

cURL

curl -X POST https://api.monapay.vn/api/v1/client/login \
  -H 'Content-Type: application/json' \
  -d '{"username":"shopabc","password":"MatKhauManh#2026"}'

PHP

<?php
$res = json_decode(file_get_contents('https://api.monapay.vn/api/v1/client/login', false, stream_context_create([
    'http' => [
        'method'  => 'POST',
        'header'  => "Content-Type: application/json\r\n",
        'content' => json_encode(['username' => getenv('MONA_USER'), 'password' => getenv('MONA_PASS')]),
    ],
])), true);

if (empty($res['success'])) {
    throw new RuntimeException('Đăng nhập MONA Pay thất bại: ' . ($res['message'] ?? 'không rõ'));
}
$accessToken = $res['data']['access_token']; // lưu lại, dùng 24 giờ

Node

const res = await fetch('https://api.monapay.vn/api/v1/client/login', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ username: process.env.MONA_USER, password: process.env.MONA_PASS }),
});
const json = await res.json();
if (!json.success) throw new Error('Đăng nhập MONA Pay thất bại: ' + json.message);
const accessToken = json.data.access_token; // lưu lại, dùng 24 giờ

GET /api/v1/client/me

Thông tin tài khoản đang đăng nhập. Cần Bearer.

curl https://api.monapay.vn/api/v1/client/me \
  -H "Authorization: Bearer $MONA_TOKEN"

Response: data gồm thông tin client (id, username, name, trạng thái kích hoạt, thời điểm tạo).

PUT /api/v1/client/change-password

Đổi mật khẩu của chính mình. Cần Bearer + X-Client-Secret.

Trường Kiểu Bắt buộc
old_password string
new_password string
curl -X PUT https://api.monapay.vn/api/v1/client/change-password \
  -H "Authorization: Bearer $MONA_TOKEN" \
  -H "X-Client-Secret: $MONA_SECRET" \
  -H 'Content-Type: application/json' \
  -d '{"old_password":"MatKhauManh#2026","new_password":"MatKhauMoi#2026"}'

Trạng thái ép buộc (kiểm 28/08/2026): máy chủ production hiện chưa từ chối lệnh ghi thiếu X-Client-Secret; bản cập nhật ép buộc đã viết xong, đang chờ đưa lên. Anh chị gửi header này ngay từ bây giờ để khi bật lên không phải sửa gì.

Đổi mật khẩu xong thì token cũ vẫn dùng được tới khi hết hạn; muốn cắt ngay thì đăng nhập lại và thu hồi key ở mục API keys.

Lỗi thường gặp

HTTP Nguyên nhân Cách xử lý
401 Sai username/mật khẩu hoặc token hết hạn Kiểm tra lại thông tin (tài khoản mới đăng nhập được ngay, không có bước chờ duyệt); token hết hạn thì login lại
401 Authorization scheme must be Bearer Header sai định dạng Đúng dạng Authorization: Bearer <token>, có khoảng trắng sau chữ Bearer
422 Thiếu trường bắt buộc hoặc sai kiểu Đọc detail[] trong body, sửa đúng tên trường
500 Lỗi phía MONA Pay Thử lại sau vài giây; lặp lại thì báo tụi em kèm message

Bước tiếp theo

  1. Tạo API key để có X-Client-Secret.
  2. Nối tài khoản ACB, tạo tài khoản ảo.
  3. Cấu hình webhook để nhận thông báo tiền vào.