Ugradite provjeru znački na svoju web-stranicu (bez iframea i SDK-a)
Dodajte na svoju stranicu mali JavaScript isječak (ili dohvat sa servera) koji provjerava bilo koji Open Badge putem javnog JSON-LD endpointa. Bez iframea, bez vanjskih trackera.
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.
Ako izdajete vjerodajnice, prije ili kasnije netko će pitati: „Kako znam da je ova značka stvarna?” Iskren odgovor nikad ne smije biti „vjerujte PNG-u”. Open Badge v2.0 to rješava javnim endpointom za provjeru čitljivim strojevima, a widget „Provjereno” na vašoj stranici traži desetak redaka koda: bez iframea, bez vanjske skripte za ugradnju i bez SDK-a.
Ovaj članak pokazuje kako točno pozvati endpoint i prikazati rezultat, u čistom JavaScriptu te na serveru u Nodeu i Pythonu. Obrađuje i što „provjera” zapravo provjerava, gdje se endpoint uklapa uz stranice za ljude koje badges.ninja već daje primateljima, te pogreške zbog kojih widget za provjeru izgleda gotovo, a da zapravo ništa ne dokazuje.
Što „provjereno” zapravo znači
Tvrdnja (assertion) u Open Badge v2.0 JSON-LD je dokument fiksnog oblika: sama tvrdnja (tko ju je primio, kada), referenca na BadgeClass (što je to, tko definira kriterije) i referenca na profil izdavatelja (tko jamči za nju). Kad „provjeravate” značku, zapravo provjeravate tri odvojene stvari:
- Postoji li tvrdnja i razrješava li se. ID dodjele je stvaran, nije pogođen niti krivotvoren.
- Je li opozvana. Izdavatelj može naknadno opozvati značku — vjerodajnica izdana greškom, kršenje pravila, istekla certifikacija — a ispravan provjeravatelj to mora prikazati, a ne samo potvrditi da zapis postoji.
- Drži li se lanac na okupu. Reference tvrdnje na značku i izdavatelja razrješavaju se u stvarne zapise koji se podudaraju, a ne u osamljene ili neusklađene ID-ove.
Widget za provjeru koji samo pinga URL i provjerava status 200 potpuno propušta točku 2. Opozvana tvrdnja se i dalje normalno razrješava — samo u sadržaju nosi zastavicu opoziva. Ako vaš widget provjerava samo „je li zahtjev uspio”, opozvana vjerodajnica prikazat će se kao provjerena, što je gore nego da widgeta uopće nema.
Javna stranica za ljude naspram API endpointa
Svaka dodjela izdana na https://badges.ninja dobiva javni URL koji primatelji mogu izravno dijeliti, bez prijave za pregled:

Na tu stranicu većina primatelja povezat će se s LinkedIna, životopisa ili potpisa e-pošte — napravljena je za ljude, prikazuje sliku značke, izdavatelja i datum izdavanja te od vas ne traži ništa da bi radila. API endpoint u nastavku vraća istu tvrdnju kao strukturirani JSON-LD, što vam treba kad gradite vlastito sučelje umjesto da samo povezujete na naše.
Endpoint
GET https://api.badges.ninja/certify-badge/award/{guid}
Zaglavlje za autentikaciju nije potrebno — namjerno je javan, jer je cijela poanta Open Badgesa da bilo tko (poslodavac, selektor, stručna komora) može provjeriti vjerodajnicu bez računa. Potpuni detalji ugovora, uključujući točne nazive polja u vraćenoj tvrdnji, nalaze se u dokumentaciji provjere.
Proslijedite GUID dodjele, koji imate iz vlastitih evidencija izdavanja ili ga možete izvući iz poveznice badges.ninja/awards/<guid> koju je s vama podijelio primatelj.
Čisti JS: dohvat i prikaz
Ovo je cijeli widget. Bez koraka izgradnje, bez npm paketa, ubacite ga izravno na bilo koju stranicu:
<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>
Zamijenite REPLACE_WITH_AWARD_ID stvarnim GUID-om dodjele. To je cijela integracija na klijentu: nema granice iframea s kojom se treba boriti u CSS-u, niti vanjske skripte koja uz provjeru povlači vlastitu analitiku ili tracking piksele.
Na serveru: Node
Ako radije provjeravate na backendu — recimo, prije prikaza značke „Provjereni partner” na profilnoj stranici koju kontrolirate ili prije prihvaćanja vjerodajnice kao dokaza u procesu uvođenja — dohvat je isti, samo bez DOM dijela:
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 };
}
Na serveru: 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")}
Oba primjera odgovor koji nije 200 tretiraju kao „nije pronađeno” umjesto da bacaju iznimku. Neispravan ili pogođen ID dodjele očekivan je ulaz za javni endpoint provjere, a ne iznimna situacija, pa ga obradite kao običnu granu, a ne kao uhvaćenu pogrešku.
Stiliziranje rezultata umjesto ugradnje tuđeg sučelja
Budući da je widget iznad samo fetch poziv prema vašem vlastitom DOM-u, svaki piksel je vaš. Uobičajen obrazac su tri vizualna stanja izravno preslikana iz odgovora:
- Provjereno — zelena kvačica uz „Provjereno” i datum izdavanja, stilizirana prema komponentama značaka/oznaka na vašoj stranici.
- Opozvano — prigušeno ili crveno stanje koje prikazuje razlog opoziva umjesto da ga skriva. I primatelji i treće strane cijene iskreno „zašto”, a ne tihu grešku.
- Nije pronađeno — vizualno ga tretirajte jednako kao „opozvano” (ne prikazujte lažno stanje uspjeha), ali s drugačijim tekstom, jer su pogrešan ID i namjeran opoziv različite situacije za onoga tko čita stranicu.
Ništa od ovoga ne traži biblioteku komponenti. Dovoljni su switch nad verified / revoked / not_found i tri CSS klase.
Predmemorija, da ne bombardirate endpoint
Endpoint provjere je javan i bez autentikacije, što znači i da nema troška kredita po zahtjevu, ali je i dalje mrežni poziv pri svakom učitavanju stranice ako ga zovete s klijenta bez predmemorije. Za stranicu koja svim posjetiteljima prikazuje istu značku (npr. značka „Provjereni partner” u podnožju) spremite rezultat na serveru s kratkim TTL-om — pet do petnaest minuta sasvim je dovoljno jer opozivi nisu signal koji se brzo mijenja — umjesto da ga dohvaćate pri svakom zahtjevu:
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;
}
Za widget po posjetitelju (primatelj koji ugrađuje vlastitu vjerodajnicu na osobnu stranicu) preskočite predmemoriju i pozovite ga svježe pri učitavanju stranice — dodatni zahtjev je na toj razini zanemariv.
Što badges.ninja primateljima već nudi
Prije nego što izgradite potpuno prilagođenu ugradnju, vrijedi znati što je već dostupno odmah. Javna stranica svake dodjele uključuje gotove isječke za dijeljenje i ugradnju koje primatelji mogu izravno kopirati, bez ikakvog koda s njihove strane:

Ako je vaš slučaj „neka primatelj pokaže da je njegova značka stvarna”, povezivanje na njegovu stranicu badges.ninja/awards/<guid> često je jednostavnije od izrade prilagođenog widgeta — to je ranije prikazana stranica za ljude i već umjesto vas razlikuje provjereno od opozvanog. Prilagođeni widget iz ovog članka izgradite kad status provjere trebate prikazati unutar sučelja vlastitog proizvoda — imenika partnera, internog audit dashboarda, alata za zapošljavanje koji provjerava kandidatove navedene certifikate — gdje povezivanje na drugu stranicu nije pravo korisničko iskustvo.
Zašto ne iframe ili widget dobavljača?
Neke platforme daju vam isječak poput <iframe src="https://vendor.example.com/verify-widget"> za ugradnju statusa provjere. Radi, ali ima stvarne troškove: ne možete restilizirati sadržaj da odgovara vašoj stranici (zaglavite s CSS-om koji je dobavljač isporučio), uvodi dokument s drugog podrijetla koji vaša Content-Security-Policy mora izričito dopustiti, a svako učitavanje stranice šalje zahtjev hostu iframea treće strane, bez obzira zanima li posjetitelja uopće status provjere. Widget s dva poziva putem fetcha izbjegava sva tri problema — vaš je DOM, vaš je stil i izvodi se samo kad vi odlučite pozvati ga.
Prolazak cijelim lancem provjere
Ako gradite nešto temeljitije od statusnog widgeta — alat za reviziju koji provjerava skup vjerodajnica, recimo, ili izvještaj o usklađenosti — prođite cijeli lanac umjesto da stanete na tvrdnji. Tvrdnja referencira URL badge (BadgeClass: naziv, opis, kriteriji), a BadgeClass pak referencira URL issuer (profil organizacije). Rigorozan provjeravatelj razrješava sva tri i potvrđuje da su međusobno dosljedna — značka stvarno pripada izdavatelju kojem tvrdi da pripada, tvrdnja stvarno referencira značku koju tvrdi — a ne samo da tvrdnja najviše razine vraća 200. To je dublje nego što treba widgetu za jednu vjerodajnicu, ali vrijedi znati da takav oblik postoji ako vas partner ili revizor ikad upita „koliko duboko vaša provjera zapravo ide?”
Česte pogreške koje treba izbjeći
- Provjera samo HTTP statusa. Kako je rečeno, opozvana tvrdnja se i dalje razrješava. Uvijek čitajte
assertion.revoked, ne zaključujte o provjeri samo iz status koda. - Fiksiranje ID-a dodjele u dijeljenoj komponenti. Ako widget treba biti višekratan na stranicama mnogih primatelja, ID dodjele primite kao parametar (data atribut, query string, prop), a ne kao literal upečen u skriptu.
- Tiho gutanje mrežnih pogrešaka.
try/catchkoji ništa ne bilježi i prikazuje isti tekst „nije pronađeno” kao za stvarno nepostojeću značku kasnije otežava otklanjanje pogrešaka. Razlikujte „mrežni poziv nije uspio” od „API je rekao ne” u svojim granama za pogreške, barem u zapisima. - Ponovna provjera pri svakom renderiranju u klijentskoj aplikaciji. Ako widget živi unutar React ili Vue komponente koja se često ponovno renderira, provjeru obavite jednom po mountu (ili jednom po TTL prozoru predmemorije, prema odjeljku o predmemoriji), a ne pri svakom renderiranju.
Košta li to kredite i radi li na besplatnom planu?
Ne. Endpoint provjere namjerno je izvan sustava kredita koji uređuje izdavanje — provjera vrijedi li značka ne košta izdavatelja ništa, a posjetitelj koji ga poziva ne treba račun, API ključ ni bilo koju razinu plana. To vrijedi bez obzira je li značka izdana na planu Free, Starter ili Pro: provjera je svojstvo same vjerodajnice, a ne značajka ograničena pretplatom izdavatelja. Zato ovaj widget možete mirno staviti na javnu stranicu s nepredvidivim prometom (stranica o karijerama, imenik partnera) bez brige o ograničenjima brzine vezanima uz vaš račun — pozivate javni endpoint samo za čitanje, a ne autentificiranu API rutu.
Jedna stvar koju vrijedi izričito naglasiti: JSON tvrdnje koji vraća endpoint ne sadrži primateljevu izvornu adresu e-pošte. E-pošta primatelja pohranjuje se hashirana na backendu upravo kako se iz javnog odgovora provjere ne bi mogli strugati osobni kontakt podaci — ono što dobivate dovoljno je za potvrdu vjerodajnice (značka, izdavatelj, datumi, status opoziva), a da endpoint ne postane alat za prikupljanje kontakata za svakoga tko prolazi kroz ID-ove dodjela.
Spremni izdati svoju prvu provjerljivu vjerodajnicu?
Počnite besplatno na badges.ninja — vizualni dizajner, javna stranica za provjeru, PDF certifikat, izlaz u Open Badge v2.0. Kreditna kartica nije potrebna.
Za potpunu komentiranu strukturu svakog polja tvrdnje pogledajte referencu JSON-LD polja. A ako vjerodajnice izdajete programski, a ne samo provjeravate, brzi vodič za API pokriva autentikaciju i poziv za stvaranje dodjele iz kojeg dolazi izlaz ovog endpointa.
Kako je nastao ovaj članak
Neki članci na ovom blogu nastaju uz pomoć AI asistenta, a zatim ih pregledava, provjerava i uređuje tim Badges Ninja prije objave. Svaki isječak koda i cijena provjereni su na stvarnom proizvodu. Više o našem uredničkom i AI procesu pročitajte na našoj stranici uredničkog procesa .

O autoru
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.

