運作方式
GELATOlab API 是標準 HTTPS JSON API,不必安裝專用 SDK。LLM 不應自行猜測食材 ID 或計算配方數值;正確流程是先搜尋食材,再把 API 回傳的 ID 與克數送進配方平衡端點。
例如:鮮奶 600g、砂糖 160g
每項食材呼叫 ingredients/search
由 GELATOlab 引擎回傳數值
SERVER-SIDE ONLY
API Key 不可放在瀏覽器、手機 App 或公開程式碼。
請把 Key 存在 server environment variable、雲端 Secret Manager 或密碼管理器。前端應呼叫你自己的後端,再由後端呼叫 GELATOlab API。
申請與安裝
啟用 BUSINESS
Public API 是 BUSINESS 與 ENTERPRISE 權益。登入 GELATOlab 後,確認帳號方案仍在有效期間。
開啟開發者中心
前往「設定 → GELATOlab API → 開啟開發者中心」,建立 LIVE 或 TEST Key。每個帳號最多可有 5 組啟用中的 Key。
立即保存 Key
完整 Key 只在建立時顯示一次。複製後存進 Secret Manager;若遺失,請撤銷舊 Key 並建立新 Key。
選擇你的執行環境
Node.js 18 以上可直接使用內建 fetch;Python 安裝 requests;終端機測試可直接使用 cURL。
不需要額外安裝 SDK
建立一個 server-side 專案,使用 Node.js 內建的 fetch。請勿把 Key 寫死在程式碼中。
mkdir gelatolab-api-demo
cd gelatolab-api-demo
npm init -y
node --version
# macOS / Linux
export GELATOLAB_API_KEY="gl_live_your_key"
# Windows PowerShell
$env:GELATOLAB_API_KEY="gl_live_your_key"
const BASE_URL = "https://gelatolab.com.tw/api/v1";
const API_KEY = process.env.GELATOLAB_API_KEY;
if (!API_KEY) throw new Error("Missing GELATOLAB_API_KEY");
export async function gelatoLab(path, options = {}) {
const response = await fetch(`${BASE_URL}${path}`, {
...options,
headers: {
Authorization: `Bearer ${API_KEY}`,
"Content-Type": "application/json",
...options.headers,
},
});
const body = await response.json();
if (!response.ok) {
const error = new Error(body.message || "GELATOlab API error");
error.status = response.status;
error.code = body.error;
error.requestId = body.request_id;
throw error;
}
return body;
}
使用 requests 建立後端 Client
建議在 virtual environment 中安裝,並從環境變數讀取 Key。
python -m venv .venv
# macOS / Linux
source .venv/bin/activate
# Windows PowerShell
.\.venv\Scripts\Activate.ps1
python -m pip install requests
import os
import requests
BASE_URL = "https://gelatolab.com.tw/api/v1"
API_KEY = os.environ["GELATOLAB_API_KEY"]
def gelatolab(path, method="GET", **kwargs):
headers = kwargs.pop("headers", {})
headers["Authorization"] = f"Bearer {API_KEY}"
response = requests.request(
method,
f"{BASE_URL}{path}",
headers=headers,
timeout=30,
**kwargs,
)
response.raise_for_status()
return response.json()
先用 cURL 驗證連線
健康檢查不需要 Key;其他端點都要帶 Bearer Authorization header。
# 公開健康檢查
curl "https://gelatolab.com.tw/api/v1/health"
# 驗證 API Key
curl "https://gelatolab.com.tw/api/v1/usage" \
-H "Authorization: Bearer $GELATOLAB_API_KEY"
curl.exe "https://gelatolab.com.tw/api/v1/usage" `
-H "Authorization: Bearer $env:GELATOLAB_API_KEY"
驗證與環境
除了 /health 與 /openapi.json,所有請求都必須在 Authorization header 放入 Bearer Key。
Authorization: Bearer gl_live_your_key
gl_live_*
正式服務使用。請依團隊、應用程式或環境分開建立,方便單獨撤銷。
gl_test_*
開發與測試環境使用。TEST 與 LIVE 的 Key 類型必須和建立時的環境一致。
端點與完整流程
/ingredients/search把使用者食材名稱解析成官方 ID
0/recipes/balance計算 PAC、POD、MSNF、固形物與凍結點
1 / success/usage查詢本月 included 與 prepaid 額度
0/health檢查 API、引擎與食材資料版本
0STEP A · RESOLVE INGREDIENTS
先搜尋每一項食材
使用者輸入的「鮮奶」可能是別名。搜尋端點會回傳 GELATOlab 官方食材 ID;後續配方只能傳 ID 與克數,不接受自行填入成分資料。
curl "https://gelatolab.com.tw/api/v1/ingredients/search?q=鮮奶&limit=5" \
-H "Authorization: Bearer $GELATOLAB_API_KEY"
{
"request_id": "...",
"query": "鮮奶",
"matches": [
{
"id": "ilLc1HQsDxs7X4vyVDR1",
"name": "全脂牛奶",
"name_en": "Whole Milk",
"category": "乳製品",
"match_score": 95
}
],
"usage_units": 0
}
STEP B · BALANCE RECIPE
使用 ID 與克數計算配方
每次 POST 必須帶一個 8–128 字元的 Idempotency-Key。相同 Key 與相同 request body 重送時,不會重複扣 unit;相同 Key 搭配不同內容會回傳 409。
curl "https://gelatolab.com.tw/api/v1/recipes/balance" \
-X POST \
-H "Authorization: Bearer $GELATOLAB_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: recipe-demo-20260717-001" \
--data '{
"recipe_type": "milk",
"items": [
{ "ingredient_id": "ilLc1HQsDxs7X4vyVDR1", "grams": 600 },
{ "ingredient_id": "2Sef4m2eeoyHz11NqQwq", "grams": 150 },
{ "ingredient_id": "v5qYjTLMaisEiKy9has0", "grams": 160 },
{ "ingredient_id": "CFY4HJ1JJXrcB8JvPPXM", "grams": 40 },
{ "ingredient_id": "R3_002", "grams": 50 }
]
}'
{
"recipe_type": "milk",
"usage_units": 1,
"balance": {
"totalWeight": 1000,
"water": 66.6,
"fat": 7.39,
"protein": 3.68,
"sugar": 15.97,
"totalSolids": 33.4,
"msnf": 9.86,
"pod": 16.83,
"pac": 181,
"freezingPoint": -1.8,
"overrun": 27.3
}
}
milkcreamsorbetyogurtveganalcoholpethighProteinsugarFreeSTEP C · CHECK USAGE
查詢剩餘額度
curl "https://gelatolab.com.tw/api/v1/usage" \
-H "Authorization: Bearer $GELATOLAB_API_KEY"
接到 LLM 或 Agent
讓模型負責理解需求與整理食材;讓 GELATOlab 負責食材解析與數值計算。這個責任邊界能避免模型捏造 PAC、POD 或食材係數。
SYSTEM INSTRUCTION
把以下規則放進 agent 的 system prompt
你可以使用 GELATOlab 配方工具。
規則:
1. 使用者提供食材名稱時,先逐項呼叫 searchIngredients。
2. 只能使用搜尋結果回傳的 ingredient_id;不可自行猜測 ID。
3. 收集所有 ID 與克數後,再呼叫 balanceRecipe。
4. PAC、POD、MSNF、總固形物與凍結點必須引用 API 結果,不可自行計算。
5. 同一次配方重試必須沿用相同 Idempotency-Key。
6. API 回傳 402 時,告知使用者額度不足;不要繞過計費。
7. API 回傳 request_id 時保留它,方便問題追蹤。
FUNCTION SCHEMA
通用 function calling 工具定義
大多數支援 function calling 的 LLM SDK 都能映射這組 JSON Schema;欄位包裝方式依供應商 SDK 調整。
export const gelatolabTools = [
{
name: "gelatolab_search_ingredients",
description: "把食材名稱解析為 GELATOlab 官方 ingredient_id。配方計算前必須先呼叫。",
inputSchema: {
type: "object",
additionalProperties: false,
required: ["query"],
properties: {
query: { type: "string", minLength: 1, maxLength: 80 },
limit: { type: "integer", minimum: 1, maximum: 20, default: 5 }
}
}
},
{
name: "gelatolab_balance_recipe",
description: "使用官方食材 ID 與克數計算配方平衡。成功呼叫扣 1 unit。",
inputSchema: {
type: "object",
additionalProperties: false,
required: ["recipe_type", "items"],
properties: {
recipe_type: {
type: "string",
enum: ["milk", "cream", "sorbet", "yogurt", "vegan", "alcohol", "pet", "highProtein", "sugarFree"]
},
items: {
type: "array",
minItems: 1,
maxItems: 60,
items: {
type: "object",
additionalProperties: false,
required: ["ingredient_id", "grams"],
properties: {
ingredient_id: { type: "string" },
grams: { type: "number", exclusiveMinimum: 0, maximum: 100000 }
}
}
}
}
}
}
];
TOOL DISPATCHER
在你的後端執行模型的 tool call
import crypto from "node:crypto";
import { gelatoLab } from "./client.mjs";
export async function runGelatoLabTool(name, input) {
if (name === "gelatolab_search_ingredients") {
const query = new URLSearchParams({
q: input.query,
limit: String(input.limit || 5),
});
return gelatoLab(`/ingredients/search?${query}`);
}
if (name === "gelatolab_balance_recipe") {
return gelatoLab("/recipes/balance", {
method: "POST",
headers: { "Idempotency-Key": crypto.randomUUID() },
body: JSON.stringify(input),
});
}
throw new Error(`Unknown tool: ${name}`);
}
額度與限制
只有成功完成的 recipes/balance 扣 1 unit。計算失敗會退回預留額度;同一個 Idempotency-Key 與相同內容的重送不會重複扣點。每月 included 額度先使用,再扣 prepaid units。
1,000 units
NT$490NT$0.49 / unit
5,000 units
NT$1,990NT$0.398 / unit
20,000 units
NT$5,990NT$0.2995 / unit
LLM 模型 token 費用由你的模型供應商另行計收,不包含在 GELATOlab units 內。
錯誤處理
錯誤回應都是 JSON,包含穩定的 error code、可讀訊息與 request_id。記錄 request_id,但不要把 API Key 寫進 log。
invalid_query / invalid_items修正輸入格式、recipe_type 或 Idempotency-Key。
invalid_api_key確認 Bearer header、Key 是否完整,或重新建立 Key。
insufficient_quota前往開發者中心購買 units,再重送原請求。
business_required / insufficient_scope確認 BUSINESS 權益與 Key scopes。
idempotency_conflict / request_in_progress相同操作沿用原 Key;不同內容產生新 Key。短暫等待後可重試。
ingredient_not_found重新呼叫搜尋端點取得有效 ID。
rate_limit_exceeded依 Retry-After header 指示延後,使用 exponential backoff。
internal_error保留 request_id,延遲後重試;不要無限重送。
{
"error": "ingredient_not_found",
"message": "找不到官方食材 ID",
"request_id": "d0f7...",
"details": {
"index": 2,
"ingredient_id": "unknown-id"
}
}
正式上線清單
READY TO FORMULATE