Web Sitenize Rozet Doğrulaması Ekleyin (Iframe Yok, SDK Yok)
Sitenize küçük bir JavaScript kod parçası (veya sunucu tarafı bir fetch) ekleyerek herhangi bir Open Badge'i herkese açık bir JSON-LD uç noktası üzerinden doğrulayın. Iframe yok, üçüncü taraf izleyici yok.
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.
Kimlik bilgileri (credential) düzenliyorsanız, er ya da geç biri soracaktır: “Bu rozetin gerçek olduğunu nereden bileceğim?” Dürüst cevap asla “PNG’ye güvenin” olmamalı. Open Badge v2.0 bunu herkese açık, makine tarafından okunabilir bir doğrulama uç noktasıyla çözer; kendi sitenize bir “Doğrulandı” widget’ı koymak ise yaklaşık on satır kod tutar — iframe yok, üçüncü taraf gömme betiği yok, SDK yok.
Bu yazı, uç noktayı tam olarak nasıl çağıracağınızı ve sonucu nasıl göstereceğinizi; saf JavaScript ile ve sunucuda Node ile Python’da gösteriyor. Ayrıca “doğrulama”nın gerçekte neyi denetlediğini, uç noktanın badges.ninja’nın alıcılara zaten sunduğu insan odaklı sayfaların yanında nereye oturduğunu ve bir doğrulama widget’ını bitmiş gibi gösterip sessizce hiçbir şey kanıtlamayan hataları ele alıyor.
”Doğrulandı” gerçekte ne demek
Open Badge v2.0 assertion’ı, sabit bir yapıya sahip bir JSON-LD belgesidir: assertion’ın kendisi (kim aldı, ne zaman), BadgeClass’a bir referans (ne olduğu, ölçütleri kimin belirlediği) ve düzenleyici profiline bir referans (kim kefil oluyor). Bir rozeti “doğruladığınızda” aslında üç ayrı şeyi kontrol ediyorsunuz:
- Assertion mevcut mu ve çözümlenebiliyor mu. Ödül kimliği gerçek; tahmin edilmiş ya da değiştirilmiş değil.
- İptal edilmiş mi. Bir düzenleyici rozeti sonradan iptal edebilir — yanlışlıkla verilmiş bir kimlik bilgisi, bir politika ihlali, süresi dolmuş bir sertifika — ve doğru çalışan bir doğrulayıcı, yalnızca kaydın var olduğunu onaylamakla kalmayıp bunu da göstermelidir.
- Zincir tutarlı mı. Assertion’ın rozet ve düzenleyici referansları, yetim ya da uyumsuz kimlikler değil, gerçek ve birbiriyle eşleşen kayıtlara çözümleniyor.
Yalnızca bir URL’ye ping atıp 200 durumuna bakan bir doğrulama widget’ı, 2. maddeyi tamamen kaçırır. İptal edilmiş bir assertion yine sorunsuz çözümlenir — yalnızca payload’unda bir iptal bayrağı taşır. Widget’ınız sadece “istek başarılı oldu mu” diye bakıyorsa, iptal edilmiş bir kimlik bilgisi doğrulanmış gibi görünür; bu da hiç widget olmamasından daha kötüdür.
Herkese açık insan sayfası ve API uç noktası
https://badges.ninja üzerinde düzenlenen her ödül, alıcıların doğrudan paylaşabileceği herkese açık bir URL alır; görüntülemek için kayıt gerekmez:

Alıcıların çoğu LinkedIn’den, özgeçmişinden veya e-posta imzasından bu sayfaya bağlantı verir — insanlar için tasarlanmıştır, rozet görselini, düzenleyiciyi ve düzenlenme tarihini gösterir ve çalışması için sizden hiçbir şey gerektirmez. Aşağıdaki API uç noktası aynı temel assertion’ı yapılandırılmış JSON-LD olarak döndürür; yalnızca bizim arayüzümüze bağlantı vermek yerine kendi arayüzünüzü oluşturuyorsanız istediğiniz şey budur.
Uç nokta
GET https://api.badges.ninja/certify-badge/award/{guid}
Kimlik doğrulama başlığı gerekmez — bu bilinçli olarak herkese açıktır, çünkü Open Badges’in bütün amacı herkesin (bir işveren, bir işe alım uzmanı, bir lisans kurulu) hesap açmadan bir kimlik bilgisini doğrulayabilmesidir. Döndürülen assertion’daki kesin alan adları dahil sözleşmenin tüm ayrıntıları doğrulama dokümanlarında yer alıyor.
Ödülün GUID’ini iletin; bunu ya kendi düzenleme kayıtlarınızdan ya da bir alıcının sizinle paylaştığı badges.ninja/awards/<guid> bağlantısından alabilirsiniz.
Saf JS: getir ve göster
Widget’ın tamamı bu. Derleme adımı yok, npm paketi yok; doğrudan herhangi bir sayfaya bırakın:
<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>
REPLACE_WITH_AWARD_ID yerine gerçek bir ödül GUID’i yazın. İstemci tarafı entegrasyonun tamamı bu: CSS ile boğuşacağınız bir iframe sınırı yok ve doğrulama kontrolünün yanında kendi analitiğini veya izleme piksellerini getiren üçüncü taraf bir betik yok.
Sunucu tarafı: Node
Doğrulamayı arka uçta yapmayı tercih ederseniz — örneğin kontrol ettiğiniz bir profil sayfasında “Doğrulanmış Ortak” rozeti göstermeden önce ya da bir katılım (onboarding) akışında bir kimlik bilgisini kanıt olarak kabul etmeden önce — fetch, DOM kısmı hariç aynıdır:
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 };
}
Sunucu tarafı: 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")}
Her iki örnek de 200 dışındaki yanıtı istisna fırlatmak yerine “bulunamadı” olarak ele alır. Herkese açık bir doğrulama uç noktası için bozuk ya da tahmin edilmiş bir ödül kimliği beklenen bir girdidir, istisnai bir durum değildir; bu yüzden onu yakalanmış bir hata olarak değil, normal bir dal olarak işleyin.
Başkasının arayüzünü gömmek yerine sonucu kendiniz biçimlendirin
Yukarıdaki widget kendi DOM’unuza yapılan basit bir fetch çağrısı olduğundan, her pikseli sizin. Yaygın bir kalıp, doğrudan yanıttan türetilen üç görsel durumdur:
- Doğrulandı — yeşil bir onay işareti, “Doğrulandı” ifadesi ve düzenlenme tarihi; sitenizin rozet/etiket bileşenlerine uyacak şekilde biçimlendirilmiş.
- İptal edildi — iptal nedenini gizlemek yerine gösteren, soluk ya da kırmızı bir durum. Hem alıcılar hem üçüncü taraflar, sessiz bir hata yerine dürüst bir “neden”den yararlanır.
- Bulunamadı — görsel olarak “iptal edildi” ile aynı şekilde ele alın (sahte bir başarı durumu göstermeyin) ama farklı bir metinle; çünkü hatalı bir kimlik ile bilinçli bir iptal, sayfayı okuyan kişi için farklı durumlardır.
Bunların hiçbiri bir bileşen kütüphanesi gerektirmez. verified / revoked / not_found üzerinde bir switch ve üç CSS sınıfı yeter.
Uç noktayı yormamak için önbellekleme
Doğrulama uç noktası herkese açık ve kimlik doğrulamasızdır; bu da istek başına kredi maliyeti olmadığı anlamına gelir — ama istemci tarafında önbelleksiz çağırırsanız her sayfa yüklemesinde yine bir ağ gidiş-dönüşüdür. Her ziyaretçiye aynı rozeti gösteren bir sayfada (örneğin altbilgide “Doğrulanmış Ortak” rozeti), sonucu her istekte yeniden çekmek yerine sunucu tarafında kısa bir TTL ile önbelleğe alın — iptaller hızlı değişen bir sinyal olmadığından beş ila on beş dakika fazlasıyla yeterli:
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;
}
Ziyaretçi başına bir widget için (bir alıcının kendi kimlik bilgisini kişisel sitesine gömmesi) önbelleği atlayıp sayfa yüklenirken her seferinde taze çağırın — o ölçekte ek istek ihmal edilebilir.
badges.ninja alıcılara zaten neler sunuyor
Tamamen özel bir gömme çözümü kurmadan önce, hazır neyin mevcut olduğunu bilmekte fayda var. Her ödülün herkese açık sayfası, alıcıların kendi taraflarında hiç kod yazmadan doğrudan kopyalayabileceği hazır paylaşım ve gömme kod parçaları içerir:

Kullanım senaryonuz “alıcının rozetinin gerçek olduğunu göstermesine izin vermek” ise, onun badges.ninja/awards/<guid> sayfasına bağlantı vermek çoğu zaman özel bir widget kurmaktan daha basittir — bu, daha önce gösterilen insan sayfasıdır ve doğrulandı/iptal edildi ayrımını zaten sizin yerinize halleder. Bu yazıdaki özel widget’ı, doğrulama durumunun kendi ürününüzün arayüzünün içinde gösterilmesi gerektiğinde kurun — bir ortak dizini, bir dahili denetim paneli, bir adayın beyan ettiği sertifikaları kontrol eden bir işe alım aracı — çünkü başka bir siteye yönlendirmek doğru kullanıcı deneyimi değildir.
Neden iframe veya satıcı widget’ı değil?
Bazı platformlar doğrulama durumunu gömmeniz için <iframe src="https://vendor.example.com/verify-widget"> gibi bir kod parçası verir. Çalışır, ama gerçek maliyetleri vardır: içeriği sitenize uyacak şekilde yeniden biçimlendiremezsiniz (satıcının getirdiği CSS’e mahkûm olursunuz), Content-Security-Policy’nizin açıkça izin vermesi gereken çapraz kaynaklı bir belge ekler ve ziyaretçi doğrulama durumunu umursasa da umursamasa da her sayfa yüklemesi üçüncü bir tarafın iframe sunucusuna istek gönderir. İki çağrılık bir fetch widget’ı üçünü de önler — DOM sizin, biçimlendirme sizin ve yalnızca siz çağırmaya karar verdiğinizde çalışır.
Tüm doğrulama zincirini izlemek
Bir durum widget’ından daha kapsamlı bir şey kuruyorsanız — örneğin bir grup kimlik bilgisini kontrol eden bir denetim aracı veya bir uyumluluk raporu — assertion’da durmak yerine zincirin tamamını izleyin. Assertion bir badge URL’sine (BadgeClass: ad, açıklama, ölçütler) referans verir ve BadgeClass da kendi içinde bir issuer URL’sine (kurum profili) referans verir. Titiz bir doğrulayıcı üçünü de çözümler ve tutarlı olduklarını doğrular — rozet gerçekten iddia ettiği düzenleyiciye ait, assertion gerçekten iddia ettiği rozete referans veriyor — yalnızca en üstteki assertion’ın 200 döndürdüğünü değil. Bu, tek bir kimlik bilgisi için durum widget’ının ihtiyaç duyduğundan daha fazla derinliktir, ancak bir ortak ya da denetçi “doğrulamanız gerçekte ne kadar derine iniyor?” diye sorarsa, bu yapının var olduğunu bilmekte fayda var.
Kaçınmanız gereken yaygın hatalar
- Yalnızca HTTP durumuna bakmak. Yukarıda ele alındığı gibi, iptal edilmiş bir assertion yine çözümlenir. Her zaman
assertion.revokeddeğerini okuyun; doğrulamayı yalnızca durum kodundan çıkarmayın. - Ortak bir bileşende ödül kimliğini koda gömmek. Widget birçok alıcının sayfasında yeniden kullanılacaksa, ödül kimliğini betiğe gömülü bir sabit olarak değil, bir parametre (data özniteliği, sorgu dizesi, prop) olarak alın.
- Ağ hatalarını sessizce yutmak. Hiçbir şey kaydetmeyen ve gerçekten eksik bir rozetle aynı “bulunamadı” metnini gösteren bir
try/catch, ileride hata ayıklamayı zorlaştırır. Hata dallarınızda, en azından günlüklerde, “ağ çağrısı başarısız oldu” ile “API hayır dedi” arasında ayrım yapın. - İstemci uygulamasında her render’da yeniden doğrulamak. Widget sık yeniden render olan bir React veya Vue bileşeninin içinde yaşıyorsa, her yeniden render’da değil, mount başına bir kez (veya yukarıdaki önbellekleme bölümündeki gibi önbellek TTL penceresi başına bir kez) doğrulayın.
Kredi harcar mı ve ücretsiz planda çalışır mı?
Hayır. Doğrulama uç noktası, düzenlemeyi yöneten kredi sisteminin bilinçli olarak dışındadır — bir rozetin geçerli olup olmadığını kontrol etmek düzenleyiciye hiçbir şeye mal olmaz ve çağıran ziyaretçinin hesap, API anahtarı ya da herhangi bir plan katmanına sahip olmasını gerektirmez. Bu, rozetin Free, Starter veya Pro planında düzenlenmiş olmasından bağımsız olarak geçerlidir: doğrulama, kimlik bilgisinin kendi özelliğidir; düzenleyicinin aboneliğine bağlı bir özellik değil. Bu yüzden bu widget’ı, trafiği öngörülemeyen herkese açık bir sayfaya (kariyer sayfası, ortak dizini) hesabınıza bağlı hız sınırları konusunda endişelenmeden güvenle koyabilirsiniz — kimlik doğrulamalı bir API rotasını değil, salt okunur, herkese açık bir uç noktayı çağırıyorsunuz.
Açıkça belirtmekte fayda var: uç noktanın döndürdüğü assertion JSON’u, alıcının ham e-posta adresini içermez. Alıcı e-postası arka uçta karma (hash) olarak saklanır; tam da herkese açık bir doğrulama yanıtından kişisel iletişim bilgisi kazınamasın diye — geri aldığınız şey, kimlik bilgisini doğrulamaya yeter (rozet, düzenleyici, tarihler, iptal durumu), ama uç noktayı ödül kimlikleri üzerinde dolaşan herkes için bir müşteri adayı toplama aracına dönüştürmez.
İlk doğrulanabilir kimlik bilginizi düzenlemeye hazır mısınız?
badges.ninja’da ücretsiz başlayın — görsel tasarımcı, herkese açık doğrulama sayfası, PDF sertifika, Open Badge v2.0 çıktısı. Kredi kartı gerekmez.
Bir assertion’daki her alanın tam açıklamalı yapısı için JSON-LD alan başvurusuna bakın. Kimlik bilgilerini yalnızca doğrulamak yerine programatik olarak düzenliyorsanız, API hızlı başlangıç kılavuzu bu uç noktanın çıktısının geldiği kimlik doğrulamayı ve ödül oluşturma çağrısını kapsar.
Bu yazı nasıl hazırlandı
Bu blogdaki bazı yazılar bir yapay zeka asistanının yardımıyla hazırlanır, ardından yayınlanmadan önce Badges Ninja ekibi tarafından incelenir, doğrulanır ve düzenlenir. Her kod örneği ve fiyat, canlı ürünle karşılaştırılarak doğrulanır. Editoryal ve yapay zeka sürecimiz hakkında daha fazla bilgiyi editoryal süreç sayfamızda bulabilirsiniz .

Yazar hakkında
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.

