← Quay lại Billbook

API Ghi Sổ Từ Xa

Cập nhật lần cuối: 10 tháng 5, 2026

Ghi mục từ cURL, Phím tắt iOS hoặc tập lệnh tự động bằng token API cá nhân. Token chỉ ghi — có thể thêm giao dịch và đọc danh sách danh mục / thẻ, nhưng không thể đọc hay xóa dữ liệu giao dịch.

1. Lấy token

Đăng nhập với quyền admin, mở Cài đặt → 🔑 API Ghi Sổ Từ Xa và bấm "Tạo token".

Token dạng văn bản chỉ hiển thị một lần — hãy sao chép ngay. Máy chủ chỉ lưu hash SHA-256, nên token bị mất chỉ có thể thay bằng cách tạo lại (hủy bỏ token cũ).

Định dạng token: bb_<userId>_<secret>. Gửi trong mọi yêu cầu dưới dạng Authorization: Bearer <token>.

2. POST /api/ingest — thêm một giao dịch

Thân yêu cầu là một đối tượng JSON với các trường sau:

  • title (string, bắt buộc) — tên giao dịch
  • amount (number, bắt buộc) — phải là số dương
  • type (string, tùy chọn, mặc định expense) — một trong expense / income / prepaid_expense / pending_income
  • category (string, tùy chọn) — tên danh mục
  • note (string, tùy chọn) — ghi chú tự do
  • created_at (string, tùy chọn) — ISO 8601; mặc định là hiện tại
curl -X POST https://billbook.me/api/ingest \
  -H "Authorization: Bearer bb_<userId>_<secret>" \
  -H "Content-Type: application/json" \
  -d '{"title":"Coffee","amount":120,"type":"expense","category":"Food"}'

# response: 201
{ "id": "...", "created_at": "..." }

3. GET /api/ingest/categories — lấy danh sách danh mục

Trả về tên danh mục của admin theo thứ tự dropdown của bảng điều khiển. Phản hồi chỉ chứa tên — không có id, user id hay dữ liệu giao dịch.

curl https://billbook.me/api/ingest/categories \
  -H "Authorization: Bearer bb_<userId>_<secret>"

# response: 200
{ "categories": ["Food", "Rent", "..."] }

4. GET /api/ingest/tags — thẻ dùng gần đây

Trả về tiền tố thẻ được cập nhật gần nhất (các đánh dấu #XXX nhúng trong tiêu đề). Mặc định 20 mục; dùng ?limit= để thay đổi (tối đa 100).

Trả về mảng rỗng thay vì lỗi nếu bảng tag_prefixes chưa tồn tại.

curl "https://billbook.me/api/ingest/tags?limit=20" \
  -H "Authorization: Bearer bb_<userId>_<secret>"

# response: 200
{ "tags": ["#management-fee", "#travel", "..."] }

5. Mã lỗi

Mọi lỗi đều ở dạng JSON: { "error": "thông điệp" }.

  • 401 — thiếu xác thực, token sai định dạng, đã thu hồi hoặc không khớp
  • 402 — gói đăng ký hết hạn; cần gia hạn để ghi
  • 405 — phương thức không hỗ trợ (ví dụ GET vào /api/ingest)
  • 501 — máy chủ thiếu SUPABASE_SERVICE_ROLE_KEY
  • 500 — lỗi nội bộ khác

6. Bảo mật và giới hạn

Theo thiết kế, token chỉ ghi được vào tổ chức của chính nó — không thể giả mạo tổ chức khác hoặc đọc dữ liệu hiện có:

  • user_id luôn là chủ token; không thể giả mạo
  • org_id luôn là org của chủ; ghi chéo org là không thể
  • Token chỉ cấp cho vai trò admin (manager / staff trả về 403)
  • Phản hồi không lộ hàng khác — chỉ trả { id, created_at }
  • Thu hồi có hiệu lực ngay; xoay vòng bất cứ lúc nào trong Cài đặt

7. Ví dụ Phím tắt iOS

Thêm hành động "Lấy nội dung URL", URL https://billbook.me/api/ingest, phương thức POST, tiêu đề Authorization: Bearer bb_...Content-Type: application/json, thân yêu cầu JSON: {"title":"Cà phê","amount":120,"type":"expense"}. Kết nối titleamount với đầu vào Phím tắt hoặc biến "Hỏi mỗi lần".

Tài liệu này chỉ là tham khảo nhanh; mã backend mới là nguồn chính thức cho hành vi thực tế.