Tino Developers
Xem .md

API công khai TinoPay

API công khai của TinoPay chạy tại https://pay.tino.vn: truy vấn lịch sử giao dịch, lấy danh sách ngân hàng và sinh ảnh mã VietQR. API này khác API merchant (https://api.tino.vn/service/<id>/tinopay/…, token đăng nhập Tino) dùng để quản lý merchant, tài khoản ngân hàng, webhook.

Cập nhật: 2026-10-25. Nguồn: tài liệu TinoPay.

Hai cách tích hợp

HướngMô tảDùng khi
APIbạn gọi tới TinoPay để truy vấn dữ liệu (lịch sử giao dịch, danh sách ngân hàng) và sinh mã QRkiểm tra, đối soát, hiện QR thanh toán
WebhookTinoPay gửi dữ liệu giao dịch tới URL của bạn ngay khi phát sinhxác nhận thanh toán tức thời, không cần hỏi lặp

Nên dùng webhook để nhận giao dịch tức thời và dùng lịch sử giao dịch để đối soát hoặc dự phòng.

Thông tin cơ bản

MụcGiá trị
Địa chỉ gốchttps://pay.tino.vn
Tiền tốendpoint API nằm dưới /api, ví dụ https://pay.tino.vn/api/transactions; riêng ảnh QR ở https://pay.tino.vn/img-qr
Định dạngJSON, UTF-8
Tiền tệVND, số nguyên, không có phần thập phân
Xác thựcAuthorization: Bearer <api_token>, trừ danh sách ngân hàng và ảnh QR
curl -G "https://pay.tino.vn/api/transactions" \
  -H "Authorization: Bearer $TINOPAY_API_TOKEN" \
  -H "Accept: application/json"

Xác thực

Mọi request cần xác thực gửi API token ở header Authorization theo chuẩn Bearer:

Authorization: Bearer <api_token>

Tạo API token

  • Trên web TinoPay: menu Tích hợp → API Access (/api-access), bấm Tạo API Token, đặt tên gợi nhớ (ví dụ server-production) rồi sao chép token ngay.
  • Bằng API merchant: Tạo API token, xem mục API token của trang Bắt đầu.

Token gốc chỉ hiện một lần khi tạo. Làm mất thì thu hồi token cũ và tạo token mới. Tạo được nhiều token và thu hồi bất kỳ token nào ở trang API Access.

Phạm vi truy cập

  • Mỗi token gắn với một tài khoản chủ sở hữu và chỉ đọc được dữ liệu (giao dịch, tài khoản ngân hàng) của chủ token đó.
  • Tham số trỏ tới tài nguyên không thuộc về bạn (ví dụ bank_account_id của người khác) thì API không trả dữ liệu.

Ví dụ gọi

JavaScript:

const res = await fetch("https://pay.tino.vn/api/transactions", {
  headers: { Authorization: `Bearer ${process.env.TINOPAY_API_TOKEN}`, Accept: "application/json" },
});
const data = await res.json();

PHP (Laravel):

$response = Http::withToken(env('TINOPAY_API_TOKEN'))
    ->acceptJson()
    ->get('https://pay.tino.vn/api/transactions');
$data = $response->json();

Lỗi xác thực

Tình huốngHTTPBody
thiếu hoặc sai định dạng header Authorization401{"message": "Thiếu API Token. Vui lòng gửi header Authorization: Bearer {token}."}
token không tồn tại hoặc đã bị thu hồi401{"message": "API Token không hợp lệ."}

Bảo mật

  • TinoPay lưu token dưới dạng băm SHA-256, không lưu token gốc: token gốc chỉ xem được một lần khi tạo.
  • Mỗi request hợp lệ cập nhật thời điểm dùng gần nhất (last_used_at) của token, giúp theo dõi token nào đang hoạt động.
  • Không đưa token vào mã phía client (trình duyệt, app di động) hay commit lên Git: chỉ dùng ở máy chủ.
  • Token bị lộ thì thu hồi ngay ở trang API Access; token đã thu hồi trả 401 từ request kế tiếp.

Lịch sử giao dịch

GET https://pay.tino.vn/api/transactions
  • Xác thực: bắt buộc.
  • Trả giao dịch của mọi tài khoản ngân hàng thuộc chủ token.
  • Mặc định lấy giao dịch trong ngày hiện tại; khoảng khác thì truyền transaction_date_from, transaction_date_to.
  • Sắp xếp theo transaction_date giảm dần (mới nhất trước), có phân trang.

Tham số truy vấn, đều tuỳ chọn:

Tham sốKiểuMặc địnhMô tả
qstring—tìm (LIKE) theo reference_number, transaction_content, transaction_id
bank_account_idstring (UUID)—lọc theo một tài khoản ngân hàng; UUID phải thuộc chủ token
typestring—in tiền vào, out tiền ra
transaction_date_fromdate (Y-m-d)hôm nayngày bắt đầu (tính cả ngày này)
transaction_date_todate (Y-m-d)hôm nayngày kết thúc (tính cả ngày này); tối đa 90 ngày kể từ from
per_pageint (1–100)20số bản ghi mỗi trang
pageint1trang hiện tại

Khoảng thời gian:

  • Không truyền cả from lẫn to: lấy trong ngày hôm nay.
  • Chỉ truyền một trong hai: lấy trọn đúng ngày đó.
  • from phải nhỏ hơn hoặc bằng to, cách nhau tối đa 90 ngày.
curl -G "https://pay.tino.vn/api/transactions" \
  -H "Authorization: Bearer $TINOPAY_API_TOKEN" \
  -H "Accept: application/json" \
  --data-urlencode "q=DH12345" \
  --data-urlencode "type=in" \
  --data-urlencode "transaction_date_from=2026-10-01" \
  --data-urlencode "transaction_date_to=2026-10-20" \
  --data-urlencode "per_page=20"
const params = new URLSearchParams({ q: "DH12345", type: "in", transaction_date_from: "2026-10-01", transaction_date_to: "2026-10-20", per_page: "20" });
const res = await fetch(`https://pay.tino.vn/api/transactions?${params}`, {
  headers: { Authorization: `Bearer ${process.env.TINOPAY_API_TOKEN}`, Accept: "application/json" },
});
const json = await res.json();

Response 200:

{
  "data": [
    {
      "id": 1032,
      "reference_number": "0551dTCO-82LiomOss",
      "transaction_content": "DH12345 chuyen tien mua hang",
      "transaction_id": "20261020083338000006",
      "bank_account_id": "9c1e6f2a-5b7d-4e1a-9f3c-2d8b6a4e0c11",
      "virtual_number": "9624QA01",
      "amount": 150000,
      "type": 1,
      "type_label": "in",
      "status": 0,
      "transaction_date": "2026-10-20 08:33:38",
      "created_at": "2026-10-20 08:33:40"
    }
  ],
  "links": {
    "first": "https://pay.tino.vn/api/transactions?page=1",
    "last": "https://pay.tino.vn/api/transactions?page=3",
    "prev": null,
    "next": "https://pay.tino.vn/api/transactions?page=2"
  },
  "meta": { "current_page": 1, "from": 1, "last_page": 3, "per_page": 20, "to": 20, "total": 57 }
}
Trường trong data[]KiểuMô tả
idintID giao dịch
reference_numberstring | nullmã tham chiếu của ngân hàng (core reference)
transaction_contentstringnội dung, diễn giải giao dịch
transaction_idstringmã giao dịch
bank_account_idstring (UUID)tài khoản ngân hàng phát sinh giao dịch
virtual_numberstring | nullsố tài khoản ảo, nếu có
amountintsố tiền (VND)
typeint1 tiền vào, 2 tiền ra
type_labelstringin tiền vào, out tiền ra
statusinttrạng thái giao dịch
transaction_datestring (Y-m-d H:i:s)thời điểm giao dịch thực tế
created_atstring (Y-m-d H:i:s)thời điểm TinoPay ghi nhận

links và meta là cấu trúc phân trang của Laravel API Resource: duyệt trang theo meta.last_page hoặc links.next.

LỗiHTTPBody
from lớn hơn to422{"message": "transaction_date_from phải nhỏ hơn hoặc bằng transaction_date_to."}
khoảng quá 90 ngày422{"message": "Khoảng thời gian tối đa là 90 ngày."}
sai kiểu dữ liệu tham số422lỗi validate của Laravel: {"message": …, "errors": {…}}

Danh sách ngân hàng

GET https://pay.tino.vn/api/banks

Ngân hàng TinoPay hỗ trợ, kèm mã ngân hàng (code) và mã BIN: dùng cho ô chọn ngân hàng hoặc lấy code để tạo mã VietQR. Không cần xác thực. Trả một mảng JSON, không bọc trong data.

curl "https://pay.tino.vn/api/banks" -H "Accept: application/json"
[
  { "id": 1, "code": "BIDV", "bin": "970418", "name": "Ngân hàng TMCP Đầu tư và Phát triển Việt Nam", "created_at": "2025-01-01 00:00:00", "updated_at": "2025-01-01 00:00:00" },
  { "id": 2, "code": "MB", "bin": "970422", "name": "Ngân hàng TMCP Quân đội", "created_at": "2025-01-01 00:00:00", "updated_at": "2025-01-01 00:00:00" }
]
TrườngKiểuMô tả
idintID ngân hàng trong TinoPay
codestringmã viết tắt (ví dụ BIDV, MB), dùng cho tham số bank_code khi tạo mã QR
binstringmã định danh ngân hàng (BIN) theo chuẩn Napas, VietQR
namestringtên đầy đủ của ngân hàng

Danh sách theo đúng dữ liệu ngân hàng đang cấu hình trong TinoPay: dùng nguyên giá trị code từ đây khi gọi API khác.

Tạo mã VietQR

GET https://pay.tino.vn/img-qr

Sinh mã VietQR động để khách quét và chuyển khoản. Endpoint trả thẳng ảnh PNG nên nhúng được vào thẻ <img>, không cần tự vẽ QR.

  • Không cần xác thực. Không có tiền tố /api.
  • Trả ảnh image/png, có header Access-Control-Allow-Origin: * nên dùng được từ trình duyệt.
  • Mã theo chuẩn VietQR, Napas 247 (dịch vụ chuyển nhanh QRIBFTTA).
Tham sốBắt buộcMô tả
bank_codecómã ngân hàng thụ hưởng (ví dụ BIDV, MB), lấy từ danh sách ngân hàng
account_nocósố tài khoản thụ hưởng
account_namekhôngtên chủ tài khoản, hiện trên khung ảnh
amountkhôngsố tiền (VND); chỉ áp dụng khi trong khoảng 1.000 – 9.999.999.999.999
memokhôngnội dung chuyển khoản, tối đa 25 ký tự (dài hơn thì bị bỏ qua)
templatekhôngdefault ảnh có khung (mặc định), only-qr chỉ mã QR
is_maskkhông1: che bớt số tài khoản trên ảnh có khung
<img src="https://pay.tino.vn/img-qr?bank_code=BIDV&account_no=96240000001&amount=150000&memo=DH12345" alt="Quét QR để thanh toán" width="320">

Đủ tham số:

https://pay.tino.vn/img-qr?bank_code=BIDV&account_no=96240000001&account_name=CONG%20TY%20ABC&amount=150000&memo=DH12345&template=default&is_mask=1

Chỉ mã QR, không khung:

https://pay.tino.vn/img-qr?bank_code=BIDV&account_no=96240000001&amount=150000&memo=DH12345&template=only-qr

Thiếu hoặc sai tham số bắt buộc thì endpoint trả văn bản, không phải ảnh:

Tình huốngTrả về
bank_code không hợp lệ hoặc không cóVui lòng nhập đúng mã ngân hàng
thiếu account_noVui lòng nhập số tài khoản

Trong luồng thanh toán, đặt memo là mã đơn hàng duy nhất (ví dụ DH12345). Khi khách chuyển khoản, webhook nhận giao dịch kèm nội dung này (và code nếu khớp mã thanh toán), nhờ đó khớp đúng đơn hàng và xác nhận thanh toán tự động.

Hỗ trợ

Vướng mắc khi tích hợp: tạo ticket hỗ trợ ngay trong trang quản trị TinoPay.