Salesforce Open Badges: emet credencials verificables des de desencadenants del CRM
Desencadena l'emissió d'Open Badges a partir de qualsevol esdeveniment d'un objecte de Salesforce (Lead won, Account upgraded, fita de formació) amb una crida Apex a l'API de 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.
La majoria d’equips de formació ja registren dins de Salesforce qui ha acabat què. Una inscripció a un curs passa a «Completed», un compte de partner arriba a un nivell de certificació, un client acaba l’onboarding. El registre canvia, i una setmana després algú exporta una llista i envia els certificats per correu a mà.
Aquesta guia et mostra com tancar aquest buit: quan un registre arriba a l’estat que t’interessa, Salesforce crida l’API de https://badges.ninja, s’emet una credencial Open Badge v2.0 i l’enllaç de verificació es desa de nou al registre. Després pots posar aquest enllaç en una plantilla de correu, en un informe o en una pàgina d’Experience Cloud.
Necessitaràs un administrador de Salesforce (o un sandbox de desenvolupador), una insígnia ja dissenyada a https://badges.ninja i una clau d’API. Si mai has cridat l’API, llegeix primer la API quickstart; et porta deu minuts.
Quan un desencadenant del CRM és l’eina adequada
Abans d’escriure Apex, comprova si realment el necessites. Si emets credencials per lots un cop per trimestre o per curs, la càrrega de CSV del tauler és més ràpida i no requereix cap codi. La via Salesforce val la pena quan:
- L’emissió s’ha de fer en el mateix moment en què canvia el registre, sense cap pas humà.
- Les dades de «qui l’ha aconseguit» ja són a Salesforce i no vols una segona font de veritat.
- Vols desar l’enllaç de la credencial al Contact, al Lead o al registre de formació personalitzat per fer-ne informes.
Si la teva eina de workflow és Zapier en lloc d’Apex, la mateixa crida a l’API també hi funciona; mira Zapier Open Badges automation.
Què estàs construint
El flux té quatre peces:
- Una insígnia dissenyada al dissenyador visual. Copia’n l’id (l’
idque retornaGET /badges). - Una clau d’API creada a la pàgina API Keys del tauler. La clau només es mostra una vegada, així que desa-la tot seguit.
- Una Named Credential a Salesforce que guarda la clau, de manera que mai no apareix al codi.
- Un desencadenant Apex més una classe Queueable que emet l’award i escriu l’enllaç de l’award al registre.

Pas 1: desa la clau en una Named Credential
Posar una clau d’API directament a l’Apex és l’error que cal evitar. A Setup, crea una External Credential amb una capçalera personalitzada i, després, una Named Credential que apunti al host de l’API:
- URL:
https://api.badges.ninja - Custom header name:
X-Api-Key - Custom header value: la teva clau, amb la forma
bws_YOUR_KEY_HERE - Named Credential name:
BadgesNinja
Dona accés al principal de l’External Credential al permission set que executa la teva automatització. Amb una Named Credential no necessites un Remote Site Setting a part; Salesforce autoritza la crida a través de la credencial. Si la teva org encara utilitza Named Credentials antigues o un endpoint senzill, afegeix https://api.badges.ninja com a Remote Site Setting i envia la capçalera des del codi.
Pas 2: afegeix camps al registre
A l’objecte que representa la fita (farem servir un objecte personalitzat anomenat Training_Enrollment__c), afegeix:
Badge_Id__c(Text): la insígnia que cal emetre. Desar-la per curs permet que un sol desencadenant serveixi moltes insígnies.Badge_Award_Id__c(Text, unique): l’id de l’award que retorna l’API.Badge_Url__c(URL): la pàgina pública de verificació.Badge_Error__c(Long Text): l’últim error, perquè els administradors vegin les fallades sense obrir els registres de depuració.
El camp Badge_Award_Id__c fa doble feina. És la teva guarda contra duplicats: el desencadenant només emet quan és buit.
Pas 3: la crida Apex
Un desencadenant no pot fer una crida directament, perquè les crides no es permeten a la mateixa transacció que un DML sense confirmar. Passa la feina a un Queueable que implementi Database.AllowsCallouts.
El contracte de l’API per a POST /awards és curt. El cos porta badgeId, un objecte recipient imbricat amb name i email, i un issuedOn obligatori. Una crida correcta retorna HTTP 200 amb { "awardId": "..." }. El nom del destinatari ha de tenir almenys cinc caràcters, de manera que un Contact anomenat «Al Li» seria rebutjat; valida abans de cridar.
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;
}
}
Dos detalls que val la pena notar. Primer, issuedOn són mil·lisegons d’epoch, que és exactament el que retorna Datetime.getTime(). Segon, la resposta no inclou l’URL de verificació, així que el codi la construeix a partir de l’id de l’award: https://badges.ninja/awards/<awardId>.
Pas 4: el desencadenant
Mantén el desencadenant prim. Només decideix quins registres són aptes i posa a la cua una tasca per registre.
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));
}
}
}
La comprovació wasCompleted importa. Sense ella, qualsevol edició posterior d’un registre completat tornaria a disparar la lògica. Combinada amb la guarda de l’id d’award buit dins de la tasca, un registre només pot generar una única credencial.
Un límit que cal respectar: Salesforce permet posar a la cua un nombre reduït de tasques Queueable des d’una sola transacció (50 en context síncron). Si carregues compleccions de forma massiva, per exemple una importació de 2.000 files, el desencadenant d’abans toparà amb aquest sostre. Per a càrregues massives, o bé puja la llista amb la càrrega massiva d’awards per CSV del tauler, o bé passa a una classe Batchable amb Database.AllowsCallouts que processi pocs registres per abast.

Gestió d’errors i reintents
L’API retorna codis d’estat estàndard, i cadascun demana una resposta diferent del teu codi:
| Status | Meaning | What to do |
|---|---|---|
| 400 | Faltava un camp o no era vàlid, inclòs un nom de destinatari de menys de cinc caràcters | No ho reintentis. Corregeix les dades i escriu el missatge a Badge_Error__c. |
| 401 | Clau d’API incorrecta o inexistent | Revisa la Named Credential. Reintentar no servirà fins que ho arreglis. |
| 402 | Sense credencials o quota al teu pla | Atura l’emissió i avisa un administrador; reintenta després d’actualitzar el pla o quan es reiniciï la quota. |
| 404 | El badgeId no existeix | Corregeix Badge_Id__c al registre o al curs. |
| 5xx or timeout | Fallada transitòria | Es pot reintentar més tard sense risc. |
Com que la tasca escriu l’error al registre i deixa Badge_Award_Id__c buit, un reintent és tan senzill com marcar una casella o tornar a desar el registre. Una petita classe Apex programada que cerqui inscripcions completades sense id d’award i amb un error transitori, i les torni a posar a la cua, et dona una cua de reintents automàtica sense cap infraestructura addicional. Limita els intents amb un camp comptador perquè un registre dolent de manera permanent no entri en bucle per sempre.
Revisa el teu pla abans de connectar-ho a producció. El pla Free cobreix 1.200 credencials l’any; Starter costa $9 al mes i Pro $29 al mes. Un desencadenant que es dispari amb cada Lead consumiria un pla petit molt de pressa, així que acota els criteris a fites reals.
Fer visible la credencial a Salesforce
Quan Badge_Url__c està omplert, el pots fer servir a qualsevol lloc:
- Alertes i plantilles de correu: fusiona el camp en un correu de «Felicitats, aquesta és la teva credencial».
- Informes: un informe sobre
Badge_Award_Id__c != nullet dona el recompte d’emissions per curs, regió o propietari del compte. - Experience Cloud: mostra l’enllaç a la pàgina de certificació d’un partner perquè els compradors el puguin verificar per ells mateixos.
- Page layouts: afegeix-hi el camp URL perquè el personal de suport pugui respondre «ha rebut la seva insígnia?» d’un cop d’ull.
La pàgina de verificació és pública i no requereix registre, i aquest és tot el sentit. Un destinatari, un responsable de selecció o l’equip de compres d’un client poden obrir l’enllaç i confirmar qui ha emès la credencial, què certifica i quan. Per a comprovacions automatitzades, el JSON-LD d’Open Badge v2.0 de qualsevol award és disponible a https://api.badges.ninja/certify-badge/award/<awardId>.
Els destinataris també reben els extres habituals: una URL de verificació única, un codi QR, un certificat PDF en A4 i una opció Add to LinkedIn des del portal del destinatari, que inicia sessió amb un enllaç màgic en lloc d’una contrasenya.
Per què això supera un connector d’insígnies d’AppExchange
Els connectors d’insígnies d’AppExchange solen tarifar-se per seient de Salesforce o per llicència de paquet gestionat. Aquest cost creix amb la mida del teu equip de Salesforce, no amb el nombre de credencials que emets, de manera que un equip de formació de deu persones i un programa de deu mil alumnes paguen preus molt diferents pel mateix resultat.
Una integració per API inverteix aquest model. Pagues per volum de credencials amb un pla fix, el codi del desencadenant és teu per llegir-lo i canviar-lo, i el resultat és Open Badge v2.0 estàndard, de manera que els destinataris no queden lligats a un visor propietari. També mantens la llibertat de disseny: el dissenyador visual ofereix més de 80 plantilles, formes, icones i càrregues personalitzades, en lloc d’una disposició fixa dins d’un paquet.
La contrapartida honesta: un connector s’instal·la amb un clic i no requereix Apex. Si ningú del teu equip pot mantenir unes quantes desenes de línies de codi, un connector o un connector sense codi pot ser l’opció més adequada. Si compares plataformes en general i no integracions, l’anàlisi de l’alternativa a Credly cobreix preus i diferències de funcions una al costat de l’altra.
Proves abans de passar a producció
Executa tot el flux primer en un sandbox.
- Crea una insígnia de prova i un destinatari de prova amb una adreça de correu que controlis.
- En les proves d’Apex, implementa un
HttpCalloutMockque retorni l’estat 200 i{"awardId":"test-award-id"}; Salesforce no permet crides reals en context de prova, i necessites aquesta cobertura per desplegar. - Al sandbox, posa una inscripció en Completed i comprova que
Badge_Award_Id__ciBadge_Url__cs’omplen en menys d’un minut. - Obre l’URL en una finestra privada del navegador per confirmar que la pàgina pública de verificació es mostra sense iniciar sessió.
- Força una fallada (deixa en blanc l’id de la insígnia o fes servir un nom de destinatari de menys de cinc caràcters) i confirma que l’error arriba a
Badge_Error__c.
Rota la clau d’API si mai es filtra en un registre de depuració o en una captura de pantalla. La revocació és immediata des de la pàgina API Keys, i només cal que actualitzis l’External Credential, no el codi.
Per tancar
El patró és petit: un desencadenant prim decideix quan, un Queueable fa la crida, una Named Credential guarda la clau i tres camps del registre desen el resultat. Funciona per a fites de formació, nivells de partner, assistència a esdeveniments o qualsevol canvi d’estat que puguis expressar a Salesforce.
Comença amb un objecte i una insígnia, observa-ho durant una setmana i amplia-ho quan el comportament dels reintents s’adapti a les teves dades.
Llest per emetre la teva primera credencial verificable? Comença gratis a badges.ninja — dissenyador visual, pàgina pública de verificació, certificat en PDF, sortida Open Badge v2.0. Sense targeta de crèdit.
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
- Emet insígnies Open Badges amb l'API REST de Badges Ninja: guia d'inici ràpid28 de set. del 2026 · 10min de lectura
- Insereix la verificació d’insígnies al teu web (sense iframe ni SDK)24 de set. del 2026 · 11min de lectura
- Certifier vs Accredible: comparativa de plataformes de certificats (2026)21 de set. del 2026 · 10min de lectura

