Open Badges no Salesforce: emita credenciais verificáveis a partir de gatilhos do CRM
Dispare a emissão de Open Badges a partir de qualquer evento de objeto do Salesforce (Lead ganho, conta promovida, marco de treinamento) com um callout Apex para a API do 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.
A maioria das equipes de treinamento já registra no Salesforce quem concluiu o quê. Uma matrícula em um curso passa para “Concluído”, uma conta de parceiro atinge um nível de certificação, um cliente termina o onboarding. O registro muda e, uma semana depois, alguém exporta uma lista e envia os certificados por e-mail na mão.
Este guia mostra como fechar essa lacuna: quando um registro chega ao status que importa para você, o Salesforce chama a API do https://badges.ninja, uma credencial Open Badge v2.0 é emitida e o link de verificação é gravado de volta no registro. Depois você pode colocar esse link em um modelo de e-mail, em um relatório ou em uma página do Experience Cloud.
Você vai precisar de um administrador do Salesforce (ou de um sandbox de desenvolvimento), de um emblema já desenhado no https://badges.ninja e de uma chave de API. Se você nunca chamou a API, leia antes o guia rápido da API; leva dez minutos.
Quando um gatilho do CRM é a ferramenta certa
Antes de escrever Apex, confira se você realmente precisa dele. Se você emite credenciais em lote uma vez por semestre ou por trimestre, o upload de CSV do painel é mais rápido e não exige nenhum código. O caminho pelo Salesforce vale a pena quando:
- A emissão deve acontecer no instante em que o registro muda, sem nenhuma etapa manual.
- Os dados de “quem conquistou” já estão no Salesforce e você não quer uma segunda fonte da verdade.
- Você quer guardar o link da credencial no Contato, no Lead ou no registro de treinamento personalizado para fins de relatório.
Se a sua ferramenta de fluxo é o Zapier em vez de Apex, a mesma chamada de API funciona lá também; veja automação de Open Badges com Zapier.
O que você vai construir
O fluxo tem quatro peças:
- Um emblema desenhado no designer visual. Copie o id dele (o
idretornado porGET /badges). - Uma chave de API criada na página de chaves de API do seu painel. A chave é exibida uma única vez, então guarde-a imediatamente.
- Uma Named Credential no Salesforce que guarda a chave, para que ela nunca apareça no código.
- Um gatilho Apex mais uma classe Queueable que emite o prêmio e grava o link do prêmio de volta no registro.

Passo 1: guarde a chave em uma Named Credential
Deixar uma chave de API fixa no código Apex é o erro a evitar. No Setup, crie uma External Credential com um cabeçalho personalizado e, depois, uma Named Credential apontando para o host da API:
- URL:
https://api.badges.ninja - Nome do cabeçalho personalizado:
X-Api-Key - Valor do cabeçalho personalizado: sua chave, no formato
bws_YOUR_KEY_HERE - Nome da Named Credential:
BadgesNinja
Conceda ao permission set que executa sua automação acesso ao principal da External Credential. Com uma Named Credential, você não precisa de um Remote Site Setting separado; o Salesforce autoriza o callout por meio da credencial. Se a sua org ainda usa Named Credentials legadas ou um endpoint simples, adicione https://api.badges.ninja como Remote Site Setting e envie o cabeçalho pelo código.
Passo 2: adicione campos ao registro
No objeto que representa a conquista (vamos usar um objeto personalizado chamado Training_Enrollment__c), adicione:
Badge_Id__c(Text): o emblema a emitir. Guardá-lo por curso permite que um único gatilho atenda a vários emblemas.Badge_Award_Id__c(Text, único): o id do prêmio retornado pela API.Badge_Url__c(URL): a página pública de verificação.Badge_Error__c(Long Text): o último erro, para que os administradores vejam as falhas sem abrir os logs de depuração.
O campo Badge_Award_Id__c tem dupla função. Ele é a sua proteção contra duplicidade: o gatilho só emite quando ele está vazio.
Passo 3: o callout Apex
Um gatilho não pode fazer um callout diretamente, porque callouts não são permitidos na mesma transação de um DML não confirmado. Passe o trabalho para um Queueable que implemente Database.AllowsCallouts.
O contrato da API para POST /awards é curto. O corpo traz badgeId, um objeto recipient aninhado com name e email, e um issuedOn obrigatório. Uma chamada bem-sucedida retorna HTTP 200 com { "awardId": "..." }. O nome do destinatário precisa ter pelo menos cinco caracteres, então um Contato chamado “Al Li” seria rejeitado; valide antes de chamar.
public class BadgeIssueJob implements Queueable, Database.AllowsCallouts {
private Id enrollmentId;
public BadgeIssueJob(Id enrollmentId) { this.enrollmentId = enrollmentId; }
public void execute(QueueableContext ctx) {
Training_Enrollment__c e = [
SELECT Id, Badge_Id__c, Badge_Award_Id__c, Contact__r.Name, Contact__r.Email
FROM Training_Enrollment__c WHERE Id = :enrollmentId LIMIT 1
];
if (e.Badge_Award_Id__c != null) { return; } // already issued
Map<String, Object> recipient = new Map<String, Object>{
'name' => e.Contact__r.Name,
'email' => e.Contact__r.Email
};
Map<String, Object> body = new Map<String, Object>{
'badgeId' => e.Badge_Id__c,
'recipient' => recipient,
'issuedOn' => Datetime.now().getTime()
};
HttpRequest req = new HttpRequest();
req.setEndpoint('callout:BadgesNinja/awards');
req.setMethod('POST');
req.setHeader('Content-Type', 'application/json');
req.setBody(JSON.serialize(body));
HttpResponse res = new Http().send(req);
if (res.getStatusCode() == 200) {
Map<String, Object> out = (Map<String, Object>) JSON.deserializeUntyped(res.getBody());
String awardId = (String) out.get('awardId');
e.Badge_Award_Id__c = awardId;
e.Badge_Url__c = 'https://badges.ninja/awards/' + awardId;
e.Badge_Error__c = null;
} else {
e.Badge_Error__c = res.getStatusCode() + ': ' + res.getBody();
}
update e;
}
}
Dois detalhes que vale notar. Primeiro, issuedOn é em milissegundos desde a época Unix, exatamente o que Datetime.getTime() retorna. Segundo, a resposta não inclui a URL de verificação, então o código a monta a partir do id do prêmio: https://badges.ninja/awards/<awardId>.
Passo 4: o gatilho
Mantenha o gatilho enxuto. Ele só decide quais registros se qualificam e enfileira um job por registro.
trigger TrainingEnrollmentBadge on Training_Enrollment__c (after insert, after update) {
for (Training_Enrollment__c e : Trigger.new) {
Boolean completed = e.Status__c == 'Completed';
Boolean wasCompleted = Trigger.isUpdate && Trigger.oldMap.get(e.Id).Status__c == 'Completed';
if (completed && !wasCompleted && e.Badge_Award_Id__c == null && e.Badge_Id__c != null) {
System.enqueueJob(new BadgeIssueJob(e.Id));
}
}
}
A verificação wasCompleted importa. Sem ela, qualquer edição posterior em um registro concluído dispararia a lógica de novo. Combinada com a proteção de id de prêmio vazio dentro do job, um registro só pode gerar uma credencial.
Um limite a respeitar: o Salesforce permite enfileirar um número pequeno de jobs Queueable a partir de uma única transação (50 em contexto síncrono). Se você carrega conclusões em massa, por exemplo uma importação de 2.000 linhas, o gatilho acima vai bater nesse teto. Para cargas em massa, envie a lista pelos prêmios em massa via CSV do painel ou troque por uma classe Batchable com Database.AllowsCallouts que processe poucos registros por escopo.

Tratamento de erros e novas tentativas
A API retorna códigos de status padrão, e cada um pede uma resposta diferente do seu código:
| Status | Significado | O que fazer |
|---|---|---|
| 400 | Um campo estava ausente ou inválido, incluindo nome de destinatário com menos de cinco caracteres | Não tente de novo. Corrija os dados e grave a mensagem em Badge_Error__c. |
| 401 | Chave de API inválida ou ausente | Verifique a Named Credential. Tentar de novo não adianta até corrigir. |
| 402 | Sem credenciais ou cota no seu plano | Pare de emitir e avise um administrador; tente de novo após fazer upgrade ou quando a cota for renovada. |
| 404 | O badgeId não existe | Corrija Badge_Id__c no registro ou no curso. |
| 5xx ou timeout | Falha transitória | Pode tentar de novo mais tarde. |
Como o job grava o erro no registro e deixa Badge_Award_Id__c vazio, tentar de novo é tão simples quanto marcar uma caixa de seleção ou salvar o registro outra vez. Uma pequena classe Apex agendada que procure matrículas concluídas sem id de prêmio e com erro transitório, e as enfileire de novo, dá a você uma fila de novas tentativas automática sem nenhuma infraestrutura extra. Limite as tentativas com um campo contador para que um registro permanentemente ruim não fique em loop para sempre.
Confira o seu plano antes de ligar isso à produção. O plano Free cobre 1.200 credenciais por ano; o Starter custa $9 por mês e o Pro, $29 por mês. Um gatilho que dispara em todo Lead consumiria um plano pequeno rapidamente, então restrinja os critérios a conquistas reais.
Tornando a credencial visível no Salesforce
Depois que Badge_Url__c estiver preenchido, você pode usá-lo em qualquer lugar:
- Alertas e modelos de e-mail: insira o campo em um e-mail de “Parabéns, aqui está a sua credencial”.
- Relatórios: um relatório sobre
Badge_Award_Id__c != nulldá a você a contagem de emissões por curso, região ou proprietário da conta. - Experience Cloud: exiba o link na página de certificação de um parceiro para que os compradores possam verificar por conta própria.
- Page layouts: adicione o campo de URL para que a equipe de suporte responda “ela recebeu o emblema?” num piscar de olhos.
A página de verificação é pública e dispensa cadastro, e esse é justamente o ponto. Um destinatário, um gestor de contratação ou o time de compras de um cliente pode abrir o link e confirmar quem emitiu a credencial, o que ela certifica e quando. Para verificações legíveis por máquina, o JSON-LD Open Badge v2.0 de qualquer prêmio está disponível em https://api.badges.ninja/certify-badge/award/<awardId>.
Os destinatários também recebem os extras de sempre: uma URL de verificação única, um QR code, um certificado em PDF A4 e a opção de adicionar ao LinkedIn pelo portal do destinatário, que faz login com um link mágico em vez de senha.
Por que isso supera um plugin de emblemas do AppExchange
Os plugins de emblemas do AppExchange costumam ser cobrados por usuário do Salesforce ou por licença de pacote gerenciado. Esse custo cresce com o tamanho da sua equipe de Salesforce, não com o número de credenciais que você emite, então uma equipe de treinamento de dez pessoas e um programa com dez mil alunos pagam de forma muito diferente pelo mesmo resultado.
Uma integração por API inverte esse modelo. Você paga pelo volume de credenciais em um plano fixo, o código do gatilho é seu para ler e alterar, e a saída é Open Badge v2.0 padrão, então os destinatários não ficam presos a um visualizador proprietário. Você também mantém a liberdade de design: o designer visual oferece mais de 80 modelos, formas, ícones e uploads personalizados, em vez de um layout fixo dentro de um pacote.
A troca, sendo honesto: um plugin se instala com um clique e não precisa de Apex. Se ninguém na sua equipe consegue manter algumas dezenas de linhas de código, um plugin ou um conector no-code pode ser a melhor escolha. Se você está comparando plataformas em geral, e não integrações, o comparativo de alternativa ao Credly cobre preços e diferenças de recursos lado a lado.
Testando antes de entrar em produção
Rode o fluxo inteiro em um sandbox primeiro.
- Crie um emblema de teste e um destinatário de teste com um endereço de e-mail que você controle.
- Nos testes Apex, implemente
HttpCalloutMockretornando status 200 e{"awardId":"test-award-id"}; o Salesforce não permite callouts reais em contexto de teste, e você precisa dessa cobertura para fazer o deploy. - No sandbox, coloque uma matrícula como Completed e confira se
Badge_Award_Id__ceBadge_Url__csão preenchidos em até um minuto. - Abra a URL em uma janela anônima do navegador para confirmar que a página pública de verificação carrega sem login.
- Force uma falha (deixe o id do emblema em branco ou use um nome de destinatário com menos de cinco caracteres) e confirme que o erro chega em
Badge_Error__c.
Gire a chave de API se ela algum dia vazar para um log de depuração ou uma captura de tela. A revogação é imediata pela página de chaves de API, e você só precisa atualizar a External Credential, não o seu código.
Resumindo
O padrão é pequeno: um gatilho enxuto decide quando, um Queueable faz o callout, uma Named Credential guarda a chave e três campos no registro armazenam o resultado. Funciona para marcos de treinamento, níveis de parceiro, presença em eventos ou qualquer mudança de estado que você consiga expressar no Salesforce.
Comece com um objeto e um emblema, acompanhe por uma semana e expanda quando o comportamento das novas tentativas se encaixar nos seus dados.
Pronto para emitir sua primeira credencial verificável? Comece grátis no 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.
Como este artigo foi feito
Alguns posts deste blog são redigidos com a ajuda de um assistente de IA e depois revisados, verificados e editados pela equipe da Badges Ninja antes da publicação. Cada exemplo de código e preço é verificado no produto real. Saiba mais sobre nosso processo editorial e de IA em 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
- Emitindo Open Badges pela API REST do Badges Ninja: guia de início rápido28 de set. de 2026 · 10min de leitura
- Incorpore a verificação de emblemas no seu site (sem iframe, sem SDK)24 de set. de 2026 · 11min de leitura
- Certifier vs Accredible: comparação de plataformas de certificados (2026)21 de set. de 2026 · 10min de leitura

