AI GO 系統串接指南(Integration Guide)
版本: 1.4 | 更新日期: 2026-04-08 | API 版本: v1
本文檔完整說明第三方應用(Integrations)如何透過「引用」與「API」串接 AI GO 系統,涵蓋所有可被引用的 API Endpoint、資料表(Table)、Custom Table(動態資料表)、Schema 與欄位定義。
目錄
- 系統總覽與架構
- 認證機制
- 整合管理 API
- 引用系統 API
- 資料代理 Proxy API(Open Proxy)
- Custom Table API(動態資料表)
- External Auth(跳轉登入)
- 可引用的資料表與 Schema 完整清單
- 錯誤碼與限制
- Proxy 查詢完整安全機制與功能限制
- Enum 值速查附錄
- 第三方應用實戰指南(Best Practices & Gotchas)
1. 系統總覽與架構
1.1 系統定位
AI GO 是一套企業級 PaaS ERP 平台,提供會計、銷售、採購、庫存、CRM、HR、MRP、專案管理等完整模組。透過 Integration(整合) 機制,第三方開發者可建立自建應用(Self-Built App),安全地存取 AI GO 的企業資料。
1.2 三種應用存取模式
| 特性 | Internal(內部) | External(外部) | Self-Built(自建) |
|---|---|---|---|
| 使用場景 | 組織內部工具 | 對外客戶/供應商應用 | 第三方獨立系統串接 |
| 認證方式 | Supabase Auth JWT | Custom App Auth | API Key / One-Time Code |
| 程式碼託管 | AI GO Builder | AI GO Builder | 第三方自行部署 |
| 資料存取 | Internal Proxy | External Proxy | Open Proxy |
| 引用需發布 | 否(即時生效) | 否(即時生效) | 是(需發布快照) |
access_mode | internal | external | self_built |
本文檔聚焦於 Self-Built(自建)模式,這是第三方整合的核心使用場景。
1.3 整體架構流程
sequenceDiagram
participant Dev as 開發者(管理端)
participant AIGO as AI GO API
participant App as 第三方應用
Note over Dev,App: === 第一階段:建立整合 ===
Dev->>AIGO: POST /integrations(建立自建應用)
AIGO-->>Dev: 回傳 app_id, slug
Dev->>AIGO: POST /integrations/{app_id}/api-keys(產生 API Key)
AIGO-->>Dev: 回傳 sk_live_xxx...(僅此一次)
Note over Dev,App: === 第二階段A:設定系統表引用 ===
Dev->>AIGO: GET /refs/available-tables(查看可引用的表)
Dev->>AIGO: GET /refs/tables/{name}/columns(查看欄位)
Dev->>AIGO: POST /refs/apps/{app_id}(建立引用 + 設定權限)
Note over Dev,App: === 第二階段B:建立 Custom Table ===
Dev->>AIGO: 在 AI GO 管理介面建立 Custom Table 及欄位定義
Note over Dev,App: === 第三階段:發布 ===
Dev->>AIGO: POST /integrations/{app_id}/publish(發布引用設定)
AIGO-->>Dev: 快照 columns + permissions 為 published 版本
Note over Dev,App: === 第四階段:存取資料 ===
App->>AIGO: GET /open/proxy/{table}(系統資料表)
AIGO-->>App: 回傳已授權欄位的資料(tenant 隔離)
App->>AIGO: GET /open/data/objects/{slug}/records(Custom Table)
AIGO-->>App: 回傳 Custom Table 記錄(tenant 隔離)
2. 認證機制
2.1 API Key Server-to-Server 認證(主要方式)
適用於 Self-Built 應用的後端對後端通訊。
API Key 格式:sk_live_ + 64 字元十六進位隨機字串
使用方式:在每個 HTTP 請求的 Header 中攜帶:
X-API-Key: sk_live_a1b2c3d4e5f6...
驗證流程:
系統會自動驗證 API Key 的有效性與所屬應用,並自動取得 app_id 和 tenant_id(不需額外傳遞)。無效或已撤銷的 Key 會回傳 401 Unauthorized。
安全建議:
- API Key 僅在建立時回傳一次完整明文,請妥善保存
- 建議將 Key 存放於環境變數或密鑰管理服務,不要寫入程式碼
- 定期輪換 Key(撤銷舊 Key → 建立新 Key)
- 同一整合可建立多把 Key(如 Production / Staging 分離)
2.2 One-Time Code 跳轉登入(Platform Auth Mode)
適用於「主站已登入用戶無縫跳轉至第三方應用」的場景。需設定 auth_mode = "platform"。
sequenceDiagram
participant User as 主站用戶
participant AIGO as AI GO API
participant App as 第三方應用
User->>AIGO: POST /integrations/{app_id}/launch(攜帶 JWT)
AIGO-->>User: { redirect_url, code, expires_in: 60 }
User->>App: 重導至 callback_url?code=xxx
App->>AIGO: POST /ext/auth/exchange(X-API-Key + code)
AIGO-->>App: { access_token, user: {id, email, name} }
Note over App: 使用 access_token 呼叫 Open Proxy
App->>AIGO: POST /ext/auth/refresh(X-API-Key + token)
AIGO-->>App: { access_token(新) }
Code 特性:有效期 60 秒、一次性使用、綁定特定 app_id
2.3 Custom App User 認證(Independent 模式)
設定 auth_mode = "independent" 時,AI GO 平台為此整合提供完整的獨立用戶認證系統,包含:
- Email + 密碼:註冊 / 登入
- OAuth 第三方登入:LINE、Google、Facebook 等(參見 §2.4)
- JWT Access Token + Refresh Token Rotation
- Builder 端用戶管理:啟用 / 停用 / 刪除
重要:Independent 模式不需要第三方開發者自行建立認證系統。AI GO 已提供現成的認證 API,開發者只需要呼叫這些端點即可為自己的應用實現完整的用戶註冊與登入功能。
2.3.1 認證流程總覽
sequenceDiagram
participant User as 終端用戶
participant App as 第三方前端
participant AIGO as AI GO API
alt Email + 密碼
User->>App: 填寫註冊 / 登入表單
App->>AIGO: POST /custom-app-auth/{slug}/register 或 login
AIGO-->>App: { access_token, refresh_token, user }
else OAuth 登入(如 LINE)
User->>App: 點擊 LINE 登入
App->>AIGO: GET /custom-app-oauth/{slug}/line/authorize
AIGO-->>User: 302 重導 LINE 授權頁
User->>AIGO: 授權回呼
AIGO-->>App: 302 redirect?oauth_token=<base64 encoded tokens>
end
Note over App: 儲存 access_token + refresh_token
App->>AIGO: GET /custom-app-auth/{slug}/me(Bearer Token)
AIGO-->>App: { user info }
Note over App: Token 即將過期時
App->>AIGO: POST /custom-app-auth/{slug}/refresh
AIGO-->>App: { new access_token, new refresh_token }
路徑說明:所有 Custom App User 認證端點以
app_slug(非app_id)作為路徑參數。slug可在整合詳情頁面的標題旁查看(12 位元十六進位字串)。系統也支援以subdomain替代slug。
2.3.2 註冊(Register)
POST /api/v1/custom-app-auth/{app_slug}/register
認證:無需認證(公開端點)
Request Body:
{
"email": "user@example.com",
"password": "my_secure_password",
"display_name": "王小明"
}
| 欄位 | 型別 | 必填 | 驗證規則 |
|---|---|---|---|
email | string | ✅ | 合法 email 格式,1~255 字元,自動轉小寫 |
password | string | ✅ | 6~128 字元 |
display_name | string | ✅ | 1~100 字元 |
Response 201 Created:
{
"access_token": "eyJhbGciOiJIUzI1NiI...",
"refresh_token": "a1b2c3d4e5f6...",
"expires_in": 900,
"token_type": "Bearer",
"user": {
"id": "uuid",
"custom_app_id": "uuid",
"tenant_id": "uuid",
"email": "user@example.com",
"display_name": "王小明",
"avatar_url": null,
"extra_data": {},
"is_active": true,
"last_login_at": null,
"created_at": "2026-04-01T00:00:00Z",
"updated_at": null
}
}
錯誤碼:
| HTTP Code | detail | 原因 |
|---|---|---|
409 | 此 Email 已被註冊 | 同一 App 下 email 不可重複 |
403 | 此來源不在白名單中 | Origin 不在 allowed_origins 白名單中 |
404 | App 不存在 | slug 無效 |
403 | 此 App 不支援用戶認證 | access_mode 非 external / self_built |
2.3.3 登入(Login)
POST /api/v1/custom-app-auth/{app_slug}/login
認證:無需認證(公開端點)
Request Body:
{
"email": "user@example.com",
"password": "my_secure_password"
}
Response 200 OK:格式同 §2.3.2 註冊 的 Response
錯誤碼:
| HTTP Code | detail | 原因 |
|---|---|---|
401 | 帳號或密碼錯誤 | email 不存在或密碼不符 |
403 | 帳號已被停用 | 使用者已被 Builder 停用 |
2.3.4 取得當前用戶(Me)
GET /api/v1/custom-app-auth/{app_slug}/me
認證:Bearer Token(Access Token)
Authorization: Bearer eyJhbGciOiJIUzI1NiI...
Response 200 OK:
{
"id": "uuid",
"custom_app_id": "uuid",
"tenant_id": "uuid",
"email": "user@example.com",
"display_name": "王小明",
"avatar_url": "https://...",
"extra_data": {},
"is_active": true,
"last_login_at": "2026-04-01T12:00:00Z",
"created_at": "2026-04-01T00:00:00Z",
"updated_at": null
}
錯誤碼:
| HTTP Code | detail | 原因 |
|---|---|---|
401 | 未提供認證 Token | 缺少 Authorization header |
401 | 無效或已過期的 Token | Access Token 過期或格式不正確 |
403 | 帳號已被停用 | 使用者已被停用 |
2.3.5 刷新 Token(Refresh)
POST /api/v1/custom-app-auth/{app_slug}/refresh
認證:無需 Bearer Token(公開端點,需 refresh_token 作為 Body 參數)
Request Body:
{
"refresh_token": "a1b2c3d4e5f6..."
}
Response 200 OK:格式同 §2.3.2 註冊 的 Response(包含全新的 access_token 和 refresh_token)
⚠️ Token Rotation:每次 refresh 成功後,舊的 Refresh Token 立即失效(撤銷)。請務必儲存並使用回傳的新
refresh_token。
錯誤碼:
| HTTP Code | detail | 原因 |
|---|---|---|
401 | 無效的 Refresh Token | Token 不存在或已被撤銷 |
401 | Refresh Token 已過期 | 超過 7 天有效期 |
401 | 使用者不存在或已停用 | 用戶帳號已刪除或停用 |
2.3.6 登出(Logout)
POST /api/v1/custom-app-auth/{app_slug}/logout
認證:Bearer Token(Access Token)
Request Body:
{
"refresh_token": "a1b2c3d4e5f6..."
}
Response 200 OK:
{
"message": "已登出"
}
2.3.7 ext/ 端點群:Custom App User 專用 API
以下端點需以 Custom App User Token(Bearer)認證,適用於 Independent 模式的前端直接存取資料:
| 端點前綴 | 說明 | 備註 |
|---|---|---|
/api/v1/ext/proxy/ | 存取系統資料表 | 與 Open Proxy 相同引擎,認證方式不同 |
/api/v1/ext/data/ | 存取 Custom Table | 與 /open/data/ 對應 |
/api/v1/ext/compile/ | 取得/執行 VFS 前端渲染程式碼 | 適用於 AI GO 託管的前端 |
/api/v1/ext/actions/ | 執行 Server-Side Actions | 執行後端自動化動作 |
/api/v1/ext/storage/ | 存取 Supabase Storage 檔案 | 上傳/下載應用相關檔案 |
使用方式:
# 使用 Custom App User Token 存取系統資料表
curl -H "Authorization: Bearer <access_token>" \
https://api.ai-go.app/api/v1/ext/proxy/customers
# 使用 Custom App User Token 存取 Custom Table
curl -H "Authorization: Bearer <access_token>" \
https://api.ai-go.app/api/v1/ext/data/objects/group_tour/records
與 Open Proxy 的區別:
/ext/*端點使用 Bearer Token(Custom App User Token),tenant_id和custom_app_id從 Token payload 自動解析/open/*端點使用 API Key(X-API-Key),適用於後端 Server-to-Server 呼叫- 兩者共用相同的引用白名單和資料過濾引擎
2.3.8 網域白名單(Origin 檢查)
設定 allowed_origins 後,Custom App Auth 端點(register / login 等)會檢查 HTTP Origin header:
| 情境 | 行為 |
|---|---|
| 白名單為空 | 放行所有來源(尚未設定) |
| 無 Origin header(後端呼叫 / curl) | 放行 |
| Origin 在白名單中 | 放行 |
| Origin 不在白名單中 | 回傳 403 此來源不在白名單中 |
⚠️ Port 注意事項:Port 是 Origin 的一部分(RFC 6454),例如
http://localhost:3000≠http://localhost:8000。設定白名單時需包含完整的scheme://host:port。
2.3.9 Builder 端用戶管理 API
以下端點供整合管理者(Builder)在 AI GO 管理介面中管理 Custom App 的用戶,需主站 JWT 認證(builder.access 權限):
| 端點 | 說明 |
|---|---|
GET /api/v1/custom-app-auth/manage/{app_id}/users | 列出 App 所有用戶 |
PATCH /api/v1/custom-app-auth/manage/{app_id}/users/{user_id} | 啟用/停用用戶(Body: { "is_active": false }) |
DELETE /api/v1/custom-app-auth/manage/{app_id}/users/{user_id} | 刪除用戶(連帶刪除所有 Session) |
停用或刪除用戶後,該用戶的認證快取會立即清除,已發出的 Access Token 在快取 TTL(60 秒)後將無法使用。
2.4 OAuth 第三方登入(LINE 等)
Independent 模式的整合可額外設定 OAuth Provider(如 LINE Login),讓終端用戶透過第三方帳號直接登入。
2.4.1 前置設定
Builder 需在 AI GO 管理介面為 App 設定 OAuth Provider:
- 進入整合管理 → 選擇 App → 設定 Tab
- 填入 Provider 的 Client ID 和 Client Secret(系統會以 AES-256 加密儲存)
- 在第三方平台(如 LINE Developers Console)設定 Callback URL 為:
https://<YOUR_API_HOST>/api/v1/custom-app-oauth/{app_slug}/{provider}/callback
2.4.2 OAuth 端點清單
| 端點 | 認證 | 說明 |
|---|---|---|
GET /api/v1/custom-app-oauth/{slug}/auth-providers | 無 | 列出已啟用的 provider |
GET /api/v1/custom-app-oauth/{slug}/{provider}/authorize | 無 | 302 重導至第三方授權頁 |
GET /api/v1/custom-app-oauth/{slug}/{provider}/callback | 無 | 第三方回呼處理(系統內部) |
POST /api/v1/custom-app-oauth/{slug}/oauth/complete-email | 無 | 補填 email(Body: { "pending_token": "...", "email": "..." }) |
目前支援的
provider值:line(LINE Login)。Google、Facebook、GitHub 等架構已就緒。
2.4.3 OAuth 登入流程
sequenceDiagram
participant User as 終端用戶
participant App as 第三方前端
participant AIGO as AI GO API
participant LINE as LINE Login
App->>AIGO: GET /{slug}/auth-providers
AIGO-->>App: [{ "provider": "line" }]
User->>App: 點擊 LINE 登入按鈕
App->>AIGO: GET /{slug}/line/authorize
AIGO-->>User: 302 → LINE 授權頁
User->>LINE: 同意授權
LINE-->>AIGO: callback?code=xxx&state=yyy
alt 有 email
AIGO-->>App: 302 → {app_url}?oauth_token=<base64>
Note over App: base64 解碼得到<br/>{ access_token, refresh_token, user }
else 無 email
AIGO-->>App: 302 → {app_url}?oauth_pending=<token>
App->>User: 顯示補填 email 表單
User->>App: 輸入 email
App->>AIGO: POST /{slug}/oauth/complete-email
AIGO-->>App: { access_token, refresh_token, user }
end
2.4.4 OAuth Token 傳遞方式
OAuth 登入成功後,系統透過 query parameter 將 token 回傳至 App 的 live_url:
| Query Parameter | 說明 |
|---|---|
oauth_token | Base64 URL-safe 編碼的 JSON 字串,包含完整 token 和用戶資訊 |
oauth_pending | 無 email 時的暫時 token(有效 30 分鐘),前端需顯示補填 email 表單 |
oauth_error | OAuth 過程中發生錯誤時的錯誤描述文字 |
前端解碼範例:
// OAuth 登入成功後解碼 token
const params = new URLSearchParams(window.location.search);
const encoded = params.get('oauth_token');
if (encoded) {
const decoded = JSON.parse(atob(encoded));
// decoded = { access_token, refresh_token, expires_in, user }
localStorage.setItem('access_token', decoded.access_token);
localStorage.setItem('refresh_token', decoded.refresh_token);
}
2.4.5 OAuth 帳號綁定行為
| 情境 | 系統行為 |
|---|---|
| OAuth identity 已存在(已綁定) | 直接登入,更新 profile |
| 有 email 且同 email 帳號已存在 | 自動綁定 OAuth identity 到現有帳號 |
| 有 email 但無現有帳號 | 自動註冊新帳號 + 建立 identity |
| 無 email | 回傳 oauth_pending token,等待補填 |
⚠️ OAuth 用戶的
password_hash為null,無法使用 Email + 密碼登入。若需要啟用密碼登入,用戶需另行設定密碼。
2.5 Token 技術規格對照表
AI GO 系統針對不同認證模式使用不同的 Token 機制:
| 項目 | Platform 模式 Token | Independent 模式 Token |
|---|---|---|
| 簽發函式 | create_app_token() | create_custom_app_user_token() |
| JWT 演算法 | HS256 | HS256 |
Payload scope | app_runtime | app_runtime |
Payload auth_type | (無) | custom_app_user |
Payload sub | 主站 User UUID | Custom App User UUID |
| Access Token TTL | 1 小時 | 15 分鐘(900 秒) |
| Refresh 機制 | API Key + 舊 Token 換新 Token | Refresh Token Rotation(舊 token 立即撤銷) |
| Refresh Token TTL | (無獨立 refresh token) | 7 天 |
| Refresh Token 格式 | (不適用) | 64 字元 hex 隨機字串 |
| Refresh Token 儲存 | (不適用) | SHA-256 hash 後寫入 DB |
| 密碼雜湊 | (不適用) | bcrypt(自動 salt) |
Access Token JWT Payload 範例(Independent 模式)
{
"sub": "550e8400-e29b-41d4-a716-446655440000",
"custom_app_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"tenant_id": "11111111-2222-3333-4444-555555555555",
"auth_type": "custom_app_user",
"scope": "app_runtime",
"iat": 1711929600,
"exp": 1711930500
}
關鍵區分:
auth_type欄位是區分 Platform Token 與 Independent Token 的關鍵。Independent 模式的 Token 固定為"custom_app_user",/ext/*端點會據此驗證身份。
2.5.1 Quick Start:30 分鐘完成 Independent 模式整合
以下是端對端整合的最小步驟:
Step 1 — 建立整合並取得 API Key:
# 在 AI GO 管理介面建立新整合(選擇「獨立用戶」模式)
# 取得 app_slug(如 e9abbb866184)和 API Key(如 sk_live_xxx)
Step 2 — 設定網域白名單:
在設定 Tab 中將前端 Origin(如 https://myapp.example.com)加入白名單。
Step 3 — 前端串接範例(JavaScript):
const API_BASE = 'https://api.ai-go.app/api/v1';
const APP_SLUG = 'e9abbb866184';
// ── 1. 使用者註冊 ──
async function register(email, password, displayName) {
const res = await fetch(`${API_BASE}/custom-app-auth/${APP_SLUG}/register`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email, password, display_name: displayName }),
});
const data = await res.json();
if (!res.ok) throw new Error(data.detail);
// 儲存 token
localStorage.setItem('access_token', data.access_token);
localStorage.setItem('refresh_token', data.refresh_token);
return data.user;
}
// ── 2. 使用者登入 ──
async function login(email, password) {
const res = await fetch(`${API_BASE}/custom-app-auth/${APP_SLUG}/login`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email, password }),
});
const data = await res.json();
if (!res.ok) throw new Error(data.detail);
localStorage.setItem('access_token', data.access_token);
localStorage.setItem('refresh_token', data.refresh_token);
return data.user;
}
// ── 3. 使用 Token 存取資料 ──
async function fetchCustomers() {
const token = localStorage.getItem('access_token');
const res = await fetch(`${API_BASE}/ext/proxy/customers`, {
headers: { 'Authorization': `Bearer ${token}` },
});
return res.json();
}
// ── 4. Token 刷新 ──
async function refreshTokens() {
const refreshToken = localStorage.getItem('refresh_token');
const res = await fetch(`${API_BASE}/custom-app-auth/${APP_SLUG}/refresh`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ refresh_token: refreshToken }),
});
const data = await res.json();
if (!res.ok) throw new Error(data.detail);
// ⚠️ 務必更新兩個 token(Token Rotation)
localStorage.setItem('access_token', data.access_token);
localStorage.setItem('refresh_token', data.refresh_token);
return data;
}
Step 4 — 後端 Server-to-Server 存取資料(Python):
import requests
API_KEY = 'sk_live_a1b2c3d4...'
API_BASE = 'https://api.ai-go.app/api/v1'
# 直接用 API Key 存取資料(不涉及用戶認證)
resp = requests.get(
f'{API_BASE}/open/proxy/customers',
headers={'X-API-Key': API_KEY},
)
print(resp.json())
3. 整合管理 API
前綴:
/api/v1/integrations認證:主站 JWT(需builder.access權限)
3.1 列出所有整合
GET /api/v1/integrations
Response 200 OK:
[
{
"id": "uuid",
"tenant_id": "uuid",
"name": "我的 ERP 整合",
"slug": "e9abbb866184",
"subdomain": "my-erp",
"live_url": "https://my-erp.example.com",
"allowed_origins": ["https://my-erp.example.com"],
"auth_mode": "independent",
"api_key_count": 2,
"created_at": "2026-03-01T00:00:00Z",
"updated_at": "2026-03-20T00:00:00Z"
}
]
3.2 建立新整合
POST /api/v1/integrations
| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
name | string | ✅ | 整合名稱(1-100 字) |
subdomain | string | ❌ | 自訂子域名(2-63 字、全域唯一) |
auth_mode | string | ❌ | "platform" 或 "independent"(預設),建立後不可變更 |
Response 201 Created:IntegrationDetail 物件
3.3 取得整合詳情
GET /api/v1/integrations/{app_id}
Response 200 OK:
{
"id": "uuid",
"tenant_id": "uuid",
"name": "...",
"slug": "...",
"subdomain": null,
"live_url": null,
"allowed_origins": [],
"auth_callback_url": null,
"auth_mode": "independent",
"access_mode": "self_built",
"created_at": "...",
"updated_at": "..."
}
3.4 重新命名
PATCH /api/v1/integrations/{app_id}/name
| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
name | string | ✅ | 新名稱(1-100 字) |
3.5 更新設定
PATCH /api/v1/integrations/{app_id}/settings
| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
live_url | string | ❌ | 上線 URL(最長 500 字) |
allowed_origins | string[] | ❌ | 網域白名單(CORS 限制) |
auth_callback_url | string | ❌ | 接收 One-Time Code 的 callback URL |
3.6 刪除整合
DELETE /api/v1/integrations/{app_id}
Response 204 No Content(連帶刪除所有 API Keys)
3.7 API Key 管理
列出 API Keys
GET /api/v1/integrations/{app_id}/api-keys
Response 200 OK:
[
{
"id": "uuid",
"app_id": "uuid",
"key_prefix": "sk_live_a1b2",
"name": "Production Key",
"is_active": true,
"last_used_at": "2026-03-20T12:00:00Z",
"expires_at": null,
"created_at": "2026-03-01T00:00:00Z"
}
]
建立 API Key
POST /api/v1/integrations/{app_id}/api-keys
| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
name | string | ✅ | Key 名稱(1-100 字),如 "Production Key" |
Response 201 Created:
{
"id": "uuid",
"app_id": "uuid",
"key_prefix": "sk_live_a1b2",
"name": "Production Key",
"api_key": "sk_live_a1b2c3d4e5f6g7h8...",
"created_at": "..."
}
⚠️
api_key欄位僅在建立時回傳一次,請立即妥善保存。
撤銷 API Key
DELETE /api/v1/integrations/{app_id}/api-keys/{key_id}
Response 204 No Content
3.8 發布審核流程
引用設定修改後,需通過「發布」才能在 Open Proxy 中生效。
發布整合
POST /api/v1/integrations/{app_id}/publish
| Query | 型別 | 說明 |
|---|---|---|
note | string | 發布備註 |
行為:
- 有
builder.publish權限 → 直接發布(自動 approved) - 無
builder.publish權限 → 建立 pending 申請等候審核
列出發布申請
GET /api/v1/integrations/{app_id}/publish-requests
核准 / 拒絕 / 取消發布申請
POST /api/v1/integrations/{app_id}/publish-requests/{req_id}/approve
POST /api/v1/integrations/{app_id}/publish-requests/{req_id}/reject
POST /api/v1/integrations/{app_id}/publish-requests/{req_id}/cancel
approve:需builder.publish權限reject:需builder.publish權限,Body:{ "reject_reason": "..." }cancel:僅申請者本人可取消
取得發布狀態
GET /api/v1/integrations/{app_id}/publish-status
Response:
{
"can_publish": true,
"is_locked": false,
"pending_request": null,
"published_at": "2026-03-20T00:00:00Z"
}
4. 引用系統 API
前綴:
/api/v1/refs認證:主站 JWT(需builder.access權限)
引用(Reference)是 AI GO 的資料授權核心機制。每個整合必須先建立引用,指定要存取哪些表的哪些欄位,以及具備什麼操作權限。
4.1 列出可引用的表
GET /api/v1/refs/available-tables
Response 200 OK:
[
{ "name": "customers", "comment": "客戶" },
{ "name": "sale_orders", "comment": "銷售訂單" },
{ "name": "product_products", "comment": "" }
]
4.2 取得表的欄位資訊
GET /api/v1/refs/tables/{table_name}/columns
Response 200 OK:
[
{
"name": "name",
"type": "VARCHAR",
"nullable": false,
"is_system": false
},
{
"name": "email",
"type": "VARCHAR",
"nullable": true,
"is_system": false
},
{
"name": "customer_id",
"type": "UUID",
"nullable": true,
"is_system": false,
"is_fk": true,
"fk_target": "customers.id"
}
]
4.3 引用 CRUD
列出 App 的所有引用
GET /api/v1/refs/apps/{app_id}
建立引用
POST /api/v1/refs/apps/{app_id}
| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
table_name | string | ✅ | 要引用的表名,如 "customers" |
columns | string[] | ❌ | 授權的欄位清單,如 ["name", "email", "phone"] |
permissions | string[] | ❌ | 權限清單,如 ["read", "create"] |
更新引用
PATCH /api/v1/refs/{ref_id}
| 欄位 | 型別 | 說明 |
|---|---|---|
columns | string[] | 新的授權欄位清單 |
permissions | string[] | 新的權限清單 |
刪除引用
DELETE /api/v1/refs/{ref_id}
4.4 權限值說明
| 權限 | 對應 Proxy 操作 | 說明 |
|---|---|---|
read | GET / POST query | 查詢資料 |
create | POST insert | 新增記錄 |
update | PATCH | 更新記錄 |
delete | DELETE | 刪除記錄 |
4.5 不可引用的表
系統核心表(如身份驗證、租戶管理、權限設定、稽核紀錄等)因安全原因永遠不可被引用。嘗試引用這些表時,API 會回傳 403 此表不可引用。
可引用的表清單請透過 GET /api/v1/refs/available-tables API 查詢。
4.6 系統欄位
以下欄位由系統自動管理,寫入時會被自動排除:
| 欄位 | 型別 | 說明 |
|---|---|---|
id | UUID | 主鍵,自動生成 |
created_at | timestamptz | 建立時間,自動設定 |
updated_at | timestamptz | 更新時間,自動更新 |
tenant_id | UUID | 租戶 ID,自動注入(row-level 隔離) |
4.7 共用業務欄位:custom_data(JSONB)
所有功能性資料表皆包含 custom_data 欄位,專為第三方應用儲存業態專屬的自訂資料設計。
| 特性 | 說明 |
|---|---|
| 型別 | JSONB(PostgreSQL 原生 JSON 二進位格式) |
| 預設值 | '{}'::jsonb(空 JSON 物件) |
| Nullable | 是(可設為 null) |
| 存取方式 | 僅透過 Proxy API(Internal / External / Open) |
| 資料隔離 | 遵循現有 tenant_id row-level 隔離機制 |
使用方式:在建立引用時將 custom_data 加入 columns 清單:
{
"table_name": "customers",
"columns": ["id", "name", "email", "custom_data"],
"permissions": ["read", "create", "update"]
}
⚠️ 若引用的
columns中未包含custom_data,則該 App 在讀取時不會看到此欄位,寫入時也會被自動忽略。
5. 資料代理 Proxy API(Open Proxy)
前綴:
/api/v1/open/proxy認證:API Key(X-API-KeyHeader) 資料隔離:自動以 Key 所屬的tenant_id做 row-level 過濾 引用版本:使用已發布(published)的引用快照
5.0 三套 Proxy 對照表
系統提供三套 Proxy 端點,共用同一個核心查詢引擎,差異僅在認證方式與引用版本:
| 特性 | Internal Proxy | External Proxy | Open Proxy(自建應用) |
|---|---|---|---|
| URL 前綴 | /api/v1/proxy/{app_id}/ | /api/v1/ext/proxy/ | /api/v1/open/proxy/ |
| 認證方式 | Supabase Auth JWT | Custom App Token | API Key(X-API-Key) |
路徑需 app_id | ✅ | ❌(Token 自帶) | ❌(Key 自帶) |
| 引用版本 | columns + permissions(即時) | published_columns + published_permissions(需發布) | published_columns + published_permissions(需發布) |
簡單查詢 limit 上限 | 500 | 1000 | 1000 |
| 支援進階查詢 | ✅ | ✅ | ✅(完整支援 filter / search / order_by) |
重要:自建應用透過 Open Proxy 同樣支援完整的進階查詢功能(filters、search、order_by、select、count_only 等),並非只有
limit/offset。使用POST /{table_name}/query即可。
External Proxy 認證說明:External Proxy(
/ext/proxy/)需使用 Custom App User Token(Bearer)認證,適用於 Independent 模式的前端直接存取資料。Token 的取得方式請參閱 §2.3 Custom App User 認證。
5.1 簡單查詢
GET /api/v1/open/proxy/{table_name}?limit=100&offset=0
| Query | 型別 | 預設 | 說明 |
|---|---|---|---|
limit | int | 100 | 每頁筆數(最大 1000) |
offset | int | 0 | 偏移量 |
Response 200 OK:
[
{
"id": "uuid",
"name": "客戶 A",
"email": "a@example.com",
"phone": "0912345678"
}
]
5.2 進階查詢
POST /api/v1/open/proxy/{table_name}/query
Request Body:
{
"filters": [
{ "column": "status", "op": "eq", "value": "active" },
{ "column": "amount_total", "op": "gte", "value": 1000 }
],
"order_by": [
{ "column": "created_at", "direction": "desc" }
],
"search": "關鍵字",
"search_columns": ["name", "email"],
"select_columns": ["id", "name", "email"],
"limit": 50,
"offset": 0,
"count_only": false
}
Filter 運算子
| 運算子 | SQL 對應 | 說明 | value 型別 |
|---|---|---|---|
eq | = | 等於 | any |
ne | != | 不等於 | any |
gt | > | 大於 | number/string |
gte | >= | 大於等於 | number/string |
lt | < | 小於 | number/string |
lte | <= | 小於等於 | number/string |
like | LIKE | 模糊匹配(區分大小寫) | string |
ilike | ILIKE | 模糊匹配(不區分大小寫) | string |
is_null | IS NULL | 為空 | 不需要 |
is_not_null | IS NOT NULL | 不為空 | 不需要 |
in | IN (...) | 包含於列表 | array |
Filter 組合邏輯
- 多個 filter 之間以 AND 連接
- 不支援 OR 組合(例外:
search功能在多個搜尋欄之間使用 OR) - 不支援巢狀分組條件(如
(A AND B) OR (C AND D)) - 若需要 BETWEEN 效果,可組合
gte+lte兩個 filter
範例 — 查詢金額 ≥ 1000 且狀態為 active 的銷售訂單:
{
"filters": [
{ "column": "amount_total", "op": "gte", "value": 1000 },
{ "column": "state", "op": "eq", "value": "sale" }
]
}
Search 全文搜尋行為
search會對search_columns(或所有授權非 id 欄位)執行ILIKE '%keyword%'- 多個搜尋欄之間以 OR 連接(任一欄位命中即回傳)
- search 與 filters 之間為 AND(兩者同時滿足)
- 搜尋時欄位值會被 cast 為
text型別,因此也可搜尋數值或 UUID 欄位
count_only 模式
設定 "count_only": true 時,僅回傳符合條件的總筆數(filters 與 search 均生效):
{ "total": 42 }
5.3 新增記錄
[!WARNING] Proxy API 操作不觸發業務單據自動生成 (Workflow Triggers) 透過 Proxy API 新增或更新業務資料(如將訂單
state改為sale),系統 不會 自動建立後續單據(如自動產生出貨單、發票)。Proxy API 為「資料層代理」,第三方應用需自行INSERT所有相關單據,但特定欄位(如已開票量、付款狀態等)系統會自動維護。各表的「自動觸發流程(Triggers)」請參閱第 8 章。
POST /api/v1/open/proxy/{table_name}
Request Body:
{
"name": "新客戶",
"email": "new@example.com",
"phone": "0912345678",
"custom_data": {
"passport_no": "A123456789",
"travel_pref": ["eco", "window_seat"]
}
}
custom_data接受任意 JSON 結構(物件、陣列、巢狀皆可)。
Response 201 Created:
{
"id": "uuid",
"created_at": "2026-03-24T00:00:00Z",
"data": {
"name": "新客戶",
"email": "new@example.com",
"custom_data": "{\"passport_no\": \"A123456789\"}"
}
}
tenant_id由系統自動注入,不需手動提供。
5.4 更新記錄
PATCH /api/v1/open/proxy/{table_name}/{row_id}
Request Body:
{
"name": "更新後名稱",
"phone": "0987654321"
}
Response 200 OK:
{ "id": "uuid", "updated": true }
5.5 刪除記錄
DELETE /api/v1/open/proxy/{table_name}/{row_id}
Response 204 No Content
5.6 自動型別轉換
Proxy 會自動將字串轉為對應的 PostgreSQL 型別:
| 輸入格式 | 轉換結果 | 範例 |
|---|---|---|
YYYY-MM-DD(正好 10 字元) | date | "2026-03-24" |
含 T 的 ISO 字串 | datetime | "2026-03-24T12:00:00Z" |
dict / list(JSON 物件/陣列) | jsonb(CAST AS jsonb) | {"key": "value"} |
UUID 格式字串(在 _id 結尾的欄位) | uuid | "a24bc8fe-5942-4937-ad2f-28812caa5425" |
空字串 ""(在 _id 結尾的欄位) | NULL | "" → 寫入 NULL |
⚠️ UUID 欄位注意事項:
- 所有以
_id結尾的欄位(如product_id、order_id)在寫入時會自動嘗試轉為 UUID 型別- 若值為空字串
"",系統會自動轉為NULL(避免 PostgreSQL 型別錯誤)- 若值不是合法的 UUID 格式(如 LINE ID
U1234567890),則保留原始字串
6. Custom Table API(動態資料表)
前綴:
/api/v1/open/data認證:API Key(X-API-KeyHeader) 資料隔離:自動以 Key 所屬的tenant_id做 row-level 過濾 引用白名單:不適用(Custom Table 隸屬於 App 本身,不走引用機制)
6.0 Custom Table 與系統資料表的差異
AI GO 提供兩種資料儲存方式,分別使用不同的 API 端點:
| 特性 | 系統資料表(Open Proxy) | Custom Table(Open Custom Data) |
|---|---|---|
| 端點前綴 | /api/v1/open/proxy/{table} | /api/v1/open/data/ |
| 資料來源 | 系統內建模組(customers, sale_orders 等) | App 自建的動態資料表 |
| Schema 定義 | 固定 PostgreSQL 表結構 | 動態 JSONB(自訂欄位定義) |
| 引用白名單 | ✅ 需要建立引用 + 發布 | ❌ 不需要(App 自有資料) |
| 資料識別方式 | table_name(如 customers) | object_id 或 api_slug |
| 管理方式 | 系統內建,不可增刪表 | 在 AI GO 管理介面自行建立 |
⚠️ 常見錯誤:請勿使用
/open/proxy/端點存取 Custom Table。Custom Table 不是實體 PostgreSQL 表,不存在於引用系統中,使用 Proxy 端點會收到403 App 未被授權存取表錯誤。
6.1 Custom Table 概念說明
Custom Table 是 AI GO 的動態資料庫系統,允許每個 App 自行定義資料表結構:
- CustomObject(資料表定義):邏輯上等同一張「表」,包含名稱和
api_slug(API 識別碼) - CustomField(欄位定義):每個 Object 可定義多個欄位(名稱、型別、是否必填等)
- CustomRecord(資料記錄):實際資料以 JSONB 格式儲存在
data欄位中
erDiagram
CustomObject ||--o{ CustomField : "has fields"
CustomObject ||--o{ CustomRecord : "has records"
CustomObject {
UUID id PK
UUID app_id FK
string name
string api_slug
}
CustomField {
UUID id PK
UUID object_id FK
string name
string field_key
string field_type
boolean is_required
int sequence
}
CustomRecord {
UUID id PK
UUID object_id FK
JSONB data
}
6.2 列出 App 的 Custom Table
GET /api/v1/open/data/objects
Response 200 OK:
[
{
"id": "uuid",
"tenant_id": "uuid",
"app_id": "uuid",
"name": "團體行程",
"api_slug": "group_tour",
"created_at": "2026-03-20T00:00:00Z",
"updated_at": "2026-03-20T00:00:00Z",
"fields": [
{
"id": "uuid",
"object_id": "uuid",
"name": "行程名稱",
"field_key": "tour_name",
"field_type": "text",
"is_required": true,
"sequence": 10
},
{
"id": "uuid",
"object_id": "uuid",
"name": "金額",
"field_key": "amount",
"field_type": "number",
"is_required": false,
"sequence": 20
}
]
}
]
回傳的
fields陣列包含完整的欄位定義,可用於動態生成表單或表格。
6.3 列出 Custom Table 的記錄
GET /api/v1/open/data/objects/{obj_id}/records
路徑參數:
| 參數 | 說明 |
|---|---|
obj_id | Custom Table 的 UUID 或 api_slug(如 group_tour) |
Response 200 OK:
[
{
"id": "uuid",
"tenant_id": "uuid",
"object_id": "uuid",
"data": {
"tour_name": "日本東京五日遊",
"amount": 35000,
"departure_date": "2026-05-01"
},
"created_at": "2026-03-20T00:00:00Z",
"updated_at": "2026-03-20T00:00:00Z"
},
{
"id": "uuid",
"tenant_id": "uuid",
"object_id": "uuid",
"data": {
"tour_name": "韓國首爾三日遊",
"amount": 18000,
"departure_date": "2026-06-15"
},
"created_at": "2026-03-21T00:00:00Z",
"updated_at": "2026-03-21T00:00:00Z"
}
]
data欄位為 JSONB,其結構由 Custom Table 的fields定義決定。
6.4 新增記錄
POST /api/v1/open/data/objects/{obj_id}/records
路徑參數:obj_id 支援 UUID 或 api_slug
Request Body:
{
"data": {
"tour_name": "泰國曼谷四日遊",
"amount": 22000,
"departure_date": "2026-07-20",
"max_people": 30,
"itinerary": ["大皇宮", "水上市場", "芭達雅"]
}
}
data接受任意 JSON 結構,包含物件、陣列、巢狀結構等。field_key對應 Custom Table 的欄位定義。
Response 201 Created:
{
"id": "uuid",
"tenant_id": "uuid",
"object_id": "uuid",
"data": {
"tour_name": "泰國曼谷四日遊",
"amount": 22000,
"departure_date": "2026-07-20",
"max_people": 30,
"itinerary": ["大皇宮", "水上市場", "芭達雅"]
},
"created_at": "2026-03-29T00:00:00Z",
"updated_at": null
}
tenant_id由系統根據 API Key 自動注入,不需手動提供。
6.5 更新記錄
PATCH /api/v1/open/data/records/{record_id}
路徑參數:
| 參數 | 說明 |
|---|---|
record_id | 記錄的 UUID |
Request Body:
{
"data": {
"amount": 25000,
"status": "confirmed"
}
}
更新為合併模式(Merge):僅覆寫傳入的欄位,未傳入的欄位保持不變。例如上例只會更新
amount和新增status,其餘欄位(如tour_name)不受影響。
Response 200 OK:
{
"id": "uuid",
"tenant_id": "uuid",
"object_id": "uuid",
"data": {
"tour_name": "泰國曼谷四日遊",
"amount": 25000,
"departure_date": "2026-07-20",
"max_people": 30,
"itinerary": ["大皇宮", "水上市場", "芭達雅"],
"status": "confirmed"
},
"created_at": "2026-03-29T00:00:00Z",
"updated_at": "2026-03-29T01:00:00Z"
}
6.6 刪除記錄
DELETE /api/v1/open/data/records/{record_id}
Response 200 OK:
{
"message": "已刪除",
"id": "uuid"
}
6.7 欄位型別說明
| 型別 | 說明 | data 中的值範例 |
|---|---|---|
text | 文字 | "日本東京五日遊" |
number | 數值 | 35000、99.5 |
date | 日期(ISO 格式字串) | "2026-05-01" |
relation | 關聯其他記錄的 UUID | "550e8400-e29b-41d4-a716-446655440000" |
由於
data是 JSONB 欄位,實際上可以儲存任意 JSON 結構(陣列、巢狀物件等),field_type主要用於 UI 表單顯示和前端驗證。
6.8 Custom Table 完整使用範例
以下展示第三方旅行社 ERP 系統串接 Custom Table 的完整流程:
# ── 第一步:取得 API Key 後,查看 App 有哪些 Custom Table ──
curl -H "X-API-Key: sk_live_a1b2c3d4e5f6..." \
https://api.ai-go.app/api/v1/open/data/objects
# 回應範例:
# [
# {
# "id": "...", "name": "團體行程", "api_slug": "group_tour",
# "fields": [{"field_key": "tour_name", "field_type": "text"}, ...]
# },
# {
# "id": "...", "name": "訂單紀錄", "api_slug": "booking",
# "fields": [{"field_key": "customer_name", ...}, ...]
# }
# ]
# ── 第二步:用 api_slug 列出「團體行程」的所有記錄 ──
curl -H "X-API-Key: sk_live_a1b2c3d4e5f6..." \
https://api.ai-go.app/api/v1/open/data/objects/group_tour/records
# ── 第三步:新增一筆行程記錄 ──
curl -X POST \
-H "X-API-Key: sk_live_a1b2c3d4e5f6..." \
-H "Content-Type: application/json" \
-d '{
"data": {
"tour_name": "沖繩四日遊",
"amount": 28000,
"departure_date": "2026-08-10",
"max_people": 25
}
}' \
https://api.ai-go.app/api/v1/open/data/objects/group_tour/records
# ── 第四步:更新記錄(Merge 模式,僅更新指定欄位)──
curl -X PATCH \
-H "X-API-Key: sk_live_a1b2c3d4e5f6..." \
-H "Content-Type: application/json" \
-d '{"data": {"amount": 32000, "status": "full"}}' \
https://api.ai-go.app/api/v1/open/data/records/{record_id}
# ── 第五步:刪除記錄 ──
curl -X DELETE \
-H "X-API-Key: sk_live_a1b2c3d4e5f6..." \
https://api.ai-go.app/api/v1/open/data/records/{record_id}
6.9 與 Open Proxy 的端點對照
如果您同時需要存取系統資料表(如 customers)和 Custom Table,請注意使用不同的 API 端點:
# ── 存取系統資料表(如客戶)→ 使用 Open Proxy ──
curl -H "X-API-Key: sk_live_xxx" \
https://api.ai-go.app/api/v1/open/proxy/customers
# ── 存取 Custom Table(如團體行程)→ 使用 Open Custom Data ──
curl -H "X-API-Key: sk_live_xxx" \
https://api.ai-go.app/api/v1/open/data/objects/group_tour/records
| 我要存取的資料 | 正確的端點 | 錯誤的端點(會收到 403) |
|---|---|---|
| 系統內建表(customers, sale_orders 等) | /open/proxy/{table} | /open/data/objects/{table}/records |
| Custom Table(App 自建的動態表) | /open/data/objects/{slug}/records | /open/proxy/{slug}(❌ 403) |
7. External Auth(跳轉登入)
僅適用於 auth_mode = "platform" 的整合。
7.1 產生登入 Code
POST /api/v1/integrations/{app_id}/launch
認證:主站 JWT(需 builder.access 權限)
Response:
{
"redirect_url": "https://my-app.com/auth/callback?code=xxx",
"code": "xxx...",
"expires_in": 60
}
7.2 Code 換 Token
POST /api/v1/ext/auth/exchange
Headers:X-API-Key: sk_live_xxx
Body:{ "code": "xxx..." }
Response:
{
"access_token": "eyJhbGciOiJIUzI1NiI...",
"token_type": "Bearer",
"expires_in": 86400,
"user": { "id": "uuid", "email": "user@example.com", "name": "王小明" }
}
7.3 刷新 Token
POST /api/v1/ext/auth/refresh
Headers:X-API-Key: sk_live_xxx
Body:{ "token": "eyJhbGciOiJI..." }
Response:
{
"access_token": "eyJhbGciOiJI...(新)",
"token_type": "Bearer",
"expires_in": 86400,
"app_id": "uuid"
}
Token 過期後有 5 分鐘寬限期可刷新,超過需重新進行 launch → exchange 流程。
8. 可引用的資料表與 Schema 完整清單
以下列出所有可被引用的資料表(僅適用於 Open Proxy,Custom Table 請參閱 §6)。 每張表皆包含
id(UUID)、created_at(timestamptz)、updated_at(timestamptz)、tenant_id(UUID) 四個系統欄位,以及custom_data(JSONB) 自訂資料欄位(參見 §4.7),以下不重複列出。
8.1 客戶模組
customers — 客戶
| 欄位 | 型別 | Nullable | FK | 說明 |
|---|---|---|---|---|
| name | VARCHAR | ✗ | 客戶名稱 | |
| customer_type | VARCHAR | ✗ | company / individual | |
| birthday | VARCHAR | ✓ | 生日 | |
| id_number | VARCHAR | ✓ | 身分證號/統編 | |
| registered_address | VARCHAR | ✓ | 登記地址 | |
| contact_address | VARCHAR | ✓ | 聯絡地址 | |
| phone | VARCHAR | ✓ | 電話 | |
| VARCHAR | ✓ | 電子郵件 | ||
| line_id | VARCHAR | ✓ | LINE ID | |
| fax | VARCHAR | ✓ | 傳真 | |
| note | TEXT | ✓ | 備註 | |
| id_file_url | VARCHAR | ✓ | 身分證檔案 URL | |
| contact_person | VARCHAR | ✓ | 聯繫窗口 | |
| vat | VARCHAR | ✓ | 稅籍編號 | |
| currency_id | UUID | ✓ | currencies.id | 幣別 |
| payment_term | VARCHAR | ✓ | 付款條件 | |
| credit_limit | FLOAT | ✓ | 信用額度 | |
| is_company | BOOLEAN | ✓ | 法人/自然人 | |
| country_id | UUID | ✓ | countries.id | 國家 |
| state_id | UUID | ✓ | country_states.id | 州省 |
| city | VARCHAR | ✓ | 城市 | |
| zip_code | VARCHAR | ✓ | 郵遞區號 | |
| lang | VARCHAR | ✓ | 語言偏好 | |
| ref | VARCHAR | ✓ | 客戶代碼 | |
| website_url | VARCHAR | ✓ | 網站 | |
| active | BOOLEAN | ✓ | 啟用狀態 | |
| short_name | VARCHAR | ✓ | 簡稱 | |
| status | VARCHAR | ✓ | active / suspended | |
| level_id | UUID | ✓ | customer_levels.id | 客戶等級 |
| salesperson_id | UUID | ✓ | users.id | 負責業務員 |
customer_levels — 客戶等級
| 欄位 | 型別 | Nullable | 說明 |
|---|---|---|---|
| name | VARCHAR | ✗ | 等級名稱 |
| discount_rate | NUMERIC(5,4) | ✓ | 折扣比率(1.0=原價) |
| description | TEXT | ✓ | 說明 |
customer_tags — 客戶標籤
| 欄位 | 型別 | Nullable | 說明 |
|---|---|---|---|
| name | VARCHAR | ✗ | 標籤名稱 |
| color | VARCHAR | ✓ | 顯示顏色 |
customer_tag_rel — 客戶-標籤關聯
| 欄位 | 型別 | FK | 說明 |
|---|---|---|---|
| customer_id | UUID | customers.id | 客戶 |
| tag_id | UUID | customer_tags.id | 標籤 |
customer_tag_prices — 標籤專屬價
| 欄位 | 型別 | FK | 說明 |
|---|---|---|---|
| tag_id | UUID | customer_tags.id | 標籤 |
| product_id | UUID | product_products.id | 商品 |
| special_price | NUMERIC(16,2) | 專屬價格 |
8.2 供應商模組
suppliers — 供應商
| 欄位 | 型別 | Nullable | FK | 說明 |
|---|---|---|---|---|
| name | VARCHAR | ✗ | 名稱 | |
| supplier_type | VARCHAR | ✗ | company / individual | |
| ref | VARCHAR | ✓ | 供應商代碼 | |
| vat | VARCHAR | ✓ | 統編 | |
| contact_person | VARCHAR | ✓ | 聯繫窗口 | |
| phone | VARCHAR | ✓ | 電話 | |
| VARCHAR | ✓ | 電子郵件 | ||
| fax | VARCHAR | ✓ | 傳真 | |
| registered_address | VARCHAR | ✓ | 登記地址 | |
| contact_address | VARCHAR | ✓ | 聯絡地址 | |
| city | VARCHAR | ✓ | 城市 | |
| zip_code | VARCHAR | ✓ | 郵遞區號 | |
| country_id | UUID | ✓ | countries.id | 國家 |
| state_id | UUID | ✓ | country_states.id | 州省 |
| payment_term | VARCHAR | ✓ | 付款條件 | |
| credit_limit | FLOAT | ✓ | 信用額度 | |
| currency_id | UUID | ✓ | currencies.id | 幣別 |
| website_url | VARCHAR | ✓ | 網站 | |
| note | TEXT | ✓ | 備註 | |
| active | BOOLEAN | ✓ | 啟用 | |
| status | VARCHAR | ✓ | active / suspended |
8.3 產品模組
product_categories — 產品分類
| 欄位 | 型別 | Nullable | FK | 說明 |
|---|---|---|---|---|
| name | VARCHAR | ✗ | 名稱 | |
| complete_name | VARCHAR | ✓ | 完整路徑名 | |
| parent_id | UUID | ✓ | product_categories.id | 父分類 |
| code | VARCHAR | ✓ | 類別編號 | |
| property_valuation | VARCHAR | ✓ | periodic / real_time | |
| property_cost_method | VARCHAR | ✓ | standard / fifo / average | |
| property_account_income_id | UUID | ✓ | account_accounts.id | 收入科目 |
| property_account_expense_id | UUID | ✓ | account_accounts.id | 費用科目 |
| default_warehouse_id | UUID | ✓ | stock_warehouses.id | 預設倉庫 |
product_templates — 產品範本
| 欄位 | 型別 | Nullable | FK | 說明 |
|---|---|---|---|---|
| name | VARCHAR | ✗ | 名稱 | |
| type | VARCHAR | ✓ | consu / service / combo | |
| categ_id | UUID | ✓ | product_categories.id | 分類 |
| list_price | NUMERIC(16,2) | ✓ | 銷售價 | |
| standard_price | NUMERIC(16,2) | ✓ | 成本價 | |
| description | TEXT | ✓ | 描述 | |
| default_code | VARCHAR | ✓ | SKU | |
| barcode | VARCHAR | ✓ | 條碼 | |
| active | BOOLEAN | ✓ | 啟用 | |
| sale_ok | BOOLEAN | ✓ | 可銷售 | |
| purchase_ok | BOOLEAN | ✓ | 可採購 | |
| uom_id | UUID | ✓ | uom_uom.id | 銷售單位 |
| uom_po_id | UUID | ✓ | uom_uom.id | 採購單位 |
| invoice_policy | VARCHAR | ✓ | order / delivery |
product_products — 產品變體
| 欄位 | 型別 | FK | 說明 |
|---|---|---|---|
| product_tmpl_id | UUID | product_templates.id | 範本 |
| default_code | VARCHAR | SKU | |
| barcode | VARCHAR | 條碼 | |
| active | BOOLEAN | 啟用 | |
| lst_price_extra | NUMERIC(16,2) | 額外售價 | |
| standard_price | NUMERIC(16,2) | 成本價 |
product_price_tiers — 階梯定價
| 欄位 | 型別 | FK | 說明 |
|---|---|---|---|
| product_tmpl_id | UUID | product_templates.id | 產品範本 |
| price_type | VARCHAR | fixed / market | |
| min_qty | NUMERIC(16,4) | 數量下限 | |
| max_qty | NUMERIC(16,4) | 數量上限 | |
| price | NUMERIC(16,2) | 單價 | |
| guide_price | NUMERIC(16,2) | 指導價格 |
product_supplierinfo — 供應商價格
| 欄位 | 型別 | FK | 說明 |
|---|---|---|---|
| supplier_id | UUID | suppliers.id | 供應商 |
| product_tmpl_id | UUID | product_templates.id | 產品範本 |
| product_id | UUID | product_products.id | 產品變體 |
| product_name | VARCHAR | 供應商品名 | |
| product_code | VARCHAR | 供應商品號 | |
| min_qty | NUMERIC(16,4) | 最低訂購量 | |
| price | NUMERIC(16,2) | 價格 | |
| currency_id | UUID | currencies.id | 幣別 |
| date_start | DATE | 生效日 | |
| date_end | DATE | 失效日 | |
| delay | INTEGER | 前置時間(天) |
8.4 銷售模組
sale_orders — 銷售訂單
📌 自動觸發流程 (Triggers)
- 新增或更新此表(以及
sale_order_lines)時,系統會自動比對出貨量與開票量,並重新計算更新本訂單的invoice_status(no,to_invoice,invoiced)。
| 欄位 | 型別 | Nullable | FK | 說明 |
|---|---|---|---|---|
| name | VARCHAR | ✓ | 單號 | |
| state | VARCHAR | ✓ | draft/sent/sale/done/cancel | |
| date_order | DATE | ✗ | 下單日 | |
| validity_date | DATE | ✓ | 有效期 | |
| note | TEXT | ✓ | 備註 | |
| amount_untaxed | NUMERIC(16,2) | ✓ | 未稅金額 | |
| amount_tax | NUMERIC(16,2) | ✓ | 稅額 | |
| amount_total | NUMERIC(16,2) | ✓ | 總金額 | |
| margin | NUMERIC(16,2) | ✓ | 毛利 | |
| invoice_status | VARCHAR | ✓ | no/to_invoice/invoiced | |
| customer_id | UUID | ✓ | customers.id | 客戶 |
| currency_id | UUID | ✓ | currencies.id | 幣別 |
| user_id | UUID | ✓ | users.id | 業務員 |
| department_id | UUID | ✓ | hr_departments.id | 部門 |
sale_order_lines — 銷售訂單明細
| 欄位 | 型別 | FK | 說明 |
|---|---|---|---|
| order_id | UUID | sale_orders.id | 訂單 |
| name | TEXT | 描述 | |
| product_id | UUID | product_products.id | 產品 |
| product_uom_qty | NUMERIC(16,4) | 數量 | |
| qty_delivered | NUMERIC(16,4) | 已交貨量 | |
| qty_invoiced | NUMERIC(16,4) | 已開票量 | |
| price_unit | NUMERIC(16,2) | 單價 | |
| discount | NUMERIC(5,2) | 折扣 % | |
| price_subtotal | NUMERIC(16,2) | 小計 | |
| price_total | NUMERIC(16,2) | 含稅總計 | |
| tax_id | UUID | account_taxes.id | 稅率 |
| delivery_date | DATE | 預交貨日 |
8.5 採購模組
purchase_orders — 採購訂單
📌 自動觸發流程 (Triggers)
- 新增或更新此表(以及
purchase_order_lines)時,系統會自動重新計算更新本訂單的開票狀態。
| 欄位 | 型別 | FK | 說明 |
|---|---|---|---|
| name | VARCHAR | 單號 | |
| state | VARCHAR | draft/sent/purchase/done/cancel | |
| date_order | DATE | 下單日 | |
| date_planned | DATE | 預計交貨日 | |
| amount_untaxed | NUMERIC(16,2) | 未稅金額 | |
| amount_tax | NUMERIC(16,2) | 稅額 | |
| amount_total | NUMERIC(16,2) | 總金額 | |
| supplier_id | UUID | suppliers.id | 供應商 |
| currency_id | UUID | currencies.id | 幣別 |
| user_id | UUID | users.id | 負責人 |
| notes | TEXT | 備註 | |
| origin | VARCHAR | 來源文件 |
purchase_order_lines — 採購訂單明細
| 欄位 | 型別 | FK | 說明 |
|---|---|---|---|
| order_id | UUID | purchase_orders.id | 訂單 |
| product_id | UUID | product_products.id | 產品 |
| product_qty | NUMERIC(16,4) | 數量 | |
| qty_received | NUMERIC(16,4) | 已收貨量 | |
| price_unit | NUMERIC(16,2) | 單價 | |
| price_subtotal | NUMERIC(16,2) | 小計 | |
| price_total | NUMERIC(16,2) | 總計 | |
| tax_id | UUID | account_taxes.id | 稅率 |
8.6 會計模組
⚠️ 核心會計邏輯與專屬 API 提醒 請注意:若您直接使用
Open Proxy API對account_moves與account_move_lines進行INSERT,系統不會觸發會計防呆與自動化處理(例如:自動取號、防呆自動平衡分錄等),這可能導致借貸不平的髒資料產生。若您正在開發獨立的會計/發票整合系統,強烈建議您全面改用 AI GO 專屬的會計業務 API:
POST /api/v1/accounting/vouchers(建立傳票:自動設定 entry 與 mapping)POST /api/v1/accounting/vouchers/{id}/post(過帳傳票:自動依據結算差額插入「自動平衡分錄」並生成 Voucher Number)在專屬 API 中,只要偵測到
Debit ≠ Credit,系統會自動幫您墊入一筆「自動平衡分錄」將總金額強制打平,確保會計約束不崩潰!詳細 Endpoint 規格請見系統的/docsSwagger 頁面。
account_moves — 會計傳票/發票
📌 自動觸發流程 (Triggers)
- 更新此發票或其明細,以及關聯付款對帳時(
account_payments),系統會自動重新計算這張發票的付款狀態payment_state(如paid,partial,not_paid)。
| 欄位 | 型別 | FK | 說明 |
|---|---|---|---|
| name | VARCHAR | 單號 | |
| move_type | VARCHAR | entry/out_invoice/in_invoice/out_refund/in_refund/out_receipt/in_receipt | |
| state | VARCHAR | draft/posted/cancel | |
| date | DATE | 記帳日期 | |
| invoice_date | DATE | 發票日期 | |
| invoice_date_due | DATE | 到期日 | |
| customer_id | UUID | customers.id | 客戶 |
| supplier_id | UUID | suppliers.id | 供應商 |
| currency_id | UUID | currencies.id | 幣別 |
| journal_id | UUID | account_journals.id | 日記帳 |
| amount_untaxed | NUMERIC(16,2) | 未稅金額 | |
| amount_tax | NUMERIC(16,2) | 稅額 | |
| amount_total | NUMERIC(16,2) | 總金額 | |
| amount_residual | NUMERIC(16,2) | 未付餘額 | |
| payment_state | VARCHAR | not_paid/partial/paid/reversed/invoicing_legacy/in_payment | |
| voucher_number | VARCHAR | 傳票號碼 |
account_move_lines — 傳票明細行
| 欄位 | 型別 | FK | 說明 |
|---|---|---|---|
| move_id | UUID | account_moves.id | 傳票 |
| name | VARCHAR | 摘要 | |
| quantity | NUMERIC(16,4) | 數量 | |
| price_unit | NUMERIC(16,2) | 單價 | |
| debit | NUMERIC(16,2) | 借方 | |
| credit | NUMERIC(16,2) | 貸方 | |
| balance | NUMERIC(16,2) | 餘額 | |
| account_id | UUID | account_accounts.id | 會計科目 |
| tax_rate | NUMERIC(5,2) | 稅率 % | |
| tax_amount | NUMERIC(16,2) | 稅額 |
會計模組還包含
account_accounts、account_journals、account_taxes、account_payment_terms、account_fiscal_positions、account_payments、account_bank_statements、account_move_templates等表,結構請透過GET /refs/tables/{table_name}/columnsAPI 即時查詢。
8.7 庫存模組
stock_warehouses — 倉庫
| 欄位 | 型別 | 說明 |
|---|---|---|
| name | VARCHAR | 倉庫名稱 |
| code | VARCHAR(5) | 簡碼 |
| active | BOOLEAN | 啟用 |
| reception_steps | VARCHAR | one_step/two_steps/three_steps |
| delivery_steps | VARCHAR | ship_only/pick_ship/pick_pack_ship |
stock_locations — 庫位
| 欄位 | 型別 | FK | 說明 |
|---|---|---|---|
| name | VARCHAR | 名稱 | |
| usage | VARCHAR | supplier/view/internal/customer/inventory/transit/production | |
| active | BOOLEAN | 啟用 | |
| barcode | VARCHAR | 條碼 | |
| location_id | UUID | stock_locations.id | 父庫位 |
stock_pickings — 揀貨單/調撥單
| 欄位 | 型別 | FK | 說明 |
|---|---|---|---|
| name | VARCHAR | 單號 | |
| state | VARCHAR | draft/waiting/confirmed/assigned/done/cancel | |
| origin | VARCHAR | 來源文件 | |
| picking_type_id | UUID | stock_picking_types.id | 揀貨類型 |
| location_id | UUID | stock_locations.id | 來源庫位 |
| location_dest_id | UUID | stock_locations.id | 目的庫位 |
| customer_id | UUID | customers.id | 客戶 |
| supplier_id | UUID | suppliers.id | 供應商 |
| sale_id | UUID | sale_orders.id | 銷售訂單 |
| purchase_id | UUID | purchase_orders.id | 採購訂單 |
stock_moves — 庫存移動
📌 自動觸發流程 (Triggers)
- 更新此表的狀態時,系統會自動重新計算關聯揀貨單 (
stock_pickings) 的部分出入庫完成狀態。
| 欄位 | 型別 | FK | 說明 |
|---|---|---|---|
| name | TEXT | 描述 | |
| state | VARCHAR | draft/waiting/confirmed/partially_available/assigned/done/cancel | |
| product_id | UUID | product_products.id | 產品 |
| product_uom_qty | NUMERIC(16,4) | 需求量 | |
| quantity | NUMERIC(16,4) | 完成量 | |
| location_id | UUID | stock_locations.id | 來源 |
| location_dest_id | UUID | stock_locations.id | 目的 |
| picking_id | UUID | stock_pickings.id | 揀貨單 |
stock_quants — 庫存量
| 欄位 | 型別 | FK | 說明 |
|---|---|---|---|
| product_id | UUID | product_products.id | 產品 |
| location_id | UUID | stock_locations.id | 庫位 |
| lot_id | UUID | stock_lots.id | 批號 |
| quantity | NUMERIC(16,4) | 在手量 | |
| reserved_quantity | NUMERIC(16,4) | 保留量 |
📌 關於庫存量維護 (Triggers):新增或更新
stock_move_lines(庫存移動明細) 時,系統會自動計算並更新對應庫位商品的保留數量 (stock_quants.reserved_quantity)。
庫存模組還包含
stock_lots、stock_picking_types、stock_move_lines、stock_routes、stock_rules、stock_packages、stock_scraps、stock_warehouse_orderpoints、stock_landed_costs、stock_picking_batches、delivery_carriers、inventory_check_batches、inventory_check_items、inventory_converts、freight_groups、freight_group_tiers等表。
8.8 CRM 模組
crm_leads — 商機
| 欄位 | 型別 | FK | 說明 |
|---|---|---|---|
| name | VARCHAR | 名稱 | |
| type | VARCHAR | lead / opportunity | |
| active | BOOLEAN | 啟用 | |
| priority | VARCHAR | 0/1/2/3(星級) | |
| stage_id | UUID | crm_stages.id | 階段 |
| probability | FLOAT | 機率 % | |
| expected_revenue | NUMERIC(16,2) | 預期營收 | |
| customer_id | UUID | customers.id | 客戶 |
| contact_name | VARCHAR | 聯絡人 | |
| email_from | VARCHAR | ||
| phone | VARCHAR | 電話 | |
| user_id | UUID | users.id | 負責人 |
| team_id | UUID | crm_teams.id | 銷售團隊 |
| date_deadline | DATE | 預計結案日 | |
| description | TEXT | 描述 |
還包含
crm_stages、crm_teams、crm_team_members、crm_lost_reasons、crm_tags、crm_recurring_plans、crm_activities等表。
8.9 HR 人力資源模組
hr_employees — 員工
📌 自動觸發流程 (Triggers)
- 出勤 (
hr_attendances):新增或更新出勤紀錄時,會自動更新對應員工目前的出勤狀態。- 請假 (
hr_leaves):請假單狀態更新為validate(核准)時,會自動扣除該員工可用休假額度(hr_leave_allocations)。- 工時 (
hr_timesheets):填寫工時表會自動累加project_tasks.effective_hours(任務實際工時),並更新專案任務進度百分比。
| 欄位 | 型別 | FK | 說明 |
|---|---|---|---|
| name | VARCHAR | 姓名 | |
| active | BOOLEAN | 啟用 | |
| employee_type | VARCHAR | employee/student/trainee/contractor/freelance | |
| job_title | VARCHAR | 職稱 | |
| work_phone | VARCHAR | 公司電話 | |
| work_email | VARCHAR | 公司信箱 | |
| mobile_phone | VARCHAR | 手機 | |
| gender | VARCHAR | male/female/other | |
| birthday | DATE | 生日 | |
| department_id | UUID | hr_departments.id | 部門 |
| job_id | UUID | hr_jobs.id | 職位 |
| parent_id | UUID | hr_employees.id | 直屬主管 |
| user_id | UUID | users.id | 關聯使用者 |
| member_id | UUID | members.id | 系統帳號 |
還包含
hr_departments、hr_jobs、hr_work_locations、hr_attendances、hr_leave_types、hr_leaves、hr_leave_allocations、hr_expense_sheets、hr_expenses、hr_skill_types、hr_skills、hr_timesheets、hr_work_entry_types、hr_work_entries等表。
8.10 MRP 製造模組
mrp_productions — 生產訂單
📌 自動觸發流程 (Triggers)
- 更新關聯工單 (
mrp_workorders) 的狀態時,系統會自動結算並刷新本生產訂單的完成進度。
| 欄位 | 型別 | FK | 說明 |
|---|---|---|---|
| name | VARCHAR | 單號 | |
| product_id | UUID | product_products.id | 產品 |
| product_qty | FLOAT | 計畫數量 | |
| qty_produced | FLOAT | 已完成數量 | |
| state | VARCHAR | draft/confirmed/progress/to_close/done/cancel | |
| bom_id | UUID | mrp_boms.id | 物料清單 |
| date_start | TIMESTAMPTZ | 開始日期 | |
| date_finished | TIMESTAMPTZ | 完成日期 | |
| user_id | UUID | users.id | 負責人 |
| is_subcontract | BOOLEAN | 委外 |
還包含
mrp_workcenters、mrp_boms、mrp_bom_lines、mrp_bom_byproducts、mrp_routing_workcenters、mrp_workorders、mrp_unbuilds等表。
8.11 專案管理模組
project_projects — 專案
📌 自動觸發流程 (Triggers)
- 建立或刪除關聯任務 (
project_tasks) 時,系統會自動維護並更新此專案主檔的總任務數 (task_count)。
| 欄位 | 型別 | FK | 說明 |
|---|---|---|---|
| name | VARCHAR | 專案名稱 | |
| active | BOOLEAN | 啟用 | |
| description | TEXT | 描述 | |
| date_start | DATE | 開始日 | |
| date | DATE | 截止日 | |
| stage_id | UUID | project_project_stages.id | 階段 |
| customer_id | UUID | customers.id | 客戶 |
| user_id | UUID | users.id | PM |
| task_count | INTEGER | 任務數 |
project_tasks — 任務
| 欄位 | 型別 | FK | 說明 |
|---|---|---|---|
| name | VARCHAR | 名稱 | |
| state | VARCHAR | 01_in_progress/1_done/1_canceled/04_waiting_normal/03_approved/02_changes_requested | |
| priority | VARCHAR | 0(一般)/1(緊急) | |
| description | TEXT | 描述 | |
| date_deadline | DATE | 截止日 | |
| project_id | UUID | project_projects.id | 專案 |
| stage_id | UUID | project_task_types.id | 看板階段 |
| parent_id | UUID | project_tasks.id | 父任務 |
| planned_hours | FLOAT | 計畫工時 | |
| effective_hours | FLOAT | 實際工時 | |
| progress | FLOAT | 進度 % |
還包含
project_project_stages、project_task_types、project_milestones、project_tags、project_roles、project_collaborators、project_task_recurrences、project_updates等表。
8.12 核心參考表
countries — 國家
| 欄位 | 型別 | 說明 |
|---|---|---|
| name | VARCHAR | 名稱 |
| code | VARCHAR(2) | ISO 3166-1 alpha-2 |
| phone_code | INTEGER | 國際電話區碼 |
| currency_id | UUID | 預設幣別 |
currencies — 幣別
| 欄位 | 型別 | 說明 |
|---|---|---|
| name | VARCHAR(3) | ISO 4217(TWD、USD) |
| full_name | VARCHAR | 完整名稱 |
| symbol | VARCHAR(10) | 符號(NT$、$) |
| decimal_places | INTEGER | 小數位數 |
uom_uom — 計量單位
| 欄位 | 型別 | FK | 說明 |
|---|---|---|---|
| name | VARCHAR | 名稱 | |
| category_id | UUID | uom_categories.id | 類別 |
| uom_type | VARCHAR | reference/bigger/smaller | |
| factor | FLOAT | 轉換因子 |
還包含
country_states、currency_rates、languages、uom_categories、ir_sequences等表。
8.13 其他模組
| 表名 | 說明 |
|---|---|
analytic_accounts | 分析帳戶 |
analytic_lines | 分析行 |
utm_sources | UTM 來源 |
utm_mediums | UTM 媒介 |
utm_campaigns | UTM 活動 |
announcements | 公告 |
file_nodes | 檔案節點 |
purchase_stock_links | 採購-庫存連結 |
sale_stock_links | 銷售-庫存連結 |
sale_purchase_links | 銷售-採購連結 |
所有表的完整欄位可透過
GET /api/v1/refs/tables/{table_name}/columns即時查詢。
9. 錯誤碼與限制
9.1 HTTP 狀態碼
| 狀態碼 | 說明 |
|---|---|
200 | 成功 |
201 | 建立成功 |
204 | 刪除成功(無回傳內容) |
400 | 請求格式錯誤(如無效的權限值、不合法的篩選欄位) |
401 | 未認證(API Key 無效或缺失) |
403 | 無權限(表不可引用、未授權的操作、未發布的引用) |
404 | 資源不存在 |
409 | 衝突(如子域名已被使用、已有 pending 發布申請) |
422 | 請求驗證失敗 |
429 | 超過速率限制 |
500 | 伺服器內部錯誤 |
9.2 常見錯誤訊息
| 訊息 | 原因 | 可能的解決方案 |
|---|---|---|
"App 未被授權存取表 '{table}'" | 尚未建立該表的引用 | 若為系統表,請建立引用;若為 Custom Table,請改用 /open/data/ 端點 |
"表 '{table}' 的引用尚未發布" | 引用已建立但未發布(Open Proxy 需發布版本) | 在整合管理中發布引用設定 |
"App 未被授權對表 '{table}' 執行 '{op}' 操作" | 引用的 permissions 不含該操作 | 更新引用加入所需權限 |
"未授權的篩選欄位: {col}" | 查詢使用了未在 columns 中授權的欄位 | 在引用中加入該欄位 |
"此表不可引用" | 該表在黑名單中 | 系統核心表無法存取 |
"API Key 無效或已撤銷" | Key 不存在或已被停用 | 重新建立 API Key |
"資料表不存在" | Custom Table 的 object_id 或 api_slug 不正確 | 先呼叫 GET /open/data/objects 確認可用的 Custom Table |
"記錄不存在" | Custom Table 的 record_id 不正確或已被刪除 | 確認 record_id 正確且屬於該 App |
9.3 速率限制
系統對所有 API 請求實施 Per-App 速率限制。超過限制時回傳 429 Too Many Requests。
9.4 安全注意事項
- 所有資料查詢自動以
tenant_id做 row-level 隔離,無法跨租戶存取 tenant_id由 API Key 自動決定,無法偽造- 寫入操作時,系統欄位(
id、created_at、updated_at、tenant_id)會被自動排除 - 欄位名稱經正則驗證(
^[a-zA-Z_][a-zA-Z0-9_]*$),防止 SQL 注入 - 僅允許白名單運算子,不接受任意 SQL
10. Proxy 查詢完整安全機制與功能限制
10.1 安全驗證流程
每次 Proxy 呼叫都會依序執行以下驗證:
① AppDataReference 白名單驗證
→ 檢查 App 是否有對目標表的引用(Open Proxy 需已發布快照)
② CRUD 權限檢查
→ 引用的 permissions 必須包含所需操作(read / create / update / delete)
③ 黑名單表檢查
→ 14 張系統核心表永遠不可存取
④ 欄位白名單驗證
→ filter / select / insert / update 的欄位必須在授權的 columns 清單中
⑤ 欄位名稱正則驗證
→ 只允許 ^[a-zA-Z_][a-zA-Z0-9_]*$,防止 SQL 注入
⑥ 運算子白名單驗證
→ 只接受 11 種已定義運算子(eq, ne, gt, gte, lt, lte, like, ilike, in, is_null, is_not_null)
⑦ Tenant 隔離注入
→ 所有查詢自動加上 WHERE tenant_id = :tid(不可跨租戶)
⑧ 系統欄位保護
→ INSERT / UPDATE 時自動排除 id, created_at, updated_at, tenant_id
10.2 Open Proxy 存取方式對照
| 呼叫方式 | 簡單查詢 | 進階查詢(含 filter) | 說明 |
|---|---|---|---|
GET /open/proxy/{table} | ✅ | ❌ | 僅 limit / offset |
POST /open/proxy/{table}/query | ✅ | ✅ | 完整 filter / search / order_by / select / count_only |
10.3 已知查詢功能限制
| 限制項目 | 說明 | 替代方案 |
|---|---|---|
| 不支援 OR 條件 | filters 之間只能 AND | 使用 search 做多欄位 OR 搜尋,或拆分為多次查詢 |
| 不支援巢狀條件 | 無法表達 (A AND B) OR C | 拆分為多次查詢後在應用層合併 |
| 不支援 JOIN | 只能查單一表 | 分別查詢兩張表後在應用層關聯 |
| 不支援聚合函式 | 無 SUM / AVG / GROUP BY | 查出原始資料後在應用層計算 |
| 不支援 BETWEEN | 無 between 運算子 | 組合 gte + lte 兩個 filter |
| 不支援 NOT IN | 只有 in,無 not_in | 查出全部後在應用層篩選 |
| 不支援 NOT LIKE | 只有 like / ilike | 查出全部後在應用層篩選 |
| 單次查詢上限 | limit 最大 500(GET)或 1000(Open Proxy GET) | 使用 offset 分頁迭代 |
| 無 cursor 分頁 | 只有 limit + offset | 大量資料建議配合 order_by + offset 遞增 |
| 無跨租戶查詢 | tenant_id 由系統強制注入 | 此為安全設計,無替代方案 |
10.4 Filter 欄位驗證規則彙整
| 驗證項目 | 檢查內容 | 失敗回傳 |
|---|---|---|
| 欄位名稱格式 | 必須符合 ^[a-zA-Z_][a-zA-Z0-9_]*$ | 400 不合法的欄位名稱 |
| 欄位授權 | 必須在 allowed_columns 清單中(id 始終允許) | 400 未授權的篩選欄位 |
| 運算子合法性 | 必須為 11 種白名單運算子之一 | 400 不支援的運算子 |
in 運算子型別 | value 必須為 array | 400 'in' 運算子的 value 必須是陣列 |
select_columns 授權 | 所選欄位必須在 allowed_columns 中 | 400 未授權的欄位 |
| Order By 欄位 | 不在白名單中的欄位會被靜默忽略 | 回退為預設排序 created_at DESC |
提示:所有表的最新欄位結構可透過
GET /api/v1/refs/tables/{table_name}/columns動態取得,包含型別、是否 Nullable、外鍵指向等資訊。建議在開發時搭配此 API 使用。
11. Enum 值速查附錄
所有 VARCHAR 型別但僅接受固定值的欄位完整清單。
- [DB]:有 PostgreSQL
CHECK CONSTRAINT,寫入非法值會直接報錯400/500- [建議]:無資料庫約束,為系統建議值;前後端介面以此為準,API 不會拒絕其他值但可能導致顯示異常
11.1 客戶模組
| 表 | 欄位 | 約束 | 可接受值 | 說明 |
|---|---|---|---|---|
customers | customer_type | [DB] | company, individual | 法人 / 自然人 |
customers | status | [DB] | active, suspended | 啟用 / 停權 |
11.2 供應商模組
| 表 | 欄位 | 約束 | 可接受值 | 說明 |
|---|---|---|---|---|
suppliers | supplier_type | [DB] | company, individual | 法人 / 自然人 |
suppliers | status | [DB] | active, suspended | 啟用 / 停權 |
11.3 產品模組
| 表 | 欄位 | 約束 | 可接受值 | 說明 |
|---|---|---|---|---|
product_categories | property_valuation | [建議] | periodic, real_time | 定期盤點 / 即時(永續盤存) |
product_categories | property_cost_method | [建議] | standard, fifo, average | 標準成本 / 先進先出 / 加權平均 |
product_templates | type | [DB] | consu, service, combo | 消耗品 / 服務 / 組合商品 |
product_templates | invoice_policy | [DB] | order, delivery | 依訂單開票 / 依出貨開票 |
product_templates | service_type | [DB] | manual, timesheet | 手動 / 依工時 |
product_templates | expense_policy | [DB] | no, cost, sales_price | 不可報銷 / 依成本 / 依售價 |
product_price_tiers | price_type | [DB] | fixed, market | 定價模式 / 時價模式 |
11.4 銷售模組
| 表 | 欄位 | 約束 | 可接受值 | 說明 |
|---|---|---|---|---|
sale_orders | state | [DB] | draft, sent, sale, done, cancel | 草稿 → 已報價 → 銷售訂單 → 完成 → 取消 |
sale_orders | invoice_status | [DB] | no, to_invoice, invoiced | 無須開票 / 待開票 / 已開票 |
sale_orders | tax_type | [建議] | tax_included, tax_excluded, tax_exempt, zero_rate | 含稅 / 未稅 / 免稅 / 零稅率 |
sale_orders | invoice_format | [建議] | duplicate, triplicate, none | 二聯式 / 三聯式 / 不開 |
sale_orders | carrier_type | [建議] | barcode, citizen_digital, mobile, none | 條碼載具 / 自然人憑證 / 手機條碼 / 無 |
sale_orders | delivery_method | [建議] | pickup, delivery, mail, freight | 自取 / 宅配 / 郵寄 / 貨運 |
sale_order_lines | invoice_status | [DB] | no, to_invoice, invoiced | 無須開票 / 待開票 / 已開票 |
sale_order_lines | display_type | [DB] | line_section, line_note | 區段標題 / 備註行 |
sale_order_template_lines | display_type | [建議] | line_section, line_note | 區段標題 / 備註行 |
11.5 採購模組
| 表 | 欄位 | 約束 | 可接受值 | 說明 |
|---|---|---|---|---|
purchase_orders | state | [DB] | draft, sent, purchase, done, cancel | 草稿 → 已報價 → 採購訂單 → 完成 → 取消 |
purchase_orders | invoice_status | [DB] | no, to_invoice, invoiced | 無須開票 / 待開票 / 已開票 |
purchase_orders | tax_type | [建議] | tax_included, tax_excluded, tax_exempt, zero_rate | 含稅 / 未稅 / 免稅 / 零稅率 |
purchase_requisitions | state | [DB] | draft, ongoing, in_progress, open, done, cancel | 草稿 → 進行中 → 處理中 → 開放 → 完成 → 取消 |
purchase_requisitions | requisition_type | [DB] | purchase, blanket_order | 採購協議 / 框架協議 |
11.6 會計模組
| 表 | 欄位 | 約束 | 可接受值 | 說明 |
|---|---|---|---|---|
account_moves | move_type | [DB] | entry, out_invoice, out_refund, in_invoice, in_refund, out_receipt, in_receipt | 日記帳分錄 / 銷項發票 / 銷項折讓 / 進項發票 / 進項折讓 / 收據 / 付款收據 |
account_moves | state | [DB] | draft, posted, cancel | 草稿 / 已過帳 / 已取消 |
account_moves | payment_state | [DB] | not_paid, partial, paid, reversed, invoicing_legacy, in_payment | 未付 / 部分付款 / 已付 / 已沖回 / 舊版格式 / 付款中 |
account_moves | journal_type | [建議] | sale, purchase, cash, bank, general | 銷售 / 採購 / 現金 / 銀行 / 一般 |
account_moves | voucher_type | [建議] | general, cash, transfer, bank | 一般傳票 / 現金傳票 / 轉帳傳票 / 銀行傳票 |
account_moves | settlement_status | [建議] | receivable, payable, provisional_receipt, provisional_payment, settled | 應收 / 應付 / 暫收 / 暫付 / 已結清 |
account_fiscal_years | state | [DB] | open, closed | 開放 / 關閉 |
account_periods | state | [DB] | open, closed | 開放 / 關閉 |
account_lock_dates | lock_date_field | [DB] | fiscalyear_lock_date, tax_lock_date, sale_lock_date, purchase_lock_date | 全域鎖帳 / 稅務鎖帳 / 銷售鎖帳 / 採購鎖帳 |
account_lock_dates | state | [DB] | active, revoked, expired | 生效中 / 已撤銷 / 已過期 |
account_reports | report_type | [DB] | general_ledger, balance_sheet, profit_loss, cash_flow, aged_receivable, aged_payable, tax_report, partner_ledger, trial_balance | 總帳 / 資產負債表 / 損益表 / 現金流量 / 應收帳齡 / 應付帳齡 / 稅務報表 / 夥伴帳 / 試算表 |
account_report_lines | expression_engine | [DB] | domain, account_codes, aggregation, tax_tags, custom | Domain 篩選 / 科目代碼 / 聚合 / 稅額標籤 / 自訂 |
account_payments | payment_type | [建議] | inbound, outbound | 收款 / 付款 |
account_payments | partner_type | [建議] | customer, supplier | 客戶 / 供應商 |
11.7 庫存模組
| 表 | 欄位 | 約束 | 可接受值 | 說明 |
|---|---|---|---|---|
stock_warehouses | reception_steps | [DB] | one_step, two_steps, three_steps | 一步收貨 / 兩步收貨 / 三步收貨 |
stock_warehouses | delivery_steps | [DB] | ship_only, pick_ship, pick_pack_ship | 直接出貨 / 揀貨+出貨 / 揀貨+包裝+出貨 |
stock_locations | usage | [DB] | supplier, view, internal, customer, inventory, production, transit | 供應商 / 檢視(虛擬群組) / 內部 / 客戶 / 盤點 / 生產 / 中轉 |
stock_picking_types | code | [DB] | incoming, outgoing, internal, mrp_operation | 進貨 / 出貨 / 內部調撥 / 製造作業 |
stock_pickings | state | [DB] | draft, waiting, confirmed, assigned, done, cancel | 草稿 / 等待 / 已確認 / 已指派 / 完成 / 取消 |
stock_pickings | priority | [DB] | 0, 1 | 一般 / 緊急 |
stock_moves | state | [DB] | draft, waiting, confirmed, partially_available, assigned, done, cancel | 草稿 / 等待 / 已確認 / 部分可用 / 已指派 / 完成 / 取消 |
stock_moves | procure_method | [DB] | make_to_stock, make_to_order | 庫存供應 / 訂單觸發 |
stock_move_lines | state | [建議] | draft, assigned, done, cancel | 草稿 / 已指派 / 完成 / 取消 |
stock_rules | action | [DB] | pull, push, pull_push, buy, manufacture | 拉式 / 推式 / 推拉混合 / 採購 / 製造 |
stock_rules | procure_method | [DB] | make_to_stock, make_to_order | 庫存供應 / 訂單觸發 |
stock_scraps | state | [DB] | draft, done | 草稿 / 完成 |
stock_scraps | scrap_reason | [建議] | damaged, expired, quality, other | 損壞 / 過期 / 品質不良 / 其他 |
stock_storage_categories | allow_new_product | [DB] | empty, same, mixed | 僅空位 / 僅同品 / 混放 |
stock_landed_costs | state | [DB] | draft, done, cancel | 草稿 / 完成 / 取消 |
stock_landed_cost_lines | split_method | [DB] | equal, by_quantity, by_current_cost_price, by_weight, by_volume | 均分 / 依數量 / 依成本 / 依重量 / 依體積 |
stock_picking_batches | state | [DB] | draft, in_progress, done, cancel | 草稿 / 進行中 / 完成 / 取消 |
delivery_carriers | delivery_type | [DB] | fixed, base_on_rule | 固定運費 / 依規則計算 |
inventory_check_batches | state | [DB] | draft, done | 草稿 / 完成 |
inventory_converts | state | [DB] | draft, done | 草稿 / 完成 |
freight_groups | mode | [DB] | fixed, tiered, free | 固定運費 / 級距運費 / 免運 |
11.8 CRM 模組
| 表 | 欄位 | 約束 | 可接受值 | 說明 |
|---|---|---|---|---|
crm_leads | type | [DB] | lead, opportunity | 潛在客戶 / 商機 |
crm_leads | priority | [DB] | 0, 1, 2, 3 | 無星 / 一星 / 二星 / 三星 |
crm_activities | activity_type | [DB] | email, call, meeting, todo | 郵件 / 通話 / 會議 / 待辦 |
crm_activities | state | [DB] | planned, done, overdue, cancelled | 已排程 / 已完成 / 已逾期 / 已取消 |
11.9 HR 人力資源模組
| 表 | 欄位 | 約束 | 可接受值 | 說明 |
|---|---|---|---|---|
hr_employees | employee_type | [建議] | employee, student, trainee, contractor, freelance | 正職 / 學生 / 實習 / 約聘 / 自由工作者 |
hr_employees | gender | [建議] | male, female, other | 男 / 女 / 其他 |
hr_employees | marital | [建議] | single, married, cohabitant, widower, divorced | 單身 / 已婚 / 同居 / 喪偶 / 離婚 |
hr_employees | hr_presence_state | [建議] | present, absent, to_define | 在線 / 離線 / 待定義 |
hr_work_locations | location_type | [DB] | home, office, other | 居家 / 辦公室 / 其他 |
hr_leave_types | requires_allocation | [建議] | yes, no | 需配額 / 不需配額 |
hr_leave_types | leave_validation_type | [建議] | no_validation, hr, manager, both | 無需審核 / HR 審核 / 主管審核 / 雙重審核 |
hr_leave_types | time_type | [建議] | leave, other | 請假 / 其他 |
hr_leave_types | request_unit | [建議] | day, half_day, hour | 天 / 半天 / 小時 |
hr_leaves | state | [DB] | draft, confirm, refuse, validate1, validate, cancel | 草稿 / 已提交 / 已拒絕 / 一級核准 / 最終核准 / 已取消 |
hr_leaves | holiday_type | [建議] | employee, company, department, category | 個人 / 全公司 / 部門 / 分類 |
hr_leave_allocations | state | [建議] | draft, confirm, validate1, validate, refuse | 草稿 / 已提交 / 一級核准 / 最終核准 / 已拒絕 |
hr_leave_allocations | allocation_type | [建議] | regular, accrual | 一般分配 / 累計分配 |
hr_expense_sheets | state | [DB] | draft, submit, approve, post, done, cancel | 草稿 / 已提交 / 已核准 / 已入帳 / 完成 / 取消 |
hr_expense_sheets | payment_state | [建議] | not_paid, in_payment, paid | 未付 / 付款中 / 已付 |
hr_expenses | state | [DB] | draft, reported, approved, done, refused | 草稿 / 已報告 / 已核准 / 完成 / 已拒絕 |
hr_expenses | payment_mode | [建議] | own_account, company_account | 個人墊付 / 公司帳戶 |
hr_work_entries | state | [DB] | draft, validated, conflict, cancelled | 草稿 / 已驗證 / 衝突 / 已取消 |
11.10 MRP 製造模組
| 表 | 欄位 | 約束 | 可接受值 | 說明 |
|---|---|---|---|---|
mrp_boms | type | [DB] | normal, phantom, subcontracting | 一般 / 套件(phantom) / 委外加工 |
mrp_boms | ready_to_produce | [DB] | all_available, asap | 全部備料才生產 / 儘速生產 |
mrp_routing_workcenters | time_mode | [DB] | auto, manual | 自動計算 / 手動設定 |
mrp_productions | state | [DB] | draft, confirmed, progress, to_close, done, cancel | 草稿 / 已確認 / 製造中 / 待結案 / 完成 / 取消 |
mrp_productions | priority | [DB] | 0, 1 | 一般 / 緊急 |
mrp_workorders | state | [DB] | pending, waiting, ready, progress, done, cancel | 待排程 / 等待物料 / 就緒 / 進行中 / 完成 / 取消 |
mrp_unbuilds | state | [DB] | draft, done | 草稿 / 完成 |
11.11 專案管理模組
| 表 | 欄位 | 約束 | 可接受值 | 說明 |
|---|---|---|---|---|
project_projects | privacy_visibility | [DB] | portal, employees, followers | 入口網站可見 / 僅員工 / 僅追蹤者 |
project_tasks | state | [DB] | 01_in_progress, 1_done, 1_canceled, 04_waiting_normal, 03_approved, 02_changes_requested | 進行中 / 完成 / 取消 / 等待中 / 已核准 / 需修改 |
project_tasks | kanban_state | [DB] | normal, done, blocked | 一般 / 就緒 / 受阻 |
project_tasks | priority | [DB] | 0, 1 | 一般 / 緊急 |
project_task_recurrences | repeat_unit | [DB] | day, week, month, year | 每日 / 每週 / 每月 / 每年 |
project_task_recurrences | repeat_type | [DB] | forever, until, after | 永久重複 / 至指定日 / 指定次數 |
project_updates | status | [DB] | on_track, at_risk, off_track, on_hold, done | 進度正常 / 有風險 / 偏離 / 暫停 / 完成 |
11.12 公告模組
| 表 | 欄位 | 約束 | 可接受值 | 說明 |
|---|---|---|---|---|
announcements | priority | [建議] | normal, high, urgent | 一般 / 重要 / 緊急 |
announcements | announcement_type | [建議] | bulletin, push | 公告 / 推播通知 |
announcements | send_mode | [建議] | immediate, scheduled | 立即發送 / 排程發送 |
announcements | send_status | [建議] | draft, pending, sent, failed | 草稿 / 待發送 / 已發送 / 發送失敗 |
announcements | target_type | [建議] | all, tag, level | 全體 / 指定標籤 / 指定等級 |
announcements | validity_type | [建議] | permanent, limited | 永久有效 / 有效期限 |
11.13 固定資產模組
| 表 | 欄位 | 約束 | 可接受值 | 說明 |
|---|---|---|---|---|
fixed_assets | state | [DB] | draft, running, fully_depreciated, disposed, closed | 草稿 / 使用中 / 已完全折舊 / 已處分 / 已結案 |
fixed_assets | depreciation_method | [DB] | straight_line, declining_balance, sum_of_years | 直線法 / 餘額遞減 / 年數合計法 |
fixed_asset_depreciations | status | [DB] | draft, posted | 草稿 / 已入帳 |
11.14 金融/銀行模組
| 表 | 欄位 | 約束 | 可接受值 | 說明 |
|---|---|---|---|---|
partner_banks | account_type | [DB] | bank, iban | 一般銀行 / IBAN 帳號 |
partner_banks | partner_type | [DB] | customer, supplier, member, tenant | 客戶 / 供應商 / 成員 / 租戶 |
11.15 核心參考表
| 表 | 欄位 | 約束 | 可接受值 | 說明 |
|---|---|---|---|---|
uom_uom | uom_type | [DB] | reference, bigger, smaller | 參考單位 / 較大單位 / 較小單位 |
countries | name_position | [建議] | before, after | 姓名在前 / 姓名在後 |
currencies | position | [建議] | before, after | 符號在前 / 符號在後 |
languages | direction | [建議] | ltr, rtl | 左至右 / 右至左 |
ir_sequences | implementation | [DB] | standard, no_gap | 標準(允許跳號) / 無間隙 |
11.16 系統管理模組
| 表 | 欄位 | 約束 | 可接受值 | 說明 |
|---|---|---|---|---|
custom_apps | access_mode | [建議] | internal, external, self_built | 內部應用 / 外部應用 / 自建應用 |
custom_apps | auth_mode | [建議] | platform, independent | 主站跳轉登入 / 獨立認證 |
使用提示:
- 查詢 filter 時,enum 欄位使用
eq運算子精確比對,例如{"column": "state", "op": "eq", "value": "draft"}- 查詢多個 enum 值可使用
in運算子,例如{"column": "state", "op": "in", "value": ["draft", "sent"]}- 新增/更新記錄時,[DB] 約束的 enum 欄位必須使用清單中的值,否則會收到
400/500錯誤
12. 第三方應用實戰指南(Best Practices & Gotchas)
[!TIP] 彙整第三方開發者常見痛點,包含資料隔離機制、查詢防呆、遷移腳本與 CI/CD 注意事項。
12.1 多應用共享租戶 (Multi-App Tenant) 的最佳實踐
[!IMPORTANT] 為什麼這很重要? 在 AI GO 系統中,同一個租戶(Tenant)可能同時啟用多套 Custom App(例如:同時有「訂房平台」與「電商商城」),如果不進行資料隔離,使用者的商城頁面就會看見「高級海景房」被當成商品販售。
建議擴充內容:
- Data Domain Separation (App Domain) 策略:強制規範所有使用到共用表(如
product_templates、sale_orders)的 Custom App,必須在創建資料時注入識別用的領域標籤(例如custom_data: { "app_domain": "ec-platform" })。 - Proxy 層面攔截實作:如果您是在前端實作 API Request 攔截器(Interceptor)或是撰寫了自有的 API Proxy 層,建議在
create與list動作中,自動幫請求補上app_domain的篩選或預設欄位,實現全站「無感隔離」。
12.2 PostgreSQL JSONB 查詢的格式陷阱 (Gotchas)
[!WARNING] 陷阱警告! JSON 序列化後的空格特性,會導致直覺寫法的 ilike 查詢失敗。
建議擴充內容:
- 字串查詢特性:AI GO 將
custom_data以 JSONB 格式儲存於資料庫中。當您使用開放代理 API (如/query端點) 進行ilike過濾時,若使用精準的{"app_domain":"ec-platform"}作為條件,通常會匹配不到資料。 - 解決方案:因為 PostgreSQL 在將 JSONB 物件序列化成字串(Text)進行比較時,常在 JSON 冒號後面自動加上空格(
{"app_domain": "ec-platform"})。因此,建議寫法應為寬鬆字串匹配:- ❌ 錯誤寫法:
custom_data::text ilike '%"app_domain":"ec-platform"%' - ✅ 正確寫法:
custom_data::text ilike '%app_domain%ec-platform%'
- ❌ 錯誤寫法:
12.3 API Proxy 的安全存取控制 (Access & Auth Models)
[!CAUTION] 某些系統核心表(如
sale_order_lines)擁有底層的硬性權限保護,不允許任意增刪。
建議擴充內容:
- 區分 Open Proxy 與 Ext Proxy:明列哪些場景(如公開型錄讀取)可使用 API Key,哪些場景(如消費者自主結帳)必須強制使用 Bearer Token(Custom App User Token)。
- Capability Matrix 限制:針對特定的表,即使您有該表的
Delete引用,如果遇到底層防呆機制(例如:無法刪除已結帳訂單的明細),API 會回應403 Forbidden錯誤,請直接導引客戶至「AI GO 管理員介面」進行圖文操作或授權退款。
12.4 資料遷移腳本範例 (Data Migration Boilerplate)
[!TIP] 當應用程式發展至第二階段(例如後期才加入資料隔離網),不可避免需要批量更新舊有歷史資料的
custom_data。
Node.js Migration Script 範例: 為了確保向前相容,您可以在本地準備一支批次腳本來自動更新:
const axios = require('axios');
const API_URL = 'https://api.ai-go.app/api/v1/open/proxy/product_templates/query';
const API_KEY = 'sk_live_xxxxxx';
async function migrate() {
let offset = 0;
while (true) {
// 先查出尚無標籤的紀錄 (僅示意,請依實際情況運用)
const resp = await axios.post(API_URL, {
limit: 100,
offset: offset
}, { headers: { 'X-API-Key': API_KEY } });
const products = resp.data.data || [];
if (products.length === 0) break;
for (const p of products) {
// 檢查且對每筆舊資料 PATCH 加入 app_domain
if (!p.custom_data || !p.custom_data.app_domain) {
await axios.patch(`https://api.ai-go.app/api/v1/open/proxy/product_templates/${p.id}`, {
custom_data: { ...(p.custom_data || {}), app_domain: 'ec-platform' }
}, { headers: { 'X-API-Key': API_KEY } });
}
}
offset += 100;
console.log(`Migrated batch offset ${offset}`);
}
}
migrate();
12.5 端到端部署與 CI/CD (E2E Deployment)
建議擴充內容:
- 環境變數同步規範:在將前端應用推播至 Vercel 或 GitHub Actions 進行建置前,請務必再三確認
.env.production或 CI/CD Secrets 儀表板中的VITE_API_BASE、VITE_APP_SLUG與AIGO_API_KEY皆已正確配置為 Production 環境對應的值。 - Repository Visibility 提醒:若您使用了 Vercel 的自動化拉取原始碼部署功能(Git Integration),必須賦予 Vercel 應用讀取該 Private GitHub Repository 的權限。若建置過程中發生模組丟失錯誤,請檢查儲存庫權限,或斟酌將原始碼庫設為 Public。