Open API 文件
load.tw 提供 RESTful API,讓開發者用程式上傳圖片、影片、音訊,以及建立短網址。所有 API 都需要 Bearer Token 認證。
🔑 如何取得 API Token
API Token 採人工審核制。請透過 聯絡表單 寄信給我們,附上:
- 你的 load.tw 帳號(Google 登入的 email)
- 用途說明(串接什麼系統、預估每月上傳量)
- 公司 / 專案名稱(個人開發者寫「個人」即可)
審核通過後我們會在 48 小時內回覆,附上你的 API Token(格式:xk_live_xxxxxxxxxxxxxxxxxxxx)。每個帳號最多持有 3 組 Token。
認證方式
所有 API 請求都需要在 HTTP Header 帶上 Bearer Token:
Authorization: Bearer xk_live_xxxxxxxxxxxxxxxxxxxx Content-Type: application/json
Token 權限等同你的帳號。Token 洩漏請立即透過聯絡表單通知我們撤銷。
API 端點總覽
| 方法 | 端點 | 說明 |
|---|---|---|
POST | /api/v1/upload | 上傳檔案(圖片 / 影片 / 音訊) |
POST | /api/v1/shorten | 建立短網址 |
GET | /api/v1/uploads | 列出我的上傳紀錄 |
GET | /api/v1/uploads/{code} | 取得單筆上傳詳情 |
DELETE | /api/v1/uploads/{code} | 刪除上傳 |
GET | /api/v1/shorts | 列出我的短網址 |
DELETE | /api/v1/shorts/{code} | 刪除短網址 |
GET | /api/v1/me | 取得目前帳號資訊 |
Base URL:https://load.tw
1. 上傳檔案 POST /api/v1/upload
上傳流程分三步,全部由 API 自動處理:presign → PUT 到雲端 → finalize。你只需要一個 POST 呼叫。
Request
使用 multipart/form-data 上傳:
| 欄位 | 類型 | 必填 | 說明 |
|---|---|---|---|
file | File | ✅ | 要上傳的檔案(最多 7 張圖 + 2 部影片 + 3 個音訊) |
description | string | 說明文字(最多 90 字) | |
effective_date | int | 有效期限 ID(預設 1 = 1 天,見下方表格) | |
password | string | 密碼保護(留空 = 不設密碼) | |
view_limit | int | 瀏覽次數限制(留空 = 不限) | |
is_public | int | 1 = 公開到圖庫(需審核),0 = 私人(預設) |
Response (200)
{
"success": true,
"code": "av5F45",
"url": "https://load.tw/av5F45",
"files": [
{
"kind": "image",
"name": "photo.jpg",
"mime": "image/jpeg",
"size": 1234567
}
],
"expires_at": "2026-04-26T14:30:00+08:00",
"created_at": "2026-04-16T14:30:00+08:00"
}
curl 範例
curl -X POST https://load.tw/api/v1/upload \ -H "Authorization: Bearer xk_live_xxxxxxxxxxxxxxxxxxxx" \ -F "[email protected]" \ -F "description=我的照片" \ -F "effective_date=8" \ -F "password=mySecret123"
Python 範例
import requests
API_TOKEN = "xk_live_xxxxxxxxxxxxxxxxxxxx"
resp = requests.post(
"https://load.tw/api/v1/upload",
headers={"Authorization": f"Bearer {API_TOKEN}"},
files={"file": open("photo.jpg", "rb")},
data={
"description": "我的照片",
"effective_date": 8, # 7 天
"password": "mySecret123",
},
)
data = resp.json()
print(data["url"]) # https://load.tw/av5F45
Node.js 範例
const fs = require('fs');
const FormData = require('form-data');
const API_TOKEN = 'xk_live_xxxxxxxxxxxxxxxxxxxx';
const form = new FormData();
form.append('file', fs.createReadStream('photo.jpg'));
form.append('description', '我的照片');
form.append('effective_date', '8');
const resp = await fetch('https://load.tw/api/v1/upload', {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_TOKEN}`,
...form.getHeaders(),
},
body: form,
});
const data = await resp.json();
console.log(data.url);
多檔上傳
curl -X POST https://load.tw/api/v1/upload \ -H "Authorization: Bearer xk_live_xxxxxxxxxxxxxxxxxxxx" \ -F "file[][email protected]" \ -F "file[][email protected]" \ -F "file[][email protected]" \ -F "description=活動花絮" \ -F "effective_date=20"
2. 建立短網址 POST /api/v1/shorten
Request
POST /api/v1/shorten
Authorization: Bearer xk_live_xxxxxxxxxxxxxxxxxxxx
Content-Type: application/json
{
"url": "https://www.example.com/very/long/path?ref=abc",
"title": "我的連結"
}
| 欄位 | 類型 | 必填 | 說明 |
|---|---|---|---|
url | string | ✅ | 要縮短的目標網址(http / https) |
title | string | 備註標題(最多 120 字,僅供後台辨識) |
Response (200)
{
"success": true,
"code": "Bk9xWz",
"short_url": "https://load.tw/Bk9xWz",
"target_url": "https://www.example.com/very/long/path?ref=abc",
"created_at": "2026-04-16T14:30:00+08:00"
}
curl 範例
curl -X POST https://load.tw/api/v1/shorten \
-H "Authorization: Bearer xk_live_xxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"url":"https://www.example.com/very/long/path","title":"我的連結"}'
Python 範例
import requests
resp = requests.post(
"https://load.tw/api/v1/shorten",
headers={
"Authorization": "Bearer xk_live_xxxxxxxxxxxxxxxxxxxx",
"Content-Type": "application/json",
},
json={"url": "https://www.example.com/very/long/path"},
)
print(resp.json()["short_url"]) # https://load.tw/Bk9xWz
3. 列出上傳紀錄 GET /api/v1/uploads
GET /api/v1/uploads?page=1&per_page=20 Authorization: Bearer xk_live_xxxxxxxxxxxxxxxxxxxx
Response (200)
{
"data": [
{
"code": "av5F45",
"url": "https://load.tw/av5F45",
"description": "我的照片",
"view_count": 142,
"fav_count": 5,
"expires_at": "2026-04-26T14:30:00+08:00",
"created_at": "2026-04-16T14:30:00+08:00"
}
],
"pagination": {
"page": 1,
"per_page": 20,
"total": 87,
"total_pages": 5
}
}
4. 取得單筆詳情 GET /api/v1/uploads/{code}
curl https://load.tw/api/v1/uploads/av5F45 \ -H "Authorization: Bearer xk_live_xxxxxxxxxxxxxxxxxxxx"
5. 刪除上傳 DELETE /api/v1/uploads/{code}
curl -X DELETE https://load.tw/api/v1/uploads/av5F45 \
-H "Authorization: Bearer xk_live_xxxxxxxxxxxxxxxxxxxx"
# Response: { "success": true, "message": "已刪除" }
6. 列出短網址 GET /api/v1/shorts
curl https://load.tw/api/v1/shorts?page=1 \ -H "Authorization: Bearer xk_live_xxxxxxxxxxxxxxxxxxxx"
7. 刪除短網址 DELETE /api/v1/shorts/{code}
curl -X DELETE https://load.tw/api/v1/shorts/Bk9xWz \
-H "Authorization: Bearer xk_live_xxxxxxxxxxxxxxxxxxxx"
# Response: { "success": true, "message": "已刪除" }
8. 帳號資訊 GET /api/v1/me
curl https://load.tw/api/v1/me \ -H "Authorization: Bearer xk_live_xxxxxxxxxxxxxxxxxxxx"
Response
{
"email": "[email protected]",
"name": "王小明",
"uploads_count": 87,
"shorts_count": 23,
"plan": "free",
"rate_limit": {
"requests_per_minute": 30,
"uploads_per_day": 100
}
}
有效期限 ID 對照表
| ID | 期限 | 說明 |
|---|---|---|
| 0 | 1 分鐘 | 閱後即焚 |
| 1 | 1 天 | 預設值 |
| 2 | 5 分鐘 | 快速分享 |
| 3 | 30 分鐘 | 會議用 |
| 4 | 1 小時 | 短期協作 |
| 5 | 6 小時 | 半日工作 |
| 6 | 12 小時 | 一個工作日 |
| 7 | 3 天 | 週末活動 |
| 8 | 7 天 | 一週活動 |
| 9 | 10 天 | 預購活動 |
| 10 | 30 天 | 最長有期限 |
| 20 | 無期限 | 永久保留 |
支援的檔案格式
| 種類 | 允許的 MIME | 單檔上限 | 每次上限 |
|---|---|---|---|
| 圖片 | image/jpeg image/png image/webp image/gif image/heic image/heif image/avif | 25 MB | 7 張 |
| 影片 | video/mp4 video/quicktime video/webm | 400 MB | 2 部 |
| 音訊 | audio/mpeg audio/mp4 audio/x-m4a audio/aac audio/wav audio/ogg audio/webm audio/flac | 50 MB | 3 個 |
Rate Limiting
| 方案 | 每分鐘請求 | 每日上傳 | 每日短網址 |
|---|---|---|---|
| Free | 30 | 100 | 500 |
| Pro(即將推出) | 120 | 1,000 | 5,000 |
超過限制會收到 429 Too Many Requests,回應 header 包含:
X-RateLimit-Limit: 30 X-RateLimit-Remaining: 0 X-RateLimit-Reset: 1713257460
錯誤回應
所有錯誤都回傳 JSON:
{
"success": false,
"error": "不支援的圖片格式",
"code": "INVALID_MIME"
}
| HTTP 狀態碼 | 說明 |
|---|---|
400 | 參數錯誤(格式不符、超過大小限制、無效的有效期限) |
401 | 未提供 Token 或 Token 無效 |
403 | Token 已被撤銷或帳號被停用 |
404 | 找不到指定的資源 |
429 | 超過 Rate Limit |
500 | 伺服器內部錯誤 |
錯誤代碼一覽
| code | 說明 |
|---|---|
UNAUTHORIZED | Token 無效或未提供 |
TOKEN_REVOKED | Token 已被撤銷 |
RATE_LIMITED | 超過請求頻率限制 |
INVALID_MIME | 不支援的檔案格式 |
FILE_TOO_LARGE | 檔案超過大小限制 |
TOO_MANY_FILES | 單次上傳超過數量限制 |
INVALID_URL | 短網址目標不是有效的 URL |
BLOCKED_DOMAIN | 目標網域已被封鎖 |
INVALID_PRESET | 無效的有效期限 ID |
NOT_FOUND | 找不到指定的資源 |
Webhook(即將推出)
我們正在開發 Webhook 功能,讓你在以下事件發生時收到即時通知:
- 上傳的分享被瀏覽(含國家 / 裝置資訊)
- 短網址被點擊
- 上傳的分享到期被自動刪除
- 上傳的分享通過 / 未通過審核
Webhook 功能預計在 2026 Q3 上線。想提前測試?聯絡我們加入 Beta。
SDK & 套件(社群維護)
| 語言 | 套件 | 狀態 |
|---|---|---|
| Python | pip install loadtw | 即將推出 |
| Node.js | npm install @loadtw/sdk | 即將推出 |
| PHP | composer require loadtw/sdk | 即將推出 |
| Go | go get github.com/loadtw/sdk | 規劃中 |
實際應用範例
以下是三個完整的、可直接執行的實際應用腳本,幫助你快速上手 load.tw API 的串接。
範例一:Python — 批次上傳資料夾內所有圖片
掃描指定資料夾中的所有圖片檔(JPG / PNG / WebP / HEIC),逐一上傳到 load.tw,並將結果彙整成 CSV。
#!/usr/bin/env python3
"""batch_upload.py — 批次上傳資料夾內所有圖片到 load.tw"""
import os
import csv
import sys
import requests
from pathlib import Path
API_TOKEN = os.environ.get("LOADTW_TOKEN", "xk_live_xxxxxxxxxxxxxxxxxxxx")
API_URL = "https://load.tw/api/v1/upload"
# 支援的圖片副檔名
EXTS = {".jpg", ".jpeg", ".png", ".webp", ".heic", ".heif", ".avif", ".gif"}
def upload_file(filepath, expire=8, password=""):
"""上傳單一檔案,回傳 (code, url) 或 (None, error)"""
headers = {"Authorization": f"Bearer {API_TOKEN}"}
data = {"effective_date": str(expire)}
if password:
data["password"] = password
with open(filepath, "rb") as f:
resp = requests.post(API_URL, headers=headers,
files={"file": (filepath.name, f)},
data=data)
result = resp.json()
if result.get("success"):
return result["code"], result["url"]
return None, result.get("error", "Unknown error")
def main():
folder = Path(sys.argv[1]) if len(sys.argv) > 1 else Path(".")
images = sorted(p for p in folder.iterdir()
if p.suffix.lower() in EXTS)
if not images:
print(f"在 {folder} 中找不到圖片檔")
sys.exit(1)
print(f"找到 {len(images)} 張圖片,開始上傳...")
results = []
for img in images:
code, url = upload_file(img)
status = "OK" if code else "FAIL"
print(f" [{status}] {img.name} → {url}")
results.append({"file": img.name, "code": code or "", "url": url})
# 輸出 CSV
csv_path = folder / "upload_results.csv"
with open(csv_path, "w", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=["file", "code", "url"])
writer.writeheader()
writer.writerows(results)
print(f"\n結果已儲存至 {csv_path}")
if __name__ == "__main__":
main()
使用方式:
export LOADTW_TOKEN="xk_live_xxxxxxxxxxxxxxxxxxxx" python3 batch_upload.py /path/to/photos/
範例二:Node.js — 從 CSV 批次縮短網址
讀取一個包含長網址的 CSV 檔案,逐行呼叫 load.tw 短網址 API,並輸出結果。
#!/usr/bin/env node
/**
* shorten_csv.js — 從 CSV 批次縮短網址
* CSV 格式:每行一個 URL,或第一欄為 URL
* 用法:node shorten_csv.js urls.csv
*/
const fs = require('fs');
const path = require('path');
const API_TOKEN = process.env.LOADTW_TOKEN || 'xk_live_xxxxxxxxxxxxxxxxxxxx';
const API_URL = 'https://load.tw/api/v1/shorten';
async function shortenUrl(url, title = '') {
const resp = await fetch(API_URL, {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ url, title }),
});
return resp.json();
}
async function main() {
const csvFile = process.argv[2];
if (!csvFile) {
console.error('用法:node shorten_csv.js <urls.csv>');
process.exit(1);
}
const lines = fs.readFileSync(csvFile, 'utf-8')
.split('\n')
.map(l => l.trim())
.filter(l => l && l.startsWith('http'));
console.log(`讀取到 ${lines.length} 個網址,開始縮短...`);
const results = [];
for (const url of lines) {
try {
const data = await shortenUrl(url);
if (data.success) {
console.log(` ✓ ${data.short_url} ← ${url.substring(0, 60)}...`);
results.push(`${url},${data.short_url},${data.code}`);
} else {
console.log(` ✗ ${data.error} ← ${url.substring(0, 60)}...`);
results.push(`${url},ERROR,${data.error}`);
}
} catch (err) {
console.log(` ✗ ${err.message} ← ${url.substring(0, 60)}...`);
results.push(`${url},ERROR,${err.message}`);
}
// 遵守 Rate Limit:每分鐘 30 次
await new Promise(r => setTimeout(r, 2100));
}
const outFile = csvFile.replace('.csv', '_shortened.csv');
fs.writeFileSync(outFile, 'original_url,short_url,code\n' + results.join('\n'));
console.log(`\n完成!結果已寫入 ${outFile}`);
}
main();
使用方式:
export LOADTW_TOKEN="xk_live_xxxxxxxxxxxxxxxxxxxx" node shorten_csv.js urls.csv
範例三:Shell — CI/CD 一行指令上傳截圖
適合在 GitHub Actions、GitLab CI 或任何 CI/CD 管線中使用。一行 curl 上傳截圖並把短網址寫入環境變數。
# 基本用法:上傳一張截圖,取得短網址 SHARE_URL=$(curl -s -X POST https://load.tw/api/v1/upload \ -H "Authorization: Bearer $LOADTW_TOKEN" \ -F "[email protected]" \ -F "effective_date=7" \ -F "description=CI build #${BUILD_NUMBER}" \ | python3 -c "import sys,json; print(json.load(sys.stdin)['url'])") echo "截圖已上傳: $SHARE_URL" # ---------- GitHub Actions 完整範例 ---------- # 在 .github/workflows/test.yml 中加入: # # - name: Upload test screenshots # env: # LOADTW_TOKEN: ${{ secrets.LOADTW_TOKEN }} # run: | # for f in test-results/screenshots/*.png; do # URL=$(curl -s -X POST https://load.tw/api/v1/upload \ # -H "Authorization: Bearer $LOADTW_TOKEN" \ # -F "file=@$f" \ # -F "effective_date=7" \ # -F "description=E2E screenshot - $(basename $f)" \ # | python3 -c "import sys,json; print(json.load(sys.stdin)['url'])") # echo " $(basename $f) → $URL" >> $GITHUB_STEP_SUMMARY # done # ---------- 搭配 jq 的簡化版 ---------- curl -s -X POST https://load.tw/api/v1/upload \ -H "Authorization: Bearer $LOADTW_TOKEN" \ -F "[email protected]" \ | jq -r '.url'
小提示:把 LOADTW_TOKEN 設為 CI/CD 的 Secret 環境變數,不要寫死在腳本裡。
常見問題
API Token 會過期嗎?
不會。Token 永久有效,除非你主動要求撤銷,或違反服務條款被停用。
可以用 API 上傳影片嗎?
可以。支援 MP4 / MOV / WebM,單檔最大 400 MB。影片會直接傳到雲端儲存,不經過我們的主機,所以即使是大檔案也很快。
API 是免費的嗎?
Free 方案完全免費,每日上傳上限 100 次、短網址 500 條。如果你需要更高的額度,Pro 方案即將推出。
我可以用 API 做商業用途嗎?
可以。只要遵守服務條款(不上傳違法內容、不濫用服務),商業用途完全允許。
審核要多久?
通常 24-48 小時內回覆。如果超過 3 天沒收到回覆,請再寄一次或透過其他管道聯繫。