Incorpora a verificação de emblemas no teu site (sem iframe, sem SDK)
Adiciona ao teu site um pequeno snippet de JavaScript (ou um fetch no servidor) que verifica qualquer Open Badge através de um endpoint JSON-LD público. Sem iframe, sem rastreadores de terceiros.
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.
Se emites credenciais, mais cedo ou mais tarde alguém pergunta: «como sei que este emblema é verdadeiro?» A resposta honesta nunca deve ser «confia no PNG». O Open Badge v2.0 resolve isto com um endpoint de verificação público e legível por máquinas, e colocar um widget de «Verificado» no teu próprio site dá cerca de dez linhas de código — sem iframe, sem script de incorporação de terceiros e sem SDK.
Este artigo mostra exatamente como chamar o endpoint e apresentar o resultado, em JavaScript puro e no servidor, em Node e Python. Explica também o que a «verificação» realmente confirma, onde o endpoint se encaixa ao lado das páginas para pessoas que o badges.ninja já oferece aos destinatários, e os erros que fazem um widget de verificação parecer concluído quando, na prática, não prova nada.
O que significa realmente «verificado»
Uma asserção Open Badge v2.0 é um documento JSON-LD com uma estrutura fixa: a própria asserção (quem a recebeu, quando), uma referência à BadgeClass (o que é, quem define os critérios) e uma referência ao perfil do emissor (quem a garante). Quando «verificas» um emblema, estás na verdade a confirmar três coisas distintas:
- A asserção existe e é resolvida. O ID da atribuição é real, não foi inventado nem adulterado.
- Foi revogada? Um emissor pode revogar um emblema depois de o atribuir — uma credencial emitida por engano, uma violação de política, uma certificação que expirou — e um verificador correto tem de o indicar, e não apenas confirmar que o registo existe.
- A cadeia é coerente. As referências da asserção ao emblema e ao emissor resolvem para registos reais e coincidentes, não para IDs órfãos ou incompatíveis.
Um widget de verificação que apenas contacta um URL e verifica se o estado é 200 ignora por completo o ponto 2. Uma asserção revogada continua a ser resolvida sem problemas — apenas traz uma indicação de revogação no payload. Se o teu widget só verifica «o pedido teve sucesso», uma credencial revogada será apresentada como verificada, o que é pior do que não ter widget nenhum.
A página pública para pessoas vs. o endpoint da API
Cada atribuição emitida em https://badges.ninja tem um URL público que os destinatários podem partilhar diretamente, sem necessidade de registo para o ver:

Essa página é a que a maioria dos destinatários vai ligar a partir do LinkedIn, de um currículo ou de uma assinatura de email — foi pensada para pessoas, mostra a imagem do emblema, o emissor e a data de emissão, e não precisa de nada da tua parte para funcionar. O endpoint da API abaixo devolve a mesma asserção como JSON-LD estruturado, que é o que queres quando estás a construir a tua própria interface em vez de apenas apontar para a nossa.
O endpoint
GET https://api.badges.ninja/certify-badge/award/{guid}
Não é necessário cabeçalho de autenticação — é público de propósito, porque todo o objetivo dos Open Badges é que qualquer pessoa (um empregador, um recrutador, uma ordem profissional) possa verificar uma credencial sem ter conta. Os detalhes completos do contrato, incluindo os nomes exatos dos campos da asserção devolvida, estão na documentação de verificação.
Passa o GUID da atribuição, que terás nos teus próprios registos de emissão ou extraído de uma ligação badges.ninja/awards/<guid> que um destinatário partilhou contigo.
JS puro: fetch e apresentação
Este é o widget completo. Sem passo de build, sem pacote npm, basta colá-lo em qualquer 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>
Troca REPLACE_WITH_AWARD_ID por um GUID de atribuição real. É toda a integração do lado do cliente: sem fronteira de iframe para lutar com o CSS e sem script de terceiros a trazer os seus próprios analytics ou pixels de rastreio juntamente com a verificação.
No servidor: Node
Se preferires verificar no teu backend — por exemplo, antes de mostrares um emblema de «Parceiro Verificado» numa página de perfil que controlas, ou antes de aceitares uma credencial como prova num fluxo de onboarding — o fetch é idêntico, menos a parte do 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 };
}
No 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")}
Ambos os exemplos tratam uma resposta diferente de 200 como «não encontrado» em vez de lançarem uma exceção. Um ID de atribuição inválido ou inventado é uma entrada esperada num endpoint de verificação público, não excecional, por isso trata-o como um ramo normal e não como um erro capturado.
Estilizar o resultado em vez de incorporar a interface de outra pessoa
Como o widget acima é apenas uma chamada fetch para o teu próprio DOM, controlas cada pixel. Um padrão comum são três estados visuais mapeados diretamente a partir da resposta:
- Verificado — um visto verde com «Verificado» e a data de emissão, estilizado de acordo com os componentes de emblema/etiqueta do teu site.
- Revogado — um estado discreto ou vermelho que mostra o motivo da revogação em vez de o esconder. Tanto os destinatários como terceiros beneficiam de um «porquê» honesto, não de uma falha silenciosa.
- Não encontrado — trata-o visualmente como «revogado» (não apresentes um estado de sucesso falso), mas com texto diferente, já que um ID inválido e uma revogação deliberada são situações distintas para quem lê a página.
Nada disto exige uma biblioteca de componentes. Um switch sobre verified / revoked / not_found e três classes CSS chegam.
Cache, para não sobrecarregares o endpoint
O endpoint de verificação é público e não autenticado, o que também significa que não há custo em créditos por pedido — mas continua a ser uma ida à rede em cada carregamento de página se o chamares no cliente sem cache. Para uma página que mostra o mesmo emblema a todos os visitantes (um emblema de «Parceiro Verificado» no rodapé, por exemplo), guarda o resultado em cache no servidor com um TTL curto — entre cinco e quinze minutos é suficiente, já que as revogações não são um sinal que mude depressa — em vez de voltares a pedir a cada 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 um widget por visitante (um destinatário a incorporar a sua própria credencial num site pessoal), dispensa a cache e chama-o de novo a cada carregamento — o pedido extra é desprezável a essa escala.
O que o badges.ninja já oferece aos destinatários
Antes de construíres uma incorporação totalmente personalizada, vale a pena saber o que já existe de origem. A página pública de cada atribuição inclui snippets de partilha e de incorporação prontos, que os destinatários podem copiar diretamente, sem código do seu lado:

Se o teu caso de uso é «deixar um destinatário mostrar que o seu emblema é verdadeiro», ligar à sua página badges.ninja/awards/<guid> é muitas vezes mais simples do que construir um widget personalizado — é a página para pessoas mostrada acima, e já trata da distinção entre verificado e revogado por ti. Constrói o widget personalizado deste artigo quando precisares do estado de verificação apresentado dentro da interface do teu próprio produto — um diretório de parceiros, um painel de auditoria interna, uma ferramenta de recrutamento que confirma as certificações declaradas por um candidato — onde apontar para outro site não é a melhor experiência.
Porque não um iframe ou um widget de fornecedor?
Algumas plataformas dão-te um snippet como <iframe src="https://vendor.example.com/verify-widget"> para incorporar o estado de verificação. Funciona, mas tem custos reais: não podes reestilizar o conteúdo para combinar com o teu site (ficas preso ao CSS que o fornecedor enviou), introduz um documento de origem cruzada que a tua Content-Security-Policy tem de permitir explicitamente, e cada carregamento de página faz um pedido ao anfitrião do iframe de um terceiro, quer o visitante queira saber do estado de verificação ou não. Um widget com fetch de duas chamadas evita os três problemas — é o teu DOM, o teu estilo, e só corre quando decides chamá-lo.
Percorrer toda a cadeia de verificação
Se estás a construir algo mais rigoroso do que um widget de estado — uma ferramenta de auditoria que verifica um lote de credenciais, por exemplo, ou um relatório de conformidade — percorre a cadeia toda em vez de parares na asserção. A asserção referencia um URL badge (a BadgeClass: nome, descrição, critérios) e a BadgeClass referencia, por sua vez, um URL issuer (o perfil da organização). Um verificador rigoroso resolve os três e confirma que são internamente coerentes — o emblema pertence mesmo ao emissor que afirma, a asserção referencia mesmo o emblema que afirma — e não apenas que a asserção de topo devolve 200. É mais profundidade do que um widget de estado de uma única credencial precisa, mas vale a pena conhecer a estrutura caso um parceiro ou auditor pergunte «até que ponto vai a vossa verificação?»
Erros comuns a evitar
- Verificar apenas o estado HTTP. Como visto acima, uma asserção revogada continua a ser resolvida. Lê sempre
assertion.revoked; não deduzas a verificação só pelo código de estado. - Fixar o ID da atribuição num componente partilhado. Se o widget deve ser reutilizável nas páginas de vários destinatários, recebe o ID da atribuição como parâmetro (um atributo data, uma query string, uma prop), e não como um literal embutido no script.
- Engolir erros de rede em silêncio. Um
try/catchque não regista nada e mostra o mesmo texto de «não encontrado» que para um emblema realmente inexistente torna a depuração dolorosa mais tarde. Distingue «a chamada de rede falhou» de «a API disse que não» nos teus ramos de erro, pelo menos nos logs. - Voltar a verificar em cada render numa aplicação cliente. Se o widget vive dentro de um componente React ou Vue que faz render com frequência, verifica uma vez por montagem (ou uma vez por janela de TTL da cache, conforme a secção de cache acima), não em cada novo render.
Custa créditos? Funciona no plano gratuito?
Não. O endpoint de verificação está deliberadamente fora do sistema de créditos que rege a emissão — verificar se um emblema é válido não custa nada ao emissor, e não exige que quem o chama tenha conta, chave de API ou qualquer plano. Isto vale quer o emblema tenha sido emitido num plano Free, Starter ou Pro: a verificação é uma propriedade da própria credencial, não uma funcionalidade condicionada pela subscrição do emissor. É também por isso que podes pôr este widget numa página pública com tráfego imprevisível (uma página de carreiras, um diretório de parceiros) sem te preocupares com limites de pedidos associados à tua conta — estás a chamar um endpoint público só de leitura, não uma rota de API autenticada.
Uma coisa que vale a pena dizer explicitamente: o JSON da asserção devolvido pelo endpoint não inclui o endereço de email em bruto do destinatário. O email do destinatário é guardado com hash no backend precisamente para que uma resposta de verificação pública não possa ser recolhida para obter contactos pessoais — o que recebes chega para confirmar a credencial (emblema, emissor, datas, estado de revogação) sem transformar o endpoint numa ferramenta de geração de leads para quem percorra IDs de atribuições.
Pronto para emitir a tua primeira credencial verificável?
Começa grátis em badges.ninja — designer visual, página pública de verificação, certificado em PDF, saída Open Badge v2.0. Sem cartão de crédito.
Para a estrutura anotada completa de todos os campos de uma asserção, consulta a referência de campos JSON-LD. E se emites credenciais por programação em vez de apenas as verificar, o início rápido da API cobre a autenticação e a chamada de criação de atribuição de onde vem o resultado deste endpoint.
Como este artigo foi feito
Alguns artigos deste blog são redigidos com a ajuda de um assistente de IA e depois revistos, verificados e editados pela equipa da Badges Ninja antes da publicação. Todos os exemplos de código e preços são verificados no produto em produção. Saiba mais sobre o nosso processo editorial e de IA na nossa página do processo editorial .

Sobre o 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.
Mais de Nacho Coll
- Open Badges no Salesforce: emitir credenciais verificáveis a partir de gatilhos do CRM1/10/2026 · 10min de leitura
- Emitir Open Badges através da API REST do Badges Ninja: guia de início rápido28/09/2026 · 10min de leitura
- Certifier vs Accredible: comparação de plataformas de certificados (2026)21/09/2026 · 10min de leitura

