I-embed ang Badge Verification sa Website Mo (Walang Iframe, Walang SDK)
Magdagdag ng maliit na JavaScript snippet (o server-side fetch) sa site mo na nag-ve-verify ng kahit anong Open Badge gamit ang public na JSON-LD endpoint. Walang iframe, walang third-party tracker.
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.
Kung nag-iissue ka ng mga credential, darating ang araw na may magtatanong: “paano ko malalaman na totoo ang badge na ito?” Hindi dapat maging sagot ang “magtiwala ka na lang sa PNG.” Nilulutas ito ng Open Badge v2.0 gamit ang public at machine-readable na verification endpoint, at ang paglalagay ng “Verified” widget sa sarili mong site ay mga sampung linya lang ng code — hindi iframe, hindi third-party embed script, at hindi SDK.
Ipinapakita ng post na ito kung paano eksaktong tawagin ang endpoint at i-render ang resulta, sa vanilla JavaScript at sa server gamit ang Node at Python. Tinatalakay rin nito kung ano talaga ang chine-check ng “verification,” kung saan bagay ang endpoint kumpara sa mga human-facing page na ibinibigay na ng badges.ninja sa mga recipient, at ang mga pagkakamaling nagpapa-mukhang tapos na ang verification widget kahit wala naman itong napapatunayan.
Ano ba talaga ang ibig sabihin ng “verified”
Ang Open Badge v2.0 assertion ay isang JSON-LD document na may nakapirming hugis: ang assertion mismo (sino ang nakatanggap, kailan), isang reference sa BadgeClass (ano ito, sino ang nagtatakda ng criteria), at isang reference sa issuer profile (sino ang nagpapatunay). Kapag nag-”verify” ka ng badge, tatlong magkakahiwalay na bagay talaga ang chine-check mo:
- Umiiral ba at nare-resolve ang assertion. Totoo ang award ID, hindi hinulaan o binago.
- Na-revoke ba ito. Puwedeng i-revoke ng issuer ang badge pagkatapos — credential na na-issue nang mali, paglabag sa policy, certification na nag-expire — at dapat itong ipakita ng tamang verifier, hindi lang kumpirmahing may record.
- Buo ba ang chain. Ang mga reference ng assertion sa badge at issuer ay talagang nagre-resolve sa mga totoo at magkatugmang record, hindi sa mga ulilang o hindi magkatugmang ID.
Ang verification widget na tumatawag lang ng URL at chine-check kung 200 ang status ay lubusang nakakaligtaan ang point 2. Nare-resolve pa rin nang maayos ang revoked na assertion — may revocation flag lang ito sa payload. Kung “nag-succeed ba ang request” lang ang chine-check ng widget mo, lalabas na verified ang revoked na credential, na mas masama pa kaysa walang widget.
Ang public na human page vs. ang API endpoint
Bawat award na na-issue sa https://badges.ninja ay may public URL na puwedeng direktang i-share ng mga recipient, at hindi kailangan ng signup para makita ito:

Iyan ang page na ili-link ng karamihan ng recipient mula sa LinkedIn, resume, o email signature — ginawa ito para sa tao, ipinapakita ang badge image, ang issuer, at ang petsa ng pag-issue, at wala itong kailangan mula sa iyo para gumana. Ang API endpoint sa ibaba ay nagbabalik ng parehong assertion bilang structured na JSON-LD, na siyang kailangan mo kapag gumagawa ka ng sarili mong UI at hindi lang nagli-link palabas sa amin.
Ang endpoint
GET https://api.badges.ninja/certify-badge/award/{guid}
Walang auth header na kailangan — sinadya itong public, dahil ang buong punto ng Open Badges ay na kahit sino (employer, recruiter, licensing board) ay makaka-verify ng credential nang walang account. Nasa verification docs ang buong detalye ng contract, kasama ang eksaktong field name sa ibinabalik na assertion.
Ipasa ang GUID ng award, na makukuha mo sa sarili mong issuance records o sa pag-parse ng badges.ninja/awards/<guid> link na ibinahagi sa iyo ng recipient.
Vanilla JS: mag-fetch at mag-render
Ito na ang buong widget. Walang build step, walang npm package, ihulog mo lang diretso sa kahit anong page:
<div id="badge-verify"></div>
<script>
async function renderBadgeVerification(awardId, mountId) {
const el = document.getElementById(mountId);
el.textContent = "Checking badge status";
try {
const res = await fetch(
`https://api.badges.ninja/certify-badge/award/${awardId}`
);
if (!res.ok) {
el.textContent = "Credential not found.";
return;
}
const assertion = await res.json();
// —— revocation check first, a resolvable assertion isn't enough on its own
if (assertion.revoked) {
el.textContent = `Revoked: ${assertion.revocationReason || "no reason given"}`;
return;
}
el.textContent = `Verified, issued ${new Date(assertion.issuedOn).toLocaleDateString()}`;
} catch (err) {
el.textContent = "Verification check failed.";
}
}
renderBadgeVerification("REPLACE_WITH_AWARD_ID", "badge-verify");
</script>
Palitan ang REPLACE_WITH_AWARD_ID ng totoong award GUID. Iyan na ang buong client-side integration: walang iframe boundary na kakalabanin mo sa CSS, at walang third-party script na may dalang sariling analytics o tracking pixel kasabay ng verification check.
Server-side: Node
Kung mas gusto mong mag-verify sa backend mo — halimbawa, bago magpakita ng “Verified Partner” badge sa profile page na kontrolado mo, o bago tumanggap ng credential bilang patunay sa onboarding flow — pareho lang ang fetch, wala lang ang DOM part:
async function verifyAward(awardId) {
const res = await fetch(
`https://api.badges.ninja/certify-badge/award/${awardId}`
);
if (!res.ok) return { verified: false, reason: "not_found" };
const assertion = await res.json();
if (assertion.revoked) {
return { verified: false, reason: assertion.revocationReason || "revoked" };
}
return { verified: true, issuedOn: assertion.issuedOn, badge: assertion.badge };
}
Server-side: Python
import requests
# —— resolve the assertion, then check revocation before trusting it
def verify_award(award_id):
res = requests.get(f"https://api.badges.ninja/certify-badge/award/{award_id}")
if res.status_code != 200:
return {"verified": False, "reason": "not_found"}
assertion = res.json()
if assertion.get("revoked"):
return {"verified": False, "reason": assertion.get("revocationReason", "revoked")}
return {"verified": True, "issued_on": assertion.get("issuedOn"), "badge": assertion.get("badge")}
Parehong itinuturing ng dalawang halimbawa na “not found” ang non-200 response sa halip na mag-throw. Ang sirang o hinulaang award ID ay inaasahang input sa public verification endpoint, hindi exceptional, kaya i-handle ito bilang normal na branch at hindi bilang nahuling error.
Pag-style ng resulta sa halip na mag-embed ng UI ng iba
Dahil ang widget sa itaas ay fetch call lang papunta sa sarili mong DOM, ikaw ang may hawak ng bawat pixel. Karaniwang pattern ang tatlong visual state na diretsong naka-map sa response:
- Verified — green na check kasama ang “Verified” at ang petsa ng pag-issue, naka-style para tumugma sa badge/tag component ng site mo.
- Revoked — muted o pulang state na nagpapakita ng revocation reason sa halip na itago ito. Nakikinabang ang mga recipient at third party sa tapat na “bakit,” hindi sa tahimik na pagkabigo.
- Not found — ituring itong kapareho ng “revoked” sa itsura (huwag mag-render ng pekeng success state), pero iba ang copy, dahil magkaibang sitwasyon ang maling ID at sinadyang revocation para sa nagbabasa ng page.
Wala sa mga ito ang nangangailangan ng component library. Sapat na ang isang switch sa verified / revoked / not_found at tatlong CSS class.
Caching, para hindi mo binabayo ang endpoint
Public at unauthenticated ang verification endpoint, kaya wala ring per-request na credit cost — pero network round trip pa rin ito sa bawat page load kung tatawagin mo sa client-side nang walang caching. Para sa page na pare-parehong badge ang ipinapakita sa bawat bisita (halimbawa, “Verified Partner” badge sa footer), i-cache ang resulta sa server na may maikling TTL — sapat na ang lima hanggang labinlimang minuto, dahil hindi mabilis magbago ang revocation — sa halip na mag-fetch ulit sa bawat request:
const cache = new Map();
async function verifyAwardCached(awardId, ttlMs = 10 * 60 * 1000) {
const hit = cache.get(awardId);
if (hit && Date.now() - hit.at < ttlMs) return hit.result;
const result = await verifyAward(awardId);
cache.set(awardId, { result, at: Date.now() });
return result;
}
Para sa per-visitor widget (recipient na nag-e-embed ng sarili niyang credential sa personal site), laktawan ang cache at tawagin nang fresh sa page load — hindi na mahalaga ang dagdag na request sa ganoong kaliit na scale.
Ano na ang ibinibigay ng badges.ninja sa mga recipient
Bago ka gumawa ng ganap na custom na embed, magandang alamin kung ano na ang available out of the box. Kasama sa public page ng bawat award ang mga ready-made na share at embed snippet na puwedeng kopyahin ng recipient, walang code na kailangan sa panig nila:

Kung ang use case mo ay “hayaang ipakita ng recipient na totoo ang badge niya,” madalas mas simple ang pag-link sa badges.ninja/awards/<guid> page nila kaysa gumawa ng custom widget — iyon ang human page na ipinakita kanina, at hinahawakan na nito ang pagkakaiba ng verified/revoked para sa iyo. Buuin ang custom widget mula sa post na ito kapag kailangan mong i-render ang verification status sa loob ng sarili mong product UI — partner directory, internal audit dashboard, hiring tool na nagche-check ng inaangking certification ng candidate — kung saan hindi tamang UX ang pag-link palabas sa ibang site.
Bakit hindi iframe o vendor widget?
May mga platform na nagbibigay ng snippet gaya ng <iframe src="https://vendor.example.com/verify-widget"> para i-embed ang verification status. Gumagana ito, pero may tunay na kapalit: hindi mo ma-restyle ang laman para tumugma sa site mo (nakadepende ka sa CSS na ipinadala ng vendor), nagdadala ito ng cross-origin document na kailangang tahasang payagan ng Content-Security-Policy mo, at bawat page load ay nagre-request sa iframe host ng third party kahit hindi pinapansin ng bisita ang verification status. Naiiwasan ng two-call fetch widget ang lahat ng tatlo — sarili mong DOM, sarili mong styling, at tumatakbo lang kapag ikaw ang nagpasyang tawagin ito.
Paglalakad sa buong verification chain
Kung gumagawa ka ng mas masinsin kaysa status widget — audit tool na nagche-check ng batch ng mga credential, halimbawa, o compliance report — lakarin ang buong chain at huwag huminto sa assertion. Nagre-reference ang assertion sa isang badge URL (ang BadgeClass: pangalan, deskripsyon, criteria) at ang BadgeClass naman ay nagre-reference sa isang issuer URL (ang org profile). Nire-resolve ng mahigpit na verifier ang lahat ng tatlo at kinukumpirmang magkakatugma ang mga ito — talagang pag-aari ng issuer na inaangkin ang badge, talagang nagre-reference ang assertion sa badge na inaangkin — hindi lang na nagbabalik ng 200 ang top-level assertion. Mas malalim ito kaysa kailangan ng single-credential status widget, pero mabuting alam mong may ganitong hugis kung sakaling itanong ng partner o auditor, “gaano ba kalalim talaga ang verification ninyo?”
Mga karaniwang pagkakamaling dapat iwasan
- HTTP status lang ang chine-check. Gaya ng nabanggit, nare-resolve pa rin ang revoked na assertion. Laging basahin ang
assertion.revoked, huwag ipalagay ang verification mula sa status code lang. - Naka-hardcode ang award ID sa shared component. Kung dapat reusable ang widget sa mga page ng maraming recipient, gawing parameter ang award ID (data attribute, query string, prop), hindi literal na nakabaon sa script.
- Tahimik na nilulunok ang network error. Ang
try/catchna walang nilo-log at pareho ang “not found” na text sa tunay na nawawalang badge ay nagpapahirap sa debugging mamaya. Paghiwalayin ang “nabigo ang network call” at “sabi ng API ay hindi” sa mga error branch mo, kahit sa logs man lang. - Nagve-verify ulit sa bawat render sa client-side app. Kung nasa React o Vue component ang widget na madalas mag-re-render, mag-verify nang isang beses kada mount (o isang beses kada cached TTL window, ayon sa caching section sa itaas), hindi sa bawat re-render.
May credit cost ba ito, at gumagana ba sa free plan?
Wala. Sinadyang nasa labas ng credit system na namamahala sa pag-issue ang verification endpoint — walang gastos sa issuer ang pag-check kung valid ang badge, at hindi kailangang may account, API key, o anumang plan tier ang bisitang tumatawag nito. Totoo ito kahit sa Free, Starter, o Pro plan na-issue ang badge: katangian ng mismong credential ang verification, hindi feature na nakakandado sa subscription ng issuer. Kaya rin ligtas mong mailalagay ang widget na ito sa public-facing page na hindi mahulaan ang traffic (careers page, partner directory) nang hindi nag-aalala sa rate limit na nakatali sa account mo — read-only at public na endpoint ang tinatawag mo, hindi authenticated na API route.
Isang bagay na dapat sabihin nang tahasan: hindi kasama sa assertion JSON na ibinabalik ng endpoint ang raw email address ng recipient. Naka-hash ang recipient email sa backend para hindi ma-scrape ang public verification response para sa personal na contact information — sapat ang makukuha mo para makumpirma ang credential (badge, issuer, mga petsa, revocation status) nang hindi nagiging lead-generation tool ang endpoint para sa sinumang nag-iiterate ng mga award ID.
Handa ka na bang mag-issue ng una mong verifiable credential?
Magsimula nang libre sa badges.ninja — visual designer, public verification page, PDF certificate, Open Badge v2.0 output. Walang credit card na kailangan.
Para sa buong annotated na istruktura ng bawat field sa assertion, tingnan ang JSON-LD field reference. At kung nag-iissue ka ng mga credential nang programmatically at hindi lang nagve-verify, saklaw ng API quickstart ang authentication at ang award-creation call na pinagmumulan ng output ng endpoint na ito.
Paano ginawa ang artikulong ito
Ang ilang artikulo sa blog na ito ay ginagawa gamit ang tulong ng AI assistant, pagkatapos ay sinusuri, tinitiyak ang katumpakan, at ine-edit ng Badges Ninja team bago ilathala. Bawat code sample at presyo ay beripikado laban sa live na produkto. Alamin pa ang tungkol sa aming editorial at AI na proseso sa aming pahina ng editorial process .

Tungkol sa may-akda
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.

