嘿!如果你正在用 AI 工具寫程式,或是玩一些自動化工具(像 Make、Zapier、n8n),一定碰過這種情況:
「請輸入你的 API Key」
蛤?那是什麼?我要去哪裡拿?
或是 AI 幫你生出一段程式碼,裡面寫著 X-API-Key: your_key_here,然後你就卡住了。
別擔心,這篇文章就是要用最白話的方式,讓你搞懂:
- API Key 到底是什麼東西?
- 為什麼有些服務需要它?
- 拿到之後要放在哪裡?
不用會寫程式也能看懂,看完你就知道怎麼處理了。
先搞懂 HTTP 長什麼樣子
在講 API Key 之前,我們要先知道 HTTP 請求的結構。這很重要,因為 API Key 就是塞在 HTTP 裡面的。
HTTP 請求就像寄一封信
每次你打一個 API,其實就是送出一個 HTTP 請求。你可以把它想像成寄一封信:
- Header(表頭):就像信封外面的資訊——寄件人、收件人、郵戳、掛號或平信
- Body(內容):就像信封裡面的信紙——你真正要講的內容
這兩個部分各有各的用途,不能搞混。
來看一個真實的 HTTP 請求
假設你要打一個 API 新增一筆使用者資料,整個請求長這樣:
POST /api/users HTTP/1.1
Host: api.example.com
Content-Type: application/json
Authorization: Bearer abc123
X-API-Key: my_secret_key
{
"name": "小明",
"email": "ming@example.com"
}上半部(空行以上)就是 Header,下半部就是 Body。
Header 裡面有什麼?
Header 就是一堆「欄位名稱: 值」的組合,每一行一個。常見的有:
| 欄位 | 幹嘛用的 | 範例 |
|---|---|---|
Host | 告訴對方你要打哪個網站 | Host: api.example.com |
Content-Type | 告訴對方你傳的資料是什麼格式 | Content-Type: application/json |
Authorization | 放驗證資訊(像是 Token) | Authorization: Bearer abc123 |
User-Agent | 告訴對方你是用什麼工具發請求 | User-Agent: Mozilla/5.0... |
Accept | 告訴對方你想要什麼格式的回應 | Accept: application/json |
這些都是「標準」的 Header,大家都認得。
Body 裡面有什麼?
Body 就是你要傳的實際資料。最常見的格式是 JSON:
{
"name": "小明",
"email": "ming@example.com"
}不是每個請求都有 Body 喔!像 GET 請求通常就沒有,因為你只是要「拿」資料,不是要「傳」資料。
重點來了:你可以自己定義 Header!
除了那些標準的 Header 之外,我們可以自己發明新的欄位,這叫做 Custom Header(自定義表頭)。
以前有個慣例是在自定義 Header 前面加 X-,像這樣:
X-API-Key: 你的金鑰
X-Request-ID: 12345但這只是慣例,不是強制規定。你愛怎麼取名都可以,沒有人會阻止你。
而且這個 X- 慣例在 2012 年已經被官方(RFC 6648)建議棄用了,原因是:如果一個自定義 Header 後來變成標準,名字裡還卡著 X- 就很尷尬。
所以現在你會看到兩種風格並存:
X-API-Key: abc123 // 舊慣例,還是很多人在用
API-Key: abc123 // 新風格,不加 X- 也完全 OK實務上,看你串接的服務要求什麼格式就用什麼。
有些服務用 X-API-Key,有些用 API-Key,甚至有些用 Authorization,都可以,沒有絕對的對錯。
API Key 到底怎麼用?什麼時候該用?
API Key 是什麼?
簡單講,API Key 就是一組「通關密碼」,用來證明「我有權限使用這個服務」。
舉個例子:你想在自己的網站上嵌入 Google Maps 地圖。Google 不會讓你免費無限用,所以你要先去 Google 後台申請一組 API Key,拿到之後可能長這樣:
AIzaSyD8f9Gk3xPm2nQwR7vL4jH5kM6sT1oY2bC之後每次你的網站要顯示地圖,就要帶上這組 Key。Google 收到請求後會檢查:「這把 Key 我認得,是有註冊的,放行!」然後才把地圖資料給你。
就像進公司要刷門禁卡一樣——沒卡,門不會開。
其他常見的情境:
- 用 OpenAI API 讓你的應用程式能呼叫 ChatGPT
- 串接金流服務(綠界、藍新)處理付款
- 接 Facebook / Instagram API 發文或抓數據
這些服務都會給你一組 API Key,你要保管好,別讓外人知道。
什麼情況適合用 API Key?
✅ 正確場景:從你的伺服器呼叫 API
這是 API Key 最適合的用法。
舉個例子:你做了一個電商網站,使用者下單後要付款。流程是這樣:
flowchart LR
User["使用者"] -->|1.按下結帳| Server["你的伺服器"]
Server -->|2.帶 API Key 呼叫| Payment["綠界金流 API"]
Payment -->|3.回傳結果| Server
Server -->|4.顯示成功| User整個過程中,API Key 都待在你的伺服器裡,使用者完全碰不到,也看不到。
這就是為什麼這種做法安全:
- Key 只有你的伺服器知道
- 外人沒有任何管道可以偷看
- 你可以設定只有特定 IP 能連進來,多一層保護
❌ 錯誤場景:從瀏覽器或 App 直接呼叫 API
這是很多新手會踩的坑。
舉個例子:你做了一個網頁,想讓使用者輸入問題,然後直接呼叫 OpenAI API 取得回答。你把 API Key 寫在 JavaScript 裡面:
flowchart LR
User["使用者的瀏覽器"] -->|帶 API Key 呼叫| OpenAI["OpenAI API"]
Hacker["有心人士 👀"] -.->|打開開發者工具偷看| User問題來了:JavaScript 是跑在使用者瀏覽器裡的,任何人只要按 F12 打開開發者工具,就能看到你的 Key。
手機 App 也一樣,可以被反編譯,Key 照樣被挖出來。
Key 被偷走之後會怎樣?別人拿你的 Key 亂用,帳單寄給你。
真實案例:Google Maps API Key
這是一個經典案例,用 Google Maps 來看正確和錯誤的差別:
❌ 錯誤示範:Key 寫在前端
很多網站直接把 Google Maps 的 API Key 寫在 HTML 裡:
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyD8f9Gk3xPm2nQwR7vL4jH5kM6sT1oY2bC"></script>任何人只要「檢視原始碼」就能複製這把 Key,然後拿去自己的網站用。Google Maps 是要收費的,帳單會寄給原本的 Key 擁有者。
✅ 正確示範:Key 放在後端
安全的做法是讓你的伺服器去呼叫 Google Maps API,前端只跟你的伺服器溝通:
flowchart LR
Browser["使用者的瀏覽器"] -->|1.請求地圖資料| Server["你的伺服器"]
Server -->|2.帶 API Key 呼叫| Google["Google Maps API"]
Google -->|3.回傳地圖資料| Server
Server -->|4.轉給前端| Browser這樣 Key 永遠不會出現在使用者的瀏覽器裡,自然也不會被偷。
記住這個原則:API Key 只能存在伺服器上,絕對不能出現在前端。
那 Key 要放在哪裡?
確定要用 API Key 之後,要放在請求的哪個位置呢?
推薦做法:放在 Header
X-API-Key: Admin123打 API 的時候帶上這個 Header,後端收到就會去檢查「這把 Key 對不對」,對了才給你資料。
另一種做法:放在 Query String
有些人會放在網址後面:
https://api.example.com/data?api_key=Admin123但這樣比較不安全,因為網址可能會被記錄在瀏覽器歷史、伺服器 Log 裡面,所以建議還是放 Header。
怎麼管理 API Key?
假設今天你要提供 API 給別人用,你要怎麼給他們 Key?
方法一:直接寫死
最簡單的方式,就是訂好一組 Key,然後告訴對方。
API_KEY=secret123456優點是簡單,缺點是不夠彈性。適合公司內部系統,大家都是自己人的情況。
方法二:用資料庫管理
比較正式的做法是把 Key 存在資料庫裡,這樣你可以:
- 隨時產生新的 Key
- 隨時把 Key 停用或刪除
- 設定 Key 的有效期限
像 Slack、Discord 這些服務,都有一個「產生 API Key」的按鈕,按下去就給你一組 Key。不想用了?按刪除就好。這就是用資料庫管理的方式。
flowchart TB
subgraph 管理階段["📋 管理階段"]
Admin["管理員"] -->|1.按下「產生 Key」| Dashboard["後台介面"]
Dashboard -->|2.建立一筆記錄| DB[("資料庫<br>─────<br>Key: abc123<br>期限: 2025/12/31<br>狀態: 有效")]
Dashboard -->|3.顯示 Key| Admin
end
subgraph 使用階段["🔐 驗證階段"]
Request["API 請求<br>帶著 Key: abc123"] -->|4.檢查這把 Key| DB
DB -->|5a.Key 有效 ✅| Allow["放行,回傳資料"]
DB -->|5b.Key 過期/刪除 ❌| Deny["拒絕,回傳錯誤"]
end這樣做的好處是:如果發現 Key 被外洩了,馬上進後台刪掉,那把 Key 立刻就失效了。
Key 什麼時候會失效?
兩種情況:
- 被刪除:你主動把這把 Key 停用了
- 過期了:Key 通常會設有效期限,過了就不能用
後端收到請求時,會去資料庫查這把 Key:存在嗎?過期了嗎?被刪除了嗎?都沒問題才放行。
來看看程式碼怎麼寫
打 API 的時候
用 cURL:
curl -X GET "https://api.example.com/data" \
-H "X-API-Key: your_key_here"用 JavaScript:
fetch('https://api.example.com/data', {
headers: {
'X-API-Key': 'your_key_here'
}
})用 Python:
import requests
headers = {'X-API-Key': 'your_key_here'}
response = requests.get('https://api.example.com/data', headers=headers)後端驗證(Node.js 範例)
app.get('/api/data', (req, res) => {
const apiKey = req.headers['x-api-key'];
if (!apiKey) {
return res.status(401).json({ error: '請提供 API Key' });
}
// 檢查 Key 是否有效(實際上會查資料庫)
if (apiKey !== 'Admin123') {
return res.status(401).json({ error: 'Key 不對喔' });
}
res.json({ message: '驗證成功!' });
});X-API-Key 和 Authorization 的差別
剛剛的程式碼範例都是用 X-API-Key 這個 Header,但如果你實際去串接 OpenAI、Stripe 這些服務,會發現他們要求的格式不太一樣:
# 我們剛剛教的
curl -H "X-API-Key: your_key_here"
# OpenAI 要求的
curl -H "Authorization: Bearer sk-xxxxxxxx"這兩種寫法都可以放 API Key,那差在哪裡?什麼時候該用哪個?
X-API-Key 是自己定義的
還記得前面說的嗎?我們可以自己發明 Header 欄位。
X-API-Key 就是大家約定俗成的寫法,不是官方規定的標準。
有些服務用 X-API-Key,有些用 API-Key(不加 X-),都可以,看服務文件怎麼寫就怎麼用。
Authorization 是 HTTP 規範的標準 Header
Authorization 就不一樣了,它不是誰發明的,而是 HTTP 協定本身就定義好的標準 Header,專門用來放驗證資訊。
你可以把它想成:HTTP 在設計的時候,就預留了一個「放通行證」的欄位,這個欄位就叫 Authorization。
最常見的格式是 Authorization: Bearer <你的金鑰>,很多大型服務(OpenAI、Stripe、GitHub…)都用這個格式。
實際打 OpenAI API 的程式碼
用 JavaScript:
fetch('https://api.openai.com/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': 'Bearer sk-xxxxxxxx', // 注意這裡是 Authorization,不是 X-API-Key
'Content-Type': 'application/json'
},
body: JSON.stringify({
model: 'gpt-4',
messages: [{ role: 'user', content: '你好' }]
})
})
用 Python:
import requests
headers = {
'Authorization': 'Bearer sk-xxxxxxxx',
'Content-Type': 'application/json'
}
response = requests.post('https://api.openai.com/v1/chat/completions',
headers=headers,
json={'model': 'gpt-4', 'messages': [{'role': 'user', 'content': '你好'}]})
那我到底該用哪個?
簡單原則:
| 情境 | 用什麼 |
|---|---|
| 串接第三方服務 | 照他們文件規定,通常是 Authorization: Bearer |
| 自己開發 API | 兩種都可以,Authorization 比較標準,X-API-Key 比較直覺 |
| 公司內部系統 | 看團隊習慣,統一就好 |
進階問題:Authorization 會不會「撞車」?
前面教的是用 Authorization 放 API Key,但其實這個 Header 還有另一個很常見的用途:放使用者的登入 Token。
舉個例子:你做了一個網站,有會員登入功能。
使用者登入成功後,後端會發一組 Token 給他,之後使用者每次發請求,都要帶上這組 Token 來證明「我是已登入的會員」。
這組 Token 通常也是放在 Authorization: Bearer 裡面。
所以問題來了:
「使用者的登入 Token 要放
Authorization…」「串接 OpenAI 的 API Key 也要放
Authorization…」「這樣不就衝突了嗎?同一個欄位怎麼放兩種東西?」
答案是:完全不會衝突!
為什麼?因為這是兩個完全獨立的請求。
還記得前面講的嗎?API Key 適合用在 Server 對 Server 的情境:
flowchart LR
User["使用者<br>瀏覽器"] -->|"① 帶登入 Token"| Server["你的後端<br>Server"]
Server -->|"② 帶 API Key"| OpenAI["OpenAI<br>API"]
OpenAI -->|"③ 回傳結果"| Server
Server -->|"④ 回傳給使用者"| User
這裡有兩個完全獨立的 HTTP 請求,各自有自己的 Header:
請求 ①:使用者 → 你的後端
POST /api/chat HTTP/1.1
Host: your-website.com
Authorization: Bearer eyJhbGciOiJIUzI1... ← 使用者的登入 Token
請求 ②:你的後端 → OpenAI
POST /v1/chat/completions HTTP/1.1
Host: api.openai.com
Authorization: Bearer sk-xxxxxxxx ← OpenAI 的 API Key
看到了嗎?這是兩封完全不同的 HTTP 請求!
使用者的 Token 是放在「使用者 → 你」這個 HTTP 請求裡,OpenAI 的 API Key 是放在「你 → OpenAI」這個 HTTP 請求裡。
兩個請求各走各的路,根本不會打架。
用前面的便利商店例子來想:你拿會員卡給店員(你的身份),店員再用 POS 機登入總公司(店員的身份)。你的會員卡跟店員的帳號是兩回事,不會互相干擾。
完整的後端程式碼長這樣
把前面學的串起來,看看你的後端(Node.js)會怎麼處理這兩個請求:
app.post('/api/chat', async (req, res) => {
// ===== 請求 ①:驗證「使用者」是誰 =====
const userToken = req.headers['authorization']; // 使用者的登入 Token
const user = verifyUserToken(userToken);
if (!user) {
return res.status(401).json({ error: '請先登入' });
}
// ===== 請求 ②:用「你的 API Key」呼叫 OpenAI =====
// 注意:這個 Key 存在環境變數,不會暴露給前端
const response = await fetch('https://api.openai.com/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.OPENAI_API_KEY}`, // OpenAI 的 Key
'Content-Type': 'application/json'
},
body: JSON.stringify({
model: 'gpt-4',
messages: [{ role: 'user', content: req.body.message }]
})
});
// ===== 把結果回傳給使用者 =====
const data = await response.json();
res.json(data);
});
這段程式碼完美呼應了前面講的幾個重點:
- API Key 放在後端:
process.env.OPENAI_API_KEY是環境變數,前端看不到 - Server 對 Server:是你的伺服器去呼叫 OpenAI,不是使用者的瀏覽器
- 兩個請求分開處理:使用者的 Token 和 OpenAI 的 Key 各管各的
安全小提醒
幾個重點,幫你避免踩雷:
- Key 只放伺服器端,前端絕對不能出現
- 用環境變數存 Key,不要直接寫在程式碼裡
- 記得設過期時間,定期換新的 Key
- 搭配 IP 白名單,只讓特定的伺服器連進來
- 一定要用 HTTPS,不然 Key 在傳輸過程中可能被攔截
總結
來複習一下重點:
| 項目 | 內容 |
|---|---|
| API Key 是什麼 | 一把用來驗證身份的鑰匙 |
| 放在哪裡 | HTTP Header 裡面,格式是 X-API-Key: 你的Key |
| 什麼時候用 | Server 對 Server ✅,Client 對 Server ❌ |
| 怎麼管理 | 簡單的寫死,正式的用資料庫 |
| 最重要的事 | Key 絕對不能暴露在前端! |
API Key 是最基本的驗證方式,搞懂這個之後,你就可以繼續學更進階的東西,像是 OAuth、JWT 等等。
希望這篇有幫助到你,有問題歡迎留言!