API keys: tạo, liệt kê, thu hồi X-Client-Secret

Cập nhật 04/09/2026Bản Markdownllms.txtopenapi.json

Video hướng dẫn

API keys: tạo, xem lại, xoay secret, thu hồi · Xem trên YouTube
Xem transcript video (9 phần)

Quản lý khóa không gián đoạn

Một mã bí mật bị mất hoặc lộ không nên kéo theo việc dừng toàn bộ hệ thống. Video này mình tạo khóa API, lưu client_secret đúng lúc, liệt kê khóa mà không lộ Secret, thay khóa và thu hồi khóa cũ. Bạn cũng sẽ phân biệt client_secret gọi API với secret_key ký webhook, vì nhầm hai chuỗi này là lỗi rất hay gặp.

Mỗi hệ thống một khóa

Mỗi hệ thống nên dùng một khóa riêng: web bán hàng một khóa, phần mềm kế toán một khóa, bot một khóa. Khi một nơi gặp sự cố, bạn thu hồi đúng khóa đó mà hệ thống khác không bị ảnh hưởng. Khóa được tạo bằng POST /api/v1/client-keys/generate, cần Bearer. Body có thể truyền name; nếu bỏ trống, tên mặc định là Default Key.

Lưu Secret ngay khi tạo

Response tạo khóa trả id, client_id, client_secret, name, is_active và created_at. Quan trọng nhất, client_secret chỉ hiện đúng một lần. Hệ thống lưu dạng băm nên đóng màn hình là không thể xem lại. Hãy chép ngay vào biến môi trường như MONA_SECRET, kiểm tra ứng dụng đọc được, và tuyệt đối không ghi chuỗi này vào mã nguồn hay commit lên git.

Gửi Secret cho lệnh ghi

Với Bearer token lấy từ client/login, mọi lệnh ghi POST, PUT, PATCH và DELETE bắt buộc kèm header X-Client-Secret. Lệnh GET chỉ cần Bearer. Nếu token lấy bằng oauth/token, header Secret không bắt buộc vì đã được kiểm khi cấp token, nhưng vẫn được khuyến nghị. Cách dùng ổn định là gửi cả hai header cho mọi request ghi của ứng dụng.

Liệt kê khóa hiện có

Muốn xem các khóa đang có, gọi GET /api/v1/client-keys/list. Response là một mảng chứa id, client_id, tên, trạng thái và ngày tạo, nhưng không bao giờ có client_secret. Vì thế, thao tác “xem lại Secret” thực tế không tồn tại. Nếu mất chuỗi bí mật, tạo khóa mới, cập nhật biến môi trường của ứng dụng, kiểm tra hoạt động rồi mới thu hồi khóa cũ.

Thu hồi khóa cũ

Để thu hồi, lấy đúng id từ danh sách rồi gọi DELETE /api/v1/client-keys/destroy/{key_id} với Bearer. Request đang dùng Secret của khóa đó sẽ bị từ chối ngay sau khi thu hồi. Nếu API trả bốn trăm lẻ bốn, khóa không tồn tại hoặc không thuộc tài khoản. Bốn trăm hai mươi hai thường do key_id không đúng UUID; hãy copy nguyên ID từ response danh sách.

Phân biệt hai Secret

Bạn cần phân biệt hai loại bí mật. client_secret đi trong X-Client-Secret để ứng dụng gọi API MONA Pay. secret_key nằm trong cấu hình webhook để MONA Pay ký payload gửi về server. Hai chuỗi này nên khác nhau, lưu ở hai biến môi trường khác nhau và xoay theo hai quy trình khác nhau. Đừng lấy Secret gọi API dán vào ô Secret của webhook.

Thay khóa an toàn

Trên dashboard, vào API Keys để tạo, xem danh sách và thu hồi. Nút tạo mở form đặt tên khóa; Secret hiện một lần nên chuẩn bị nơi lưu trước khi bấm. Dashboard còn có khối copy prompt cho AI agent. Không bấm thu hồi khi ứng dụng mới chưa chuyển sang khóa thay thế. Nếu gặp bốn trăm lẻ một, lấy Bearer token mới. Khi thay khóa, thử một request GET và một request ghi trước khi cắt khóa cũ.

Mở docs và tạo khóa

Endpoint, response mẫu và quy tắc dùng hai loại Secret nằm tại monapay.vn/docs/api/api-keys. Bạn đăng ký tại my.monapay.vn, vào mục API Keys và tạo một khóa riêng cho môi trường thử trước tiên. Nếu cần hỗ trợ xoay khóa mà không gián đoạn ứng dụng, gọi tổng đài một chín không không, sáu ba sáu, sáu bốn tám để đội MONA cùng kiểm tra.

API key của MONA Pay là chuỗi client_secret sinh bằng POST /api/v1/client-keys/generate. Hệ thống chỉ hiện secret đúng 1 lần lúc tạo, sau đó lưu dạng băm nên không xem lại được. Với Bearer token từ client/login, mọi request POST, PUT, PATCH và DELETE bắt buộc kèm X-Client-Secret; với token từ oauth/token, header này không bắt buộc nhưng MONA Pay vẫn khuyến nghị gửi. Mất secret thì tạo key mới rồi thu hồi key cũ, mỗi tài khoản tạo được nhiều key.

Khi nào cần key

Việc Cần Bearer Cần X-Client-Secret
Đăng ký, đăng nhập không không
Đọc dữ liệu (GET): giao dịch, VA, log webhook có không
Ghi dữ liệu (POST, PUT, PATCH, DELETE): tạo VA, tạo QR, cấu hình webhook/Telegram, đổi mật khẩu có Bắt buộc với token client/login; khuyến nghị với token oauth/token

Cách làm sạch: mỗi hệ thống tích hợp (web bán hàng, phần mềm kế toán, bot) dùng 1 key riêng, đặt tên theo hệ thống đó. Hệ thống nào bị lộ thì thu hồi đúng key đó, hệ thống khác không ảnh hưởng.

POST /api/v1/client-keys/generate

Cần Bearer.

Trường Kiểu Bắt buộc Ghi chú
name string không Tên gợi nhớ, mặc định Default Key

Response 200:

JSON
{
  "success": true,
  "message": "Key generated successfully",
  "data": {
    "id": "0190a1b2-...",
    "client_id": "0190a0f0-...",
    "client_secret": "mps_...chuoi-bi-mat-chi-hien-1-lan",
    "name": "Web ban hang",
    "is_active": true,
    "created_at": "2026-08-28T10:30:00"
  }
}

Lưu client_secret ngay vào biến môi trường (MONA_SECRET). Đóng màn hình là không lấy lại được.

cURL

Terminal
curl -X POST https://api.monapay.vn/api/v1/client-keys/generate \
  -H "Authorization: Bearer $MONA_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"name":"Web ban hang"}'

PHP

PHP
<?php
function monaPost(string $path, array $body, string $token, ?string $secret = null): array {
    $headers = "Content-Type: application/json\r\nAuthorization: Bearer $token\r\n";
    if ($secret) $headers .= "X-Client-Secret: $secret\r\n";
    $raw = file_get_contents('https://api.monapay.vn' . $path, false, stream_context_create([
        'http' => ['method' => 'POST', 'header' => $headers, 'content' => json_encode($body), 'ignore_errors' => true],
    ]));
    return json_decode($raw, true) ?? ['success' => false, 'message' => 'Không đọc được response'];
}

$res = monaPost('/api/v1/client-keys/generate', ['name' => 'Web ban hang'], getenv('MONA_TOKEN'));
$clientSecret = $res['data']['client_secret'] ?? null; // ghi vào .env, chỉ hiện 1 lần

Node

JavaScript
const res = await fetch('https://api.monapay.vn/api/v1/client-keys/generate', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${process.env.MONA_TOKEN}` },
  body: JSON.stringify({ name: 'Web ban hang' }),
});
const { success, data, message } = await res.json();
if (!success) throw new Error(message);
console.log('Ghi vào .env:', data.client_secret); // chỉ hiện 1 lần

GET /api/v1/client-keys/list

Danh sách key của tài khoản, không kèm secret. Cần Bearer.

Terminal
curl https://api.monapay.vn/api/v1/client-keys/list \
  -H "Authorization: Bearer $MONA_TOKEN"
JSON
{
  "success": true,
  "message": "Keys retrieved",
  "data": [
    { "id": "0190a1b2-...", "client_id": "0190a0f0-...", "name": "Web ban hang", "is_active": true, "created_at": "2026-08-28T10:30:00" }
  ]
}

DELETE /api/v1/client-keys/destroy/{key_id}

Thu hồi key. Cần Bearer. Request đang dùng secret của key này sẽ bị từ chối ngay sau khi thu hồi.

Terminal
curl -X DELETE https://api.monapay.vn/api/v1/client-keys/destroy/0190a1b2-... \
  -H "Authorization: Bearer $MONA_TOKEN"

Response: {"success": true, "message": "Key destroyed", "data": null}. Key không tồn tại hoặc không thuộc tài khoản trả 404.

Dùng secret trong request ghi

Terminal
curl -X POST https://api.monapay.vn/api/v1/client-webhooks \
  -H "Authorization: Bearer $MONA_TOKEN" \
  -H "X-Client-Secret: $MONA_SECRET" \
  -H 'Content-Type: application/json' \
  -d '{"name":"Web ban hang","webhook_url":"https://shop.vn/webhook/monapay","auth_type":"HMAC_SHA256","secret_key":"hmac-cua-anh-chi"}'

Lưu ý phân biệt 2 loại secret: client_secret (X-Client-Secret) là để bạn gọi API MONA Pay; secret_key trong cấu hình webhook là để MONA Pay ký payload gửi sang server bạn (xem Bảo mật webhook). Hai chuỗi này nên khác nhau.

  • Token từ POST /api/v1/client/login: mọi lệnh ghi POST, PUT, PATCH và DELETE bắt buộc kèm X-Client-Secret; thiếu header này, MONA Pay trả 401 Thiếu X-Client-Secret.
  • Token từ POST /api/v1/oauth/token: máy chủ đã kiểm client_secret khi cấp token nên không đòi lại header ở từng lệnh ghi. SDK và MCP chính thức vẫn gửi kèm.

MONA Pay khuyến nghị luôn gửi X-Client-Secret để token lộ qua log hoặc proxy cũng không thể tự ý đổi cấu hình.

Lỗi thường gặp

HTTP Nguyên nhân Cách xử lý
401 Thiếu hoặc sai Bearer token Login lại lấy token mới
404 key_id không tồn tại hoặc không thuộc tài khoản Gọi /client-keys/list lấy đúng id
422 key_id không đúng định dạng UUID Copy nguyên id từ danh sách

Thao tác tạo và thu hồi key cũng làm được trên dashboard tại mục API Keys, có sẵn khối “copy prompt cho AI agent” để dán vào Claude Code, Codex hoặc Cursor.

Dashboard MONA Pay tạo, xem và thu hồi API Keys cho hệ thống hoặc AI agent
Dashboard liệt kê từng API key và khối lệnh dùng với AI agent, ảnh chụp từ dashboard my.monapay.vn.