透過 Badges Ninja REST API 簽發 Open Badges:快速入門
驗證身分、建立簽發者、設計或上傳徽章,再把它頒發給接收者——全部透過 REST 完成。附 JavaScript 與 Python 範例。
大多數證書專案其實用不上 API。如果你開設的課程每年只有幾百位畢業生,控制台就能搞定一切:在視覺化設計器裡設計數位徽章,上傳一個 CSV,每位接收者都會拿到一個驗證頁面和一份 PDF 證書。如果你的情況正是如此,請先看如何透過 CSV 簽發 Open Badges,之後再回來。
當證書需要由其他系統來簽發時,API 就派上用場了:你的學習平台把某門課程標記為完成,你的報名工具結束了一場活動,你的人資系統記錄下一個已完成的合規模組。在這些情境裡,沒人想要每週末都匯出一次試算表。在完成的那一刻發出一次 HTTP 呼叫簡單得多,接收者也能在成就還新鮮的時候拿到數位徽章。
本快速入門用四次呼叫走完整個流程:取得金鑰、建立簽發者、建立徽章、頒發徽章。之後我們再看如何把驗證連結交給接收者,以及如何檢查結果。下面所有請求格式都來自已部署的 handler,所以你可以直接複製並執行。
開始之前你需要準備什麼
- 一個 badges.ninja 的免費帳號。Free 方案足夠完成本教學:它包含 2 個簽發者、5 個徽章、2 個席位和 1 個 API 金鑰。
- 一個在控制台中建立的 API 金鑰。
- 一張作為徽章圖像的 PNG 或 JPG,或是一個你在視覺化設計器中設計好的徽章。
所有請求的基底 URL 都是 https://api.badges.ninja。
步驟 1:建立 API 金鑰
登入後,在側邊欄開啟 API Keys,點選 Create API Key。幫它取一個能說明用途的名稱,例如 “LMS integration”,這樣之後輪替金鑰時你就能分辨它們。

金鑰只會顯示一次。請立刻把它複製到你的密鑰管理工具或環境變數中。金鑰以 bws_ 開頭,後面接 32 個十六進位字元,每次請求都要把它放在 X-Api-Key 標頭中傳送。在同一個畫面中撤銷金鑰會立即生效。
幾個能省去日後麻煩的習慣:
- 絕對不要把金鑰放進前端程式碼或公開的程式庫。請從伺服器、無伺服器函式或自動化工具呼叫 API。
- 每個整合使用一個金鑰。一旦某個金鑰外洩,你只需要撤銷這一個整合,而不是全部。
- 控制台也接受你已登入的工作階段(以
Authorization: Bearer傳送的 Cognito JWT),但對於指令碼和整合來說,API 金鑰才是合適的工具。
下面所有範例都從名為 BADGES_API_KEY 的環境變數讀取金鑰。
步驟 2:建立簽發者
簽發者是為徽章背書的組織。它會出現在每個驗證頁面以及 Open Badge v2.0 資料中,所以請使用大家真正熟悉的名稱。
curl -X POST https://api.badges.ninja/issuers \
-H "X-Api-Key: $BADGES_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"Acme Academy","url":"https://acme.example.com","email":"badges@acme.example.com"}'
必填欄位是 name(至少 3 個字元)、url(有效的 http 或 https 位址)和 email。選填欄位是 logo(base64 編碼的圖像)和 linkedinOrganizationId,後者會在你的公開證書頁面上啟用 Add to LinkedIn Profile 按鈕。
回應中包含簽發者識別碼:
{
"issuerId": "https://api.badges.ninja/certify-badge/issuer/a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
請原封不動地保留這個值。它是下一步的輸入。
簽發者驗證
只有已驗證的簽發者才能建立徽章。驗證方式如下:
- 如果簽發者的電子郵件與你帳號上的電子郵件相符,簽發者會被自動驗證。這是第一次測試最快的途徑。
- 如果電子郵件不同,一封附有驗證碼的驗證郵件會寄到該位址。在建立徽章之前,你需要在控制台(或透過簽發者 API)確認這個驗證碼。
因此,在本教學中請使用你註冊時用的同一個電子郵件。
步驟 3:建立徽章
徽章是可重複使用的範本:名稱、描述、頒發標準和圖像。你之後頒發的每一次授予都會指向它。
請求是單純的 JSON。圖像以 base64 字串的形式傳入,所以不用跟 multipart 上傳搏鬥。形如 data:image/png;base64, 的 data URL 前綴會被接受並自動移除。
JavaScript(Node 18 或更新版本):
import { readFileSync } from "node:fs";
const API_KEY = process.env.BADGES_API_KEY;
const image = readFileSync("./badge.png").toString("base64");
const res = await fetch("https://api.badges.ninja/badges", {
method: "POST",
headers: { "X-Api-Key": API_KEY, "Content-Type": "application/json" },
body: JSON.stringify({
name: "JavaScript Fundamentals",
description: "Demonstrates proficiency in core JavaScript concepts",
criteria: "Completed the JavaScript Fundamentals course with a score of 80% or higher",
image,
issuerId: "https://api.badges.ninja/certify-badge/issuer/a1b2c3d4-e5f6-7890-abcd-ef1234567890",
}),
});
const { badgeId } = await res.json();
console.log(badgeId);
Python:
import base64, os, requests
API_KEY = os.environ["BADGES_API_KEY"]
with open("badge.png", "rb") as f:
image = base64.b64encode(f.read()).decode()
res = requests.post(
"https://api.badges.ninja/badges",
headers={"X-Api-Key": API_KEY},
json={
"name": "JavaScript Fundamentals",
"description": "Demonstrates proficiency in core JavaScript concepts",
"criteria": "Completed the JavaScript Fundamentals course with a score of 80% or higher",
"image": image,
"issuerId": "https://api.badges.ninja/certify-badge/issuer/a1b2c3d4-e5f6-7890-abcd-ef1234567890",
},
)
badge_id = res.json()["badgeId"]
print(badge_id)
這五個欄位(name、description、criteria、image、issuerId)都是必填的。另有兩個值得了解的選填欄位:shareText,即接收者在社群網路上分享時看到的預設文字(支援 {{badge_name}}、{{issuer_name}} 和 {{award_url}} 佔位符);以及 designJson,它儲存視覺化設計器的文件,以便之後可以逐圖層編輯徽章。
成功時會回傳 HTTP 200 和 { "badgeId": "<id>" }。圖像會被永久儲存,這個徽章現在就是一個任何人都可以取得的 Open Badge v2.0 BadgeClass。
到底該不該用程式碼建立徽章?
通常不該。徽章設計是創意工作,視覺化設計器(80 多個範本、形狀、圖示、11 種字型以及自訂上傳)比指令碼合適得多。常見的做法是:在控制台裡把每個徽章設計一次,然後讓你的整合只針對它頒發授予。你可以用 GET /badges 列出你的徽章,並複製所需徽章的 id。
當你需要以程式方式產生徽章時,例如為擁有數百門課程的目錄每門課程產生一個,或是在建置測試環境時,再透過 API 建立徽章。
步驟 4:頒發徽章
這就是你的整合要呼叫成千上萬次的那個請求。傳送徽章、接收者和日期即可。
curl:
curl -X POST https://api.badges.ninja/awards \
-H "X-Api-Key: $BADGES_API_KEY" \
-H "Content-Type: application/json" \
-d '{"badgeId":"<badge-id>","recipient":{"name":"Jane Smith","email":"jane@example.com"},"issuedOn":"2026-09-28"}'
JavaScript:
const res = await fetch("https://api.badges.ninja/awards", {
method: "POST",
headers: { "X-Api-Key": API_KEY, "Content-Type": "application/json" },
body: JSON.stringify({
badgeId,
recipient: { name: "Jane Smith", email: "jane@example.com" },
issuedOn: Date.now(),
}),
});
const { awardId } = await res.json();
Python:
import time, requests
res = requests.post(
"https://api.badges.ninja/awards",
headers={"X-Api-Key": API_KEY},
json={
"badgeId": badge_id,
"recipient": {"name": "Jane Smith", "email": "jane@example.com"},
"issuedOn": int(time.time() * 1000),
},
)
award_id = res.json()["awardId"]
最容易踩坑的幾條規則:
recipient是一個巢狀物件,包含name和email。像recipientEmail這樣的扁平欄位會被拒絕。recipient.name至少要有 5 個字元。issuedOn是必填的。可以傳送紀元毫秒數,或2026-09-28這樣的 ISO 日期字串。expires是選填的,接受相同的格式。
成功時回傳 HTTP 200,回應內容中包含 awardId。接收者的電子郵件在 Open Badge 資料中以 SHA-256 雜湊的形式儲存,因此公開的 JSON 絕不會洩露它。
步驟 5:找到驗證頁面和 Open Badge JSON
頒發回應給你的是一個識別碼,而不是現成的連結。該識別碼以一個 GUID 結尾,公開頁面就是用這個 GUID 組成的:
- 供人閱讀的驗證頁面:
https://badges.ninja/awards/<awardId> - Open Badge v2.0 JSON-LD:
https://api.badges.ninja/certify-badge/award/<awardId>
如果你拿到的 awardId 是一個完整的 URL,請把路徑的最後一段當作 GUID。
兩者都是公開的。任何拿到連結的人都不需要建立帳號就能驗證這份證書,這正是重點:雇主或招生人員應該能在十秒內查驗一枚徽章。
取得這份 JSON,看看外界看到的是什麼:
curl https://api.badges.ninja/certify-badge/award/<awardId>
你會得到一個 Open Badge v2.0 Assertion:它所引用的徽章、經過雜湊的接收者身分、頒發日期,以及一個指回託管 assertion 的驗證區塊。由於這是標準的 Open Badges 資料,任何理解該格式的工具都能讀取。這種可攜性正是選擇 Open Badges 而不是專有 PDF 的原因;Open Badges vs PDF certificates 對這項取捨有更深入的討論。
接收者如何收到證書
建立授予和通知接收者是兩件事。接收者可以透過接收者入口網站 badges.ninja/me 開啟自己的證書,該入口使用免密碼的魔法連結登入,他們還可以在 badges.ninja/u/<handle> 發布公開個人頁面。在驗證頁面上,他們可以把徽章加入 LinkedIn、下載 PDF 證書,或分享連結。
最初幾次測試時,用你自己的電子郵件給自己頒發一個徽章,親自走一遍接收者的體驗。這是發現徽章描述讀起來彆扭之類問題的最快辦法。
不會讓你頭痛的錯誤處理
API 使用一般的 HTTP 狀態碼。你會遇到的有:
| Status | 意義 | 該怎麼做 |
|---|---|---|
| 200 | 成功 | 讀取 JSON 回應內容 |
| 400 | 欄位缺失或無效,包括接收者姓名少於 5 個字元 | 修正請求內容;重試同樣的請求還是會失敗 |
| 401 | API 金鑰缺失或錯誤 | 檢查 X-Api-Key 標頭,以及金鑰是否已被撤銷 |
| 402 | 額度或方案配額用完 | 升級方案,或等待下一個配額週期 |
| 404 | 找不到該徽章 | 檢查你傳入的 badgeId |
兩個實用建議。第一,把 400 當作資料問題,並記錄回應內容,因為它會指出出錯的欄位。第二,在你這一側做到冪等:把 awardId 和完成紀錄一起存進你自己的資料庫,並在再次呼叫 API 之前先檢查它。這樣,重試的 webhook 或重新執行的工作就不會給同一個人頒發兩份證書。
在真實整合中把它們串起來
典型的接線方式如下:
- 在控制台中設計徽章,每門課程或每個里程碑一個,並記下每個徽章的 ID。
- 在你的系統裡儲存一份從課程到徽章 ID 的對應。
- 學員完成課程時,你的伺服器用其姓名、電子郵件和完成日期呼叫
POST /awards。 - 把回傳的
awardId儲存到對應的完成紀錄上。 - 在你自己的產品裡顯示驗證連結,讓學員不必離開就能看到。
如果你不想寫程式碼,任何能傳送帶有 JSON 內容和自訂標頭的 HTTP 請求的自動化工具,都可以發出同樣的呼叫。把它指向 https://api.badges.ninja/awards,並把表單或試算表的欄位對應到 badgeId、recipient.name、recipient.email 和 issuedOn。
值得了解的方案與限制
所有方案都提供 API;解鎖它不需要額外付費。Free 方案($0)包含 2 個簽發者、5 個徽章、2 個席位、1 個 API 金鑰,以及每年 1,200 份證書。Starter 為每月 $9,Pro 為每月 $29,限額更高。在規劃部署規模之前,請查看價格頁面了解目前的數字。如果你在比較其他平台對 API 存取的收費,Credly alternative 把各家的費用並排列了出來。
接下來去哪裡
- 完整的端點參考位於 API 文件,提供 40 種語言版本。
- 關於驗證與金鑰處理的細節,請參閱驗證指南。
- 關於錯誤碼的詳細說明,請參閱錯誤參考。
- 當一次一個呼叫不夠用時,請使用控制台中的批次頒發:上傳一個 CSV,需要時可以暫停或繼續這次執行。
第一次成功頒發才是最難的部分。此後,剩下的就是把同一個呼叫接入你記錄成就的各個地方。
準備好頒發你的第一份可驗證證書了嗎? 在 badges.ninja 免費開始 —— 視覺化設計器、公開驗證頁面、PDF 證書、Open Badge v2.0 輸出。無需信用卡。
本文章是如何完成的
本部落格的部分文章是在 AI 助理協助下起草,並在發布前由 Badges Ninja 團隊審閱、查證與編輯。所有程式碼範例與價格皆已對照正式產品驗證。如需了解我們的編輯與 AI 流程,請參閱我們的 編輯流程頁面 .

關於作者
Nacho Coll
Founder & Engineer at Badges Ninja
Nacho founded Badges Ninja to make issuing verifiable digital credentials as simple as a single API call — Open Badge v2.0 badges and certificates, minted, hosted, and verifiable without standing up your own issuer infrastructure. Writes about the Open Badges spec, credential verification, and running a credentialing platform serverless on AWS, from the operator side of the wire.

