📄 Document AI API
Trích xuất dữ liệu có cấu trúc từ tài liệu — hóa đơn VAT, CCCD/CMND, OCR, PDF → Markdown. Upload file, nhận JSON chỉ với 1 API call.
Tổng quan
Document AI cung cấp 5 endpoint chuyên biệt theo từng task:
| Task | Endpoint | Input | Output | Giá |
|---|---|---|---|---|
| 🧾 Hóa đơn VAT | POST /v1/extract/invoice | JPEG, PNG, WebP, PDF | JSON | 750đ / hóa đơn |
| 🪪 CCCD / CMND | POST /v1/extract/idcard | JPEG, PNG, WebP | JSON | 500đ / ảnh |
| 📋 Chứng từ tổng quát | POST /v1/extract/document | JPEG, PNG, WebP, PDF | JSON | 750đ / tài liệu |
| 📝 OCR Tài liệu | POST /v1/document/ocr | JPEG, PNG, WebP, PDF | JSON (text) | 250đ / trang |
| 📑 PDF → Markdown | POST /v1/pdf/markdown | JPEG, PNG, WebP, PDF | JSON (markdown) | 500đ / trang |
💡 Billing: Hóa đơn và CCCD tính phí cố định mỗi tài liệu/ảnh. OCR và PDF→Markdown tính phí theo số trang (PDF nhiều trang = giá/trang × số trang). Trừ trực tiếp vào ví VNĐ.
Base URL
https://platform.beeknoee.com
URL đầy đủ = Base URL + đường dẫn endpoint, ví dụ: https://platform.beeknoee.com/v1/extract/invoice.
⚠️ Đường dẫn không có tiền tố
/api. Dùng/v1/...(không phải/api/v1/...).
Tất cả endpoint đều dùng chung API Key với các dịch vụ khác (Text, TTS, Video...).
Authentication
| Header | Value | Required |
|---|---|---|
Authorization | Bearer YOUR_API_KEY | ✅ |
API Key tạo tại trang API Keys. Ngoài API key, endpoint cũng chấp nhận JWT session (dùng nội bộ cho trang Document AI).
Request Format
Tất cả endpoint đều dùng multipart/form-data (upload file).
Form Fields
| Field | Type | Required | Description |
|---|---|---|---|
file | File | ✅ | File tài liệu cần xử lý |
language | string | ❌ | Ngôn ngữ ưu tiên: vi (default), en... (auto-detect nếu khác) |
Giới hạn file
| Endpoint | File types | Max size |
|---|---|---|
/v1/extract/invoice | JPEG, PNG, WebP, PDF | ảnh 20MB · PDF 50MB |
/v1/extract/idcard | JPEG, PNG, WebP | 20MB |
/v1/extract/document | JPEG, PNG, WebP, PDF | ảnh 20MB · PDF 50MB |
/v1/document/ocr | JPEG, PNG, WebP, PDF | ảnh 20MB · PDF 50MB |
/v1/pdf/markdown | JPEG, PNG, WebP, PDF | ảnh 20MB · PDF 50MB |
Giới hạn áp theo loại file thật (MIME), không theo endpoint: ảnh JPEG/PNG/WebP ≤ 20MB, PDF ≤ 50MB. Vượt ngưỡng →
400kèm dung lượng file của bạn.
Response Format
Tất cả endpoint trả về JSON với envelope chung:
{
"id": "65d2a852-6f7a-4e08-9bcc-90e1fbc79fa6",
"status": "completed",
"task_type": "ocr",
"file_name": "document.png",
"page_count": 1,
"processing_ms": 2699,
"cost_vnd": 250,
"cost_per_page": 250,
"confidence": 0.9,
"result": { ... },
"created_at": "2026-07-09T02:49:56.314Z"
}
| Field | Type | Description |
|---|---|---|
id | string | ID job (UUID) — tra cứu lại qua GET /v1/document/jobs/:id |
status | string | completed khi thành công |
task_type | string | invoice | idcard | document | ocr | pdf_markdown |
file_name | string | Tên file đã upload |
page_count | number | Số trang (ảnh JPEG/PNG/WebP luôn = 1) |
processing_ms | number | Thời gian xử lý (ms) |
cost_vnd | number | Số tiền đã trừ ví (đ) |
cost_per_page | number | Giá mỗi trang — chỉ có ở OCR & PDF→Markdown |
confidence | number | Độ tin cậy 0–1 (1 = chắc chắn nhất) |
result | object | Dữ liệu trích xuất (khác nhau theo task — xem bên dưới) |
created_at | string | ISO 8601 timestamp |
⚠️ Quan trọng — vị trí dữ liệu trong
result:
invoice,idcard,document,ocr→ dữ liệu nằm ởresult.data.*pdf_markdown→ markdown + metadata nằm ởresult.*trực tiếp (result.markdown,result.title... — không córesult.data)
Endpoints chi tiết
1. 🧾 Trích xuất Hóa đơn VAT
POST /v1/extract/invoice
Trích xuất thông tin từ ảnh/PDF hóa đơn VAT Việt Nam: seller, buyer, items, tổng tiền, mã số thuế, VAT.
Response mẫu:
{
"id": "a1b2c3d4-...",
"status": "completed",
"task_type": "invoice",
"file_name": "hoadon.jpg",
"page_count": 1,
"processing_ms": 2340,
"cost_vnd": 750,
"confidence": 0.95,
"result": {
"data": {
"invoice_no": "0001234",
"serial": "AA/26E",
"date": "2025-01-15",
"seller": {
"name": "Công ty TNHH ABC",
"tax_code": "0123456789",
"address": "123 Nguyễn Huệ, Q.1, TP.HCM"
},
"buyer": {
"name": "Nguyễn Văn A",
"tax_code": "9876543210",
"address": "456 Lê Lợi, Q.3, TP.HCM"
},
"items": [
{
"name": "Dịch vụ hosting VPS",
"unit": "Tháng",
"quantity": 12,
"unit_price": 500000,
"amount": 6000000
}
],
"subtotal": 6000000,
"vat_rate": 10,
"vat_amount": 600000,
"total": 6600000,
"total_in_words": "Sáu triệu sáu trăm nghìn đồng",
"currency": "VND",
"payment_method": "Chuyển khoản"
}
},
"created_at": "2026-07-09T02:49:56.314Z"
}
2. 🪪 Trích xuất CCCD / CMND
POST /v1/extract/idcard
Trích xuất thông tin từ ảnh Căn cước công dân (CCCD) hoặc Chứng minh nhân dân (CMND).
Response mẫu:
{
"id": "b2c3d4e5-...",
"status": "completed",
"task_type": "idcard",
"file_name": "cccd_front.jpg",
"page_count": 1,
"processing_ms": 1850,
"cost_vnd": 500,
"confidence": 0.92,
"result": {
"data": {
"id_number": "001234567890",
"full_name": "NGUYỄN VĂN A",
"date_of_birth": "1990-01-01",
"gender": "Nam",
"nationality": "Việt Nam",
"place_of_origin": "Hà Nội",
"place_of_residence": "Số 1, Phố Trần Hưng Đạo, Hoàn Kiếm, Hà Nội",
"issue_date": "2021-06-15",
"expiry_date": "2050-01-01",
"card_type": "CCCD",
"side": "front"
}
},
"created_at": "2026-07-09T02:49:56.314Z"
}
⚠️ Lưu ý: Chỉ hỗ trợ ảnh mặt trước CCCD/CMND. Đảm bảo ảnh rõ nét, không bị cắt xén. Ngày trả về theo format
YYYY-MM-DD.
3. 📋 Trích xuất Chứng từ tổng quát
POST /v1/extract/document
Dành cho chứng từ không phải hóa đơn VAT: báo giá, đơn đặt hàng, hợp đồng, phiếu giao hàng, biên lai. Tự nhận diện loại chứng từ (doc_type) rồi trích xuất bên bán/bên mua, danh sách hàng mục, chiết khấu, VAT, tổng tiền và điều khoản.
Response mẫu:
{
"id": "c3d4e5f6-...",
"status": "completed",
"task_type": "document",
"file_name": "bao-gia.pdf",
"page_count": 1,
"processing_ms": 1780,
"cost_vnd": 750,
"confidence": 0.95,
"result": {
"data": {
"doc_type": "quotation",
"doc_no": "BG-2026-0812",
"title": "BÁO GIÁ",
"date": "2026-08-12",
"valid_until": "2026-09-11",
"seller": {
"name": "CÔNG TY TNHH BEEKNOEE",
"tax_code": "0109876543",
"address": "Hà Nội",
"phone": "0900000000",
"email": "[email protected]"
},
"buyer": {
"name": "CÔNG TY CP THỬ NGHIỆM",
"tax_code": "0101234567",
"address": null,
"phone": null,
"email": null
},
"items": [
{ "name": "Gói API Document AI", "unit": "gói", "quantity": 2, "unit_price": 1500000, "amount": 3000000, "note": null },
{ "name": "Phí triển khai", "unit": "lần", "quantity": 1, "unit_price": 2000000, "amount": 2000000, "note": null }
],
"subtotal": 5000000,
"discount_amount": 0,
"vat_rate": 10,
"vat_amount": 500000,
"total": 5500000,
"total_in_words": "Năm triệu năm trăm nghìn đồng",
"currency": "VND",
"payment_terms": "Thanh toán 100% sau khi ký hợp đồng",
"delivery_terms": "Bàn giao trong 7 ngày làm việc",
"notes": "Báo giá có hiệu lực 30 ngày kể từ ngày phát hành."
}
},
"created_at": "2026-08-12T08:38:24.165Z"
}
doc_type có thể nhận: quotation (báo giá) · purchase_order (đơn đặt hàng) · contract (hợp đồng) · delivery_note (phiếu giao hàng) · receipt (biên lai) · invoice · other.
💡 Chọn giữa
/v1/extract/documentvà/v1/extract/invoice: hai endpoint cùng giá 750đ. Dùnginvoicekhi chứng từ là hóa đơn VAT (cầnserial, ký hiệu,payment_method). Dùngdocumentcho mọi loại còn lại — schema rộng hơn (doc_type,valid_until,discount_amount, điều khoản thanh toán/giao hàng). Field không có trên tài liệu sẽ trảnull, không bịa.
4. 📝 OCR Tài liệu
POST /v1/document/ocr
Trích xuất toàn bộ text từ ảnh hoặc PDF. Hỗ trợ tiếng Việt Unicode với độ chính xác cao.
Response mẫu:
{
"id": "65d2a852-6f7a-4e08-9bcc-90e1fbc79fa6",
"status": "completed",
"task_type": "ocr",
"file_name": "document.png",
"page_count": 1,
"processing_ms": 2699,
"cost_vnd": 250,
"cost_per_page": 250,
"confidence": 0.9,
"result": {
"data": {
"text": "CỘNG HÒA XÃ HỘI CHỦ NGHĨA VIỆT NAM\nĐộc lập - Tự do - Hạnh phúc\n\nGIẤY XÁC NHẬN THÔNG TIN\n\nHọ và tên: Nguyễn Văn An\nNgày sinh: 15/03/1990\n...",
"language": "vi",
"word_count": 52,
"blocks": [
{ "text": "CỘNG HÒA XÃ HỘI CHỦ NGHĨA VIỆT NAM\nĐộc lập - Tự do - Hạnh phúc", "type": "heading" },
{ "text": "Họ và tên: Nguyễn Văn An\nNgày sinh: 15/03/1990\n...", "type": "paragraph" }
]
}
},
"created_at": "2026-07-09T02:49:56.314Z"
}
blocks[].type: heading | paragraph | table | list.
5. 📑 PDF → Markdown
POST /v1/pdf/markdown
Chuyển đổi PDF hoặc ảnh tài liệu thành Markdown sạch. Giữ nguyên cấu trúc: heading, bảng, danh sách, bold/italic.
Response mẫu: (lưu ý — dữ liệu nằm trực tiếp trong result, không có result.data)
{
"id": "c3d4e5f6-...",
"status": "completed",
"task_type": "pdf_markdown",
"file_name": "report.pdf",
"page_count": 3,
"processing_ms": 3100,
"cost_vnd": 1500,
"cost_per_page": 500,
"confidence": 0.9,
"result": {
"markdown": "# Báo cáo Tài chính Q4/2024\n\n## 1. Tổng quan\n\nDoanh thu quý 4 đạt **500 tỷ VNĐ**, tăng 25% so với cùng kỳ năm trước.\n\n## 2. Chi tiết\n\n| Hạng mục | Q3/2024 | Q4/2024 | Thay đổi |\n|----------|---------|---------|----------|\n| Doanh thu | 400 tỷ | 500 tỷ | +25% |\n",
"title": "Báo cáo Tài chính Q4/2024",
"headings": ["1. Tổng quan", "2. Chi tiết", "2.1 Phân tích"],
"word_count": 320,
"has_tables": true,
"has_images": false
},
"created_at": "2026-07-09T02:49:56.314Z"
}
Tra cứu lịch sử Job
Mỗi request thành công đều lưu lại thành 1 job.
GET /v1/document/jobs?limit=20&offset=0&task_type=ocr
GET /v1/document/jobs/:id
Response mẫu (GET /v1/document/jobs):
{ "data": [ /* mảng job */ ], "total": 0, "limit": 20, "offset": 0 }
Ví dụ tích hợp
1. cURL — Trích xuất hóa đơn
curl -X POST https://platform.beeknoee.com/v1/extract/invoice \
-H "Authorization: Bearer sk-bee-your-key" \
-F "[email protected]" \
-F "language=vi"
2. cURL — Trích xuất báo giá / chứng từ
curl -X POST https://platform.beeknoee.com/v1/extract/document \
-H "Authorization: Bearer sk-bee-your-key" \
-F "[email protected]" \
-F "language=vi"
3. cURL — OCR tài liệu
curl -X POST https://platform.beeknoee.com/v1/document/ocr \
-H "Authorization: Bearer sk-bee-your-key" \
-F "[email protected]" \
-F "language=vi"
4. cURL — PDF sang Markdown
curl -X POST https://platform.beeknoee.com/v1/pdf/markdown \
-H "Authorization: Bearer sk-bee-your-key" \
-F "[email protected]"
5. Python — requests
import requests
API_KEY = "sk-bee-your-key"
BASE_URL = "https://platform.beeknoee.com"
# Trích xuất hóa đơn
def extract_invoice(file_path: str) -> dict:
with open(file_path, "rb") as f:
response = requests.post(
f"{BASE_URL}/v1/extract/invoice",
headers={"Authorization": f"Bearer {API_KEY}"},
files={"file": f},
data={"language": "vi"},
)
response.raise_for_status()
return response.json()
result = extract_invoice("hoadon.jpg")
data = result["result"]["data"] # ← dữ liệu nằm ở result.data
print(f"Seller: {data['seller']['name']}")
print(f"Total: {data['total']:,}đ")
print(f"Confidence: {result['confidence'] * 100:.0f}%")
print(f"Đã trừ ví: {result['cost_vnd']}đ")
6. Python — OCR + xử lý batch
import requests
from pathlib import Path
API_KEY = "sk-bee-your-key"
BASE_URL = "https://platform.beeknoee.com"
def ocr_document(file_path: str) -> str:
with open(file_path, "rb") as f:
response = requests.post(
f"{BASE_URL}/v1/document/ocr",
headers={"Authorization": f"Bearer {API_KEY}"},
files={"file": f},
data={"language": "vi"},
)
response.raise_for_status()
return response.json()["result"]["data"]["text"] # ← result.data.text
# Batch OCR: xử lý tất cả ảnh trong folder
folder = Path("./documents")
for img in folder.glob("*.png"):
text = ocr_document(str(img))
output = img.with_suffix(".txt")
output.write_text(text, encoding="utf-8")
print(f"✅ {img.name} → {output.name} ({len(text)} chars)")
7. Python — CCCD
import requests
API_KEY = "sk-bee-your-key"
BASE_URL = "https://platform.beeknoee.com"
def extract_idcard(file_path: str) -> dict:
with open(file_path, "rb") as f:
response = requests.post(
f"{BASE_URL}/v1/extract/idcard",
headers={"Authorization": f"Bearer {API_KEY}"},
files={"file": f},
)
response.raise_for_status()
return response.json()
result = extract_idcard("cccd_front.jpg")
info = result["result"]["data"] # ← result.data
print(f"Họ tên: {info['full_name']}")
print(f"Số CCCD: {info['id_number']}")
print(f"Ngày sinh: {info['date_of_birth']}")
print(f"Confidence: {result['confidence'] * 100:.0f}%")
8. Node.js — FormData
import fs from 'fs';
const API_KEY = 'sk-bee-your-key';
const BASE_URL = 'https://platform.beeknoee.com';
async function extractInvoice(filePath) {
const formData = new FormData();
formData.append('file', new Blob([fs.readFileSync(filePath)]));
formData.append('language', 'vi');
const response = await fetch(`${BASE_URL}/v1/extract/invoice`, {
method: 'POST',
headers: { 'Authorization': `Bearer ${API_KEY}` },
body: formData,
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${await response.text()}`);
}
return response.json();
}
const result = await extractInvoice('./hoadon.jpg');
const data = result.result.data; // ← result.data
console.log('Seller:', data.seller.name);
console.log('Total:', data.total.toLocaleString(), 'VNĐ');
9. Node.js — PDF to Markdown
import fs from 'fs';
const API_KEY = 'sk-bee-your-key';
const BASE_URL = 'https://platform.beeknoee.com';
async function pdfToMarkdown(filePath) {
const formData = new FormData();
formData.append('file', new Blob([fs.readFileSync(filePath)]));
const response = await fetch(`${BASE_URL}/v1/pdf/markdown`, {
method: 'POST',
headers: { 'Authorization': `Bearer ${API_KEY}` },
body: formData,
});
if (!response.ok) throw new Error(`Error: ${response.status}`);
const data = await response.json();
return data.result.markdown; // ← pdf_markdown: result.markdown (KHÔNG có .data)
}
const markdown = await pdfToMarkdown('./report.pdf');
fs.writeFileSync('report.md', markdown, 'utf-8');
console.log('✅ Saved report.md');
Error Handling
Khi lỗi, response trả về theo format OpenAI-style — chỉ có object error, không có wrapper status:
{
"error": {
"message": "Số dư không đủ. Cần: 750đ ...",
"type": "insufficient_balance",
"param": null,
"code": "insufficient_balance"
}
}
Các lỗi thường gặp
| HTTP | code | Khi nào |
|---|---|---|
| 400 | invalid_request | Thiếu field file, hoặc request không hợp lệ |
| 400 | insufficient_balance | Số dư ví không đủ |
| 400 | gemini_api_error / extraction_failed / invalid_json | AI không xử lý được (ảnh mờ, nội dung không đọc được) |
| 400 | — | Sai định dạng file, file quá lớn, hoặc vượt rate limit (message mô tả rõ) |
| 400 | — | Tính năng chưa được kích hoạt (model chưa cấu hình trong hệ thống) |
| 401 | invalid_api_key | Thiếu header Authorization, API key sai / đã thu hồi, hoặc phiên đăng nhập hết hạn |
| 403 | insufficient_permissions | Tài khoản bị vô hiệu hoá (ACCOUNT_DISABLED) hoặc đang khoá bảo mật 24h sau reset 2FA (SECURITY_LOCKED) — đọc message để biết trường hợp nào |
| 404 | route_not_found | Sai URL/method — endpoint không tồn tại. Kiểm tra lại đường dẫn trong bảng đầu trang (path đúng là /v1/..., không có /api) |
| 404 | resource_not_found | Job không tồn tại hoặc không thuộc về bạn (GET /v1/document/jobs/:id) |
⚠️ Phân biệt 401 và 403: 401 = hệ thống chưa biết bạn là ai (thiếu/sai/hết hạn token) → sửa ở phía key. 403 = đã biết bạn là ai nhưng tài khoản đang bị chặn → liên hệ hỗ trợ. Trước 12/08/2026 cả hai đều trả về 403, nay đã tách đúng.
Lưu ý: Document AI trả phần lớn lỗi nghiệp vụ dưới dạng HTTP 400 (kể cả rate limit và số dư không đủ), khác với endpoint chat (dùng 429/402). Client nên đọc
error.code/error.messagethay vì chỉ dựa vào HTTP status.
Python — Error handling với retry
import time
import requests
API_KEY = "sk-bee-your-key"
BASE_URL = "https://platform.beeknoee.com"
def extract_with_retry(endpoint: str, file_path: str, max_retries=3):
for attempt in range(max_retries):
try:
with open(file_path, "rb") as f:
response = requests.post(
f"{BASE_URL}{endpoint}",
headers={"Authorization": f"Bearer {API_KEY}"},
files={"file": f},
data={"language": "vi"},
timeout=90,
)
if response.status_code >= 500:
wait = 2 ** attempt
print(f"Server error, retry sau {wait}s...")
time.sleep(wait)
continue
response.raise_for_status()
return response.json()
except requests.exceptions.Timeout:
print(f"Timeout, retry {attempt + 1}/{max_retries}")
time.sleep(1)
raise Exception("Max retries exceeded")
# Sử dụng
result = extract_with_retry("/v1/extract/invoice", "hoadon.jpg")
print(result["result"]["data"])
Billing — Cách tính phí
- Hóa đơn VAT, CCCD/CMND và Chứng từ tổng quát: tính phí cố định mỗi tài liệu / ảnh (1 request = 1 đơn vị, PDF nhiều trang vẫn tính 1)
- OCR và PDF→Markdown: tính phí theo số trang. PDF nhiều trang = giá/trang × số trang
- Ảnh (JPEG/PNG/WebP) luôn được tính là 1 trang
- Trừ trực tiếp vào ví VNĐ; số tiền đã trừ trả về ở field
cost_vnd - Chỉ tính phí khi
status: "completed" - Request lỗi (4xx, 5xx) không bị tính phí
| Endpoint | Giá | Đơn vị |
|---|---|---|
/v1/extract/invoice | 750đ | / hóa đơn |
/v1/extract/idcard | 500đ | / ảnh |
/v1/extract/document | 750đ | / tài liệu |
/v1/document/ocr | 250đ | / trang |
/v1/pdf/markdown | 500đ | / trang |
Ví dụ:
Xử lý 100 hóa đơn: 100 × 750đ = 75,000đ
OCR 1 file PDF 50 trang: 50 × 250đ = 12,500đ
PDF→MD 1 file 20 trang: 20 × 500đ = 10,000đ
Rate Limits
Rate limit áp theo cấu hình model (RPM/RPD). Vượt giới hạn → HTTP 400 kèm message mô tả (VD: "Giới hạn tốc độ: N requests/phút").
Best Practices
- Đọc đúng vị trí dữ liệu —
invoice/idcard/document/ocrởresult.data.*;pdf_markdownởresult.markdown+ metadata trực tiếp trongresult. Field theo snake_case (tax_code,id_number,unit_price...). - Ảnh rõ nét — Đảm bảo tài liệu không bị mờ, nghiêng, hoặc cắt xén. Chất lượng ảnh ảnh hưởng trực tiếp đến
confidence. - Chọn đúng endpoint — Dùng endpoint chuyên biệt (
/extract/invoice) thay vì OCR tổng quát để có kết quả cấu trúc tốt hơn. - Kiểm tra confidence — Nếu
confidence < 0.7, nên yêu cầu user upload lại ảnh chất lượng cao hơn. - Batch processing — Xử lý nhiều file? Gọi song song (parallel) nhưng respect rate limits.
- Error retry — Luôn implement retry với exponential backoff cho lỗi 5xx.
- File size — Giới hạn cứng: ảnh ≤ 20MB, PDF ≤ 50MB. Nên compress ảnh nếu > 5MB (JPEG quality 85% thường đủ tốt) để giảm thời gian upload.
- PDF multi-page — Endpoint OCR và PDF→Markdown hỗ trợ PDF nhiều trang. Kết quả ghép tất cả các trang. Tính phí theo số trang (VD: PDF 50 trang × 250đ = 12,500đ).
Dùng thử trực tiếp
Bạn có thể dùng thử tất cả tính năng Document AI trực tiếp trên web tại trang Document AI — upload file, xem kết quả ngay không cần code.
Tiếp theo
- Chat Completions — Kết hợp Document AI + LLM để phân tích tài liệu
- Authentication — Cách tạo và quản lý API Key
- API Usage — Theo dõi chi phí sử dụng
- Error Handling — Best practices xử lý lỗi