Insereix la verificació d’insígnies al teu web (sense iframe ni SDK)
Afegeix un petit fragment de JavaScript (o una crida des del servidor) al teu web que verifiqui qualsevol Open Badge amb un endpoint JSON-LD públic. Sense iframe ni rastrejadors de tercers.
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.
Si emets credencials, tard o d’hora algú et preguntarà: «Com sé que aquesta insígnia és real?». La resposta honesta mai no hauria de ser «fia’t del PNG». Open Badge v2.0 ho resol amb un endpoint de verificació públic i llegible per màquines, i posar un giny de «Verificada» al teu web són unes deu línies de codi: ni un iframe, ni un script d’incrustació de tercers, ni un SDK.
Aquest article mostra exactament com cridar l’endpoint i mostrar el resultat, amb JavaScript pur i al servidor amb Node i Python. També explica què comprova realment la «verificació», on encaixa l’endpoint al costat de les pàgines per a persones que badges.ninja ja ofereix als destinataris, i els errors que fan que un giny de verificació sembli acabat mentre no demostra res.
Què vol dir realment «verificada»
Una asserció d’Open Badge v2.0 és un document JSON-LD amb una forma fixa: la mateixa asserció (qui l’ha rebuda, quan), una referència a la BadgeClass (què és, qui en defineix els criteris) i una referència al perfil de l’emissor (qui l’avala). Quan «verifiques» una insígnia, en realitat comproves tres coses diferents:
- Que l’asserció existeix i es resol. L’ID del lliurament és real, no inventat ni manipulat.
- Que no ha estat revocada. Un emissor pot revocar una insígnia a posteriori —una credencial emesa per error, una infracció de normativa, una certificació caducada— i un verificador correcte ho ha de mostrar, no només confirmar que el registre existeix.
- Que la cadena és coherent. Les referències de l’asserció a la insígnia i a l’emissor es resolen en registres reals i coincidents, no en IDs orfes o que no concorden.
Un giny de verificació que només fa ping a una URL i comprova l’estat 200 es deixa el punt 2 totalment. Una asserció revocada es resol perfectament: simplement porta un indicador de revocació a la càrrega. Si el teu giny només comprova «la petició ha anat bé», una credencial revocada es mostrarà com a verificada, cosa pitjor que no tenir cap giny.
La pàgina pública per a persones vs. l’endpoint de l’API
Cada lliurament emès a https://badges.ninja obté una URL pública que els destinataris poden compartir directament, sense necessitat de registrar-se per veure-la:

Aquesta és la pàgina que la majoria de destinataris enllaçaran des de LinkedIn, un currículum o una signatura de correu: està pensada per a persones, mostra la imatge de la insígnia, l’emissor i la data d’emissió, i no necessita res de tu per funcionar. L’endpoint de l’API següent retorna la mateixa asserció com a JSON-LD estructurat, que és el que et convé quan construeixes la teva pròpia interfície en lloc de limitar-te a enllaçar la nostra.
L’endpoint
GET https://api.badges.ninja/certify-badge/award/{guid}
No cal capçalera d’autenticació: és públic a propòsit, perquè tot el sentit d’Open Badges és que qualsevol persona (una empresa, un reclutador, un col·legi professional) pugui verificar una credencial sense compte. Els detalls complets del contracte, amb els noms exactes dels camps de l’asserció retornada, són a la documentació de verificació.
Passa-li el GUID del lliurament, que tindràs als teus registres d’emissió o que podràs extreure d’un enllaç badges.ninja/awards/<guid> que t’hagi compartit un destinatari.
JS pur: obtenir i mostrar
Aquest és tot el giny. Sense pas de compilació, sense paquet npm; el pots posar directament a qualsevol pàgina:
<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>
Canvia REPLACE_WITH_AWARD_ID pel GUID d’un lliurament real. Aquesta és tota la integració al client: sense frontera d’iframe contra la qual lluitar amb el CSS, i sense cap script de tercers que hi afegeixi la seva analítica o píxels de seguiment al costat de la comprovació.
Al servidor: Node
Si prefereixes verificar al backend —per exemple, abans de mostrar una insígnia de «Soci verificat» en una pàgina de perfil que controles, o abans d’acceptar una credencial com a prova en un flux d’incorporació—, la crida és idèntica sense la part del DOM:
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 };
}
Al servidor: 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")}
Tots dos exemples tracten una resposta que no sigui 200 com a «no trobada» en lloc de llançar una excepció. Un ID de lliurament trencat o inventat és una entrada esperable en un endpoint de verificació públic, no una excepció, així que tracta’l com una branca normal en lloc d’un error capturat.
Dona estil al resultat en lloc d’incrustar la interfície d’altri
Com que el giny anterior és només una crida fetch cap al teu propi DOM, cada píxel és teu. Un patró habitual són tres estats visuals derivats directament de la resposta:
- Verificada: una marca verda amb «Verificada» i la data d’emissió, amb l’estil dels components d’insígnia o etiqueta del teu web.
- Revocada: un estat apagat o vermell que mostra el motiu de la revocació en lloc d’amagar-lo. Tant els destinataris com els tercers agraeixen un «per què» honest, no un error silenciós.
- No trobada: tracta-la visualment igual que «revocada» (no mostris un fals estat d’èxit), però amb un text diferent, ja que un ID incorrecte i una revocació deliberada són situacions diferents per a qui llegeix la pàgina.
Res d’això requereix una biblioteca de components. Un switch sobre verified / revoked / not_found i tres classes CSS ho cobreixen.
Memòria cau, perquè no martelleges l’endpoint
L’endpoint de verificació és públic i sense autenticació, cosa que també vol dir que no hi ha cap cost de crèdits per petició, però continua sent un viatge de xarxa a cada càrrega de pàgina si el crides des del client sense memòria cau. En una pàgina que mostra la mateixa insígnia a tots els visitants (una insígnia de «Soci verificat» al peu, per exemple), desa el resultat al servidor amb un TTL curt —cinc a quinze minuts van sobrats, perquè les revocacions no són un senyal que canviï de pressa— en lloc de tornar-lo a demanar a cada petició:
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;
}
Per a un giny per visitant (un destinatari que incrusta la seva pròpia credencial en un web personal), salta’t la memòria cau i crida’l de nou a cada càrrega de pàgina: la petició addicional és insignificant a aquesta escala.
Què ja ofereix badges.ninja als destinataris
Abans de construir una incrustació totalment a mida, val la pena saber què hi ha ja disponible de sèrie. La pàgina pública de cada lliurament inclou fragments per compartir i incrustar que els destinataris poden copiar directament, sense escriure codi:

Si el teu cas és «deixar que un destinatari mostri que la seva insígnia és real», enllaçar la seva pàgina badges.ninja/awards/<guid> sol ser més senzill que construir un giny a mida: és la pàgina per a persones que hem vist abans, i ja gestiona per tu la distinció entre verificada i revocada. Construeix el giny a mida d’aquest article quan necessitis mostrar l’estat de verificació dins la interfície del teu propi producte —un directori de socis, un tauler d’auditoria intern, una eina de selecció que comprova les certificacions declarades d’un candidat—, on enllaçar cap a un altre web no és la millor experiència d’usuari.
Per què no un iframe o un giny d’un proveïdor?
Algunes plataformes et donen un fragment com <iframe src="https://vendor.example.com/verify-widget"> per incrustar l’estat de verificació. Funciona, però té costos reals: no pots reestilitzar-ne el contingut perquè combini amb el teu web (et quedes amb el CSS que hagi enviat el proveïdor), introdueix un document d’origen creuat que la teva Content-Security-Policy ha de permetre explícitament, i cada càrrega de pàgina fa una petició a l’amfitrió de l’iframe d’un tercer tant si al visitant li importa l’estat de verificació com si no. Un giny de dues crides amb fetch evita les tres coses: és el teu DOM, el teu estil, i només s’executa quan tu decideixes cridar-lo.
Recórrer tota la cadena de verificació
Si construeixes alguna cosa més completa que un giny d’estat —una eina d’auditoria que comprova un lot de credencials, per exemple, o un informe de compliment—, recorre tota la cadena en lloc d’aturar-te a l’asserció. L’asserció referencia una URL badge (la BadgeClass: nom, descripció, criteris) i la BadgeClass, al seu torn, referencia una URL issuer (el perfil de l’organització). Un verificador rigorós resol les tres i confirma que són coherents entre si —la insígnia pertany realment a l’emissor que diu, l’asserció referencia realment la insígnia que diu—, no només que l’asserció de nivell superior retorni un 200. És més profunditat de la que necessita un giny de credencial única, però convé saber que existeix per si un soci o un auditor et pregunta algun dia: «fins a quin punt arriba realment la vostra verificació?».
Errors habituals que cal evitar
- Comprovar només l’estat HTTP. Com s’ha vist, una asserció revocada es resol igualment. Llegeix sempre
assertion.revoked; no dedueixis la verificació només del codi d’estat. - Fixar l’ID del lliurament en un component compartit. Si el giny ha de ser reutilitzable a les pàgines de molts destinataris, rep l’ID del lliurament com a paràmetre (un atribut data, una query string, una prop), no com un literal incrustat a l’script.
- Empassar-se els errors de xarxa en silenci. Un
try/catchque no registra res i mostra el mateix text de «no trobada» que per a una insígnia realment inexistent fa que depurar després sigui penós. Distingeix entre «la crida de xarxa ha fallat» i «l’API ha dit que no» a les teves branques d’error, almenys als registres. - Reverificar a cada renderització en una aplicació de client. Si el giny viu dins d’un component de React o Vue que es renderitza sovint, verifica una vegada per muntatge (o una vegada per finestra de TTL de la memòria cau, segons la secció anterior), no a cada nova renderització.
Costa crèdits i funciona al pla gratuït?
No. L’endpoint de verificació és deliberadament fora del sistema de crèdits que regeix l’emissió: comprovar si una insígnia és vàlida no costa res a l’emissor, i no cal que el visitant que el crida tingui compte, clau d’API ni cap nivell de pla. Això val tant si la insígnia es va emetre en un pla Free, Starter o Pro: la verificació és una propietat de la credencial mateixa, no una funcionalitat limitada per la subscripció de l’emissor. També és per això que pots posar aquest giny amb tota tranquil·litat en una pàgina pública amb trànsit imprevisible (una pàgina de feina, un directori de socis) sense preocupar-te per límits de taxa lligats al teu compte: crides un endpoint públic de només lectura, no una ruta d’API autenticada.
Una cosa que val la pena dir explícitament: l’asserció JSON que retorna l’endpoint no inclou l’adreça electrònica en clar del destinatari. El correu del destinatari es desa xifrat amb hash al backend precisament perquè una resposta de verificació pública no es pugui rastrejar per obtenir dades de contacte personals: el que reps és suficient per confirmar la credencial (insígnia, emissor, dates, estat de revocació) sense convertir l’endpoint en una eina de captació de contactes per a qualsevol que iteri sobre IDs de lliuraments.
Preparat per emetre la teva primera credencial verificable?
Comença gratis a badges.ninja: dissenyador visual, pàgina de verificació pública, certificat en PDF, sortida Open Badge v2.0. Sense targeta de crèdit.
Per a l’estructura anotada completa de cada camp d’una asserció, consulta la referència de camps JSON-LD. I si emets credencials per programa en lloc de només verificar-les, la guia ràpida de l’API explica l’autenticació i la crida de creació de lliuraments d’on surt el resultat d’aquest endpoint.
Com es va fer aquest article
Alguns articles d'aquest blog es redacten amb l'ajuda d'un assistent d'IA i després són revisats, verificats i editats per l'equip de Badges Ninja abans de publicar-los. Cada mostra de codi i preu es verifica amb el producte real. Llegeix més sobre el nostre procés editorial i d'IA a la nostra pàgina del procés editorial .

Sobre l'autor
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.
Més de Nacho Coll
- Salesforce Open Badges: emet credencials verificables des de desencadenants del CRM1 d’oct. del 2026 · 10min de lectura
- Emet insígnies Open Badges amb l'API REST de Badges Ninja: guia d'inici ràpid28 de set. del 2026 · 10min de lectura
- Certifier vs Accredible: comparativa de plataformes de certificats (2026)21 de set. del 2026 · 10min de lectura

