Tạo REST API Tùy Chỉnh Với Apps Script (doGet/doPost)
Apps Script Như Một Backend API
Google Apps Script có thể deploy thành Web App, hoạt động như một REST API endpoint miễn phí. Mọi request từ website, app mobile hay công cụ automation đều có thể gọi vào API này để đọc/ghi dữ liệu Google Sheets. Chi tiết hơn tại: tự dựng URL shortener trên Google Sheets.
Cấu Trúc doGet() — Endpoint Đọc Dữ Liệu
/** * GET /exec?action=list&sheet=Orders&limit=50&token=xxx */ function doGet(e) { try { const token = PropertiesService.getScriptProperties().getProperty('API_TOKEN'); if (token && e.parameter.token !== token) { return respond({ error: 'Unauthorized' }, 401); }const action = e.parameter.action || 'list'; const sheetName = e.parameter.sheet || 'Data'; const limit = parseInt(e.parameter.limit) || 100; const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName); if (!sheet) return respond({ error: 'Sheet not found: ' + sheetName }, 404); if (action === 'count') { return respond({ count: Math.max(0, sheet.getLastRow() - 1) }); } const raw = sheet.getDataRange().getValues(); if (raw.length <= 1) return respond({ data: [], total: 0 }); const headers = raw[0]; const data = raw.slice(1, limit + 1).map(row => { const obj = {}; headers.forEach((h, i) => { obj[h] = row[i]; }); return obj; }); return respond({ data, total: raw.length - 1 });} catch (err) { return respond({ error: err.toString() }, 500); } }
function respond(data, status) { return ContentService .createTextOutput(JSON.stringify({ ...data, status: status || 200 })) .setMimeType(ContentService.MimeType.JSON); }
Cấu Trúc doPost() — Endpoint Ghi Dữ Liệu
/** * POST /exec body: { token, sheet, ...fields } */ function doPost(e) { try { let payload; if (e.postData && e.postData.type === 'application/json') { payload = JSON.parse(e.postData.contents); } else { payload = e.parameter; }const token = PropertiesService.getScriptProperties().getProperty('API_TOKEN'); if (token && payload.token !== token) return respond({ error: 'Unauthorized' }, 401); const sheetName = payload.sheet || 'Data'; const ss = SpreadsheetApp.getActiveSpreadsheet(); let sheet = ss.getSheetByName(sheetName); if (!sheet) sheet = ss.insertSheet(sheetName); // Auto-create headers nếu sheet trống if (sheet.getLastRow() === 0) { const headers = ['timestamp', ...Object.keys(payload).filter(k => k !== 'token' && k !== 'sheet')]; sheet.appendRow(headers); sheet.getRange(1, 1, 1, headers.length).setFontWeight('bold').setBackground('#f0f0f0'); } const headers = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0]; const newRow = headers.map(h => h === 'timestamp' ? new Date() : (payload[h] ?? '')); sheet.appendRow(newRow); return respond({ success: true, row: sheet.getLastRow() });
} catch (err) { console.error('doPost error: ' + err.toString()); return respond({ error: err.toString() }, 500); } }
Deploy Web App Và Cài Token
- Apps Script Editor → Deploy → New deployment
- Type: Web app | Execute as: Me | Access: Anyone
- Copy URL → Dùng trong curl, Postman hay code client
// Chạy một lần để tạo token
function setupApiToken() {
const token = Utilities.getUuid();
PropertiesService.getScriptProperties().setProperty('API_TOKEN', token);
Logger.log('API_TOKEN: ' + token);
}Test Với curl
# Đọc dữ liệu curl "https://script.google.com/macros/s/AKfy.../exec?action=list&sheet=Orders&token=YOUR_TOKEN&limit=10"Ghi dữ liệu
curl -X POST "https://script.google.com/macros/s/AKfy.../exec" -H "Content-Type: application/json" -d '{"token":"YOUR_TOKEN","sheet":"Orders","name":"Nguyen Van A","amount":500000}'
Giới Hạn Cần Biết
- Không hỗ trợ custom HTTP status codes — status trả trong JSON body.
- Quota: 20.000 request/ngày (tài khoản cá nhân), không giới hạn với Workspace.
- Execution time tối đa 6 phút/request — không phù hợp tác vụ nặng.
- CORS: Apps Script tự xử lý, dùng được từ browser.
Câu Hỏi Thường Gặp
Apps Script Web App có dùng được cho production thật không?
Dùng được cho các ứng dụng nội bộ, MVP, hoặc tích hợp quy mô vừa. Với hệ thống cần uptime cao và không giới hạn quota, nên cân nhắc backend riêng — nhưng với hầu hết nhu cầu ghi/đọc dữ liệu vào Sheets, Apps Script đã đủ ổn định.
Làm sao bảo mật endpoint doPost để tránh bị spam request?
Ngoài kiểm tra token trong body request, nên thêm giới hạn tần suất bằng cách lưu timestamp request gần nhất vào PropertiesService và từ chối nếu gọi quá nhanh. Không nên public URL Web App công khai nếu không có xác thực.
Tại sao gọi API từ trình duyệt bị lỗi CORS dù đã deploy đúng?
Kiểm tra lại quyền truy cập khi deploy là "Anyone" (không phải "Anyone with Google account"), vì Apps Script chỉ tự xử lý CORS khi Web App cho phép truy cập ẩn danh.
Web App URL có thay đổi sau mỗi lần deploy lại không?
Nếu dùng "Manage deployments" và chọn deploy bản mới cho cùng deployment ID, URL giữ nguyên. Nếu tạo "New deployment" mới, URL sẽ đổi — cần cập nhật lại ở phía gọi API.
💡 Giải pháp sẵn có cho bạn
Không muốn tự làm? Dùng ngay Phần Mềm Quản Lý Bán Hàng bằng Google Sheet — đầy đủ tính năng, cài đặt nhanh.
Xem sản phẩm →📚 Bài Viết Liên Quan
Chia sẻ bài viết:
Tuân Hoang
Đội ngũ SheetStore
Google Workspace Certified, 5+ years experience
Bạn thấy bài viết hữu ích?
Đăng ký nhận thông báo khi có bài viết mới.