透過 Badges Ninja REST API 簽發 Open Badges:快速入門

驗證身分、建立簽發者、設計或上傳徽章,再把它頒發給接收者——全部透過 REST 完成。附 JavaScript 與 Python 範例。

Nacho Coll 作者 更新於 15 分鐘閱讀
驗證身分、建立簽發者、設計或上傳徽章,再把它頒發給接收者——全部透過 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”,這樣之後輪替金鑰時你就能分辨它們。

Newly created key revealed once

金鑰只會顯示一次。請立刻把它複製到你的密鑰管理工具或環境變數中。金鑰以 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 個字元修正請求內容;重試同樣的請求還是會失敗
401API 金鑰缺失或錯誤檢查 X-Api-Key 標頭,以及金鑰是否已被撤銷
402額度或方案配額用完升級方案,或等待下一個配額週期
404找不到該徽章檢查你傳入的 badgeId

兩個實用建議。第一,把 400 當作資料問題,並記錄回應內容,因為它會指出出錯的欄位。第二,在你這一側做到冪等:把 awardId 和完成紀錄一起存進你自己的資料庫,並在再次呼叫 API 之前先檢查它。這樣,重試的 webhook 或重新執行的工作就不會給同一個人頒發兩份證書。

在真實整合中把它們串起來

典型的接線方式如下:

  1. 在控制台中設計徽章,每門課程或每個里程碑一個,並記下每個徽章的 ID。
  2. 在你的系統裡儲存一份從課程到徽章 ID 的對應。
  3. 學員完成課程時,你的伺服器用其姓名、電子郵件和完成日期呼叫 POST /awards。
  4. 把回傳的 awardId 儲存到對應的完成紀錄上。
  5. 在你自己的產品裡顯示驗證連結,讓學員不必離開就能看到。

如果你不想寫程式碼,任何能傳送帶有 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 輸出。無需信用卡。

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.

返回部落格

相關文章