Open Badges et Salesforce : émettre des certifications vérifiables depuis des déclencheurs CRM

Déclenchez l’émission d’un Open Badge à partir de n’importe quel événement d’objet Salesforce (Lead gagné, Account promu, étape de formation franchie) grâce à un callout Apex vers l’API Badges Ninja.

Nacho Coll Par Mis à jour 10 min de lecture
Déclenchez l’émission d’un Open Badge à partir de n’importe quel événement d’objet Salesforce (Lead gagné, Account promu, étape de formation franchie) grâce à un callout Apex vers l’API Badges Ninja.

La plupart des équipes de formation enregistrent déjà dans Salesforce qui a terminé quoi. Une inscription à un cours passe à « Completed », un compte partenaire atteint un palier de certification, un client termine son onboarding. L’enregistrement change, puis quelqu’un exporte une liste et envoie les certificats par e-mail, à la main, une semaine plus tard.

Ce guide montre comment combler cet écart : quand un enregistrement atteint le statut qui vous intéresse, Salesforce appelle l’API de https://badges.ninja, un justificatif Open Badge v2.0 est émis, et le lien de vérification est réécrit sur l’enregistrement. Vous pouvez ensuite glisser ce lien dans un modèle d’e-mail, un rapport ou une page Experience Cloud.

Il vous faudra un administrateur Salesforce (ou une sandbox de développement), un badge déjà conçu sur https://badges.ninja et une clé d’API. Si vous n’avez jamais appelé l’API, lisez d’abord le guide de démarrage rapide de l’API ; il prend dix minutes.

Quand un déclencheur CRM est le bon outil

Avant d’écrire de l’Apex, vérifiez que vous en avez besoin. Si vous émettez vos justificatifs par lots, une fois par semestre ou par trimestre, l’import CSV du tableau de bord est plus rapide et ne demande aucun code. La voie Salesforce se justifie quand :

  • L’émission doit avoir lieu dès qu’un enregistrement change, sans intervention humaine.
  • Les données sur « qui l’a obtenu » vivent déjà dans Salesforce et vous ne voulez pas d’une seconde source de vérité.
  • Vous voulez stocker le lien du justificatif sur le Contact, le Lead ou l’enregistrement de formation personnalisé pour vos rapports.

Si votre outil de workflow est Zapier plutôt qu’Apex, le même appel d’API fonctionne aussi là-bas ; consultez l’automatisation des Open Badges avec Zapier.

Ce que vous allez construire

Le flux comporte quatre éléments :

  1. Un badge conçu dans le concepteur visuel. Copiez son identifiant (l’id renvoyé par GET /badges).
  2. Une clé d’API créée dans la page API Keys de votre tableau de bord. La clé n’est affichée qu’une fois, alors conservez-la tout de suite.
  3. Un Named Credential dans Salesforce qui contient la clé, pour qu’elle n’apparaisse jamais dans le code.
  4. Un déclencheur Apex et une classe Queueable qui émettent l’attribution et réécrivent le lien de l’attribution sur l’enregistrement.

Newly created API key revealed once

Étape 1 : stocker la clé dans un Named Credential

Coder une clé d’API en dur dans l’Apex est l’erreur à éviter. Dans Setup, créez un External Credential avec un en-tête personnalisé, puis un Named Credential qui pointe vers l’hôte de l’API :

  • URL : https://api.badges.ninja
  • Nom de l’en-tête personnalisé : X-Api-Key
  • Valeur de l’en-tête personnalisé : votre clé, sous la forme bws_YOUR_KEY_HERE
  • Nom du Named Credential : BadgesNinja

Donnez à l’ensemble de permissions qui exécute votre automatisation l’accès au principal de l’External Credential. Avec un Named Credential en place, vous n’avez pas besoin d’un Remote Site Setting distinct ; Salesforce autorise le callout via le credential. Si votre organisation utilise encore des Named Credentials hérités ou un simple endpoint, ajoutez https://api.badges.ninja comme Remote Site Setting et envoyez l’en-tête depuis le code.

Étape 2 : ajouter des champs à l’enregistrement

Sur l’objet qui représente la réussite (nous utiliserons un objet personnalisé appelé Training_Enrollment__c), ajoutez :

  • Badge_Id__c (Texte) : le badge à émettre. Le stocker par cours permet à un seul déclencheur de servir de nombreux badges.
  • Badge_Award_Id__c (Texte, unique) : l’identifiant d’attribution renvoyé par l’API.
  • Badge_Url__c (URL) : la page de vérification publique.
  • Badge_Error__c (Texte long) : la dernière erreur, pour que les administrateurs voient les échecs sans ouvrir les journaux de débogage.

Le champ Badge_Award_Id__c joue un double rôle. C’est votre garde-fou contre les doublons : le déclencheur n’émet que lorsqu’il est vide.

Étape 3 : le callout Apex

Un déclencheur ne peut pas effectuer de callout directement, car les callouts ne sont pas autorisés dans la même transaction qu’un DML non validé. Confiez le travail à un Queueable qui implémente Database.AllowsCallouts.

Le contrat d’API de POST /awards est court. Le corps contient badgeId, un objet recipient imbriqué avec name et email, et un issuedOn obligatoire. Un appel réussi renvoie un HTTP 200 avec { "awardId": "..." }. Le nom du destinataire doit comporter au moins cinq caractères : un Contact nommé « Al Li » serait donc rejeté. Validez avant d’appeler.

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;
    }
}

Deux détails méritent l’attention. Premièrement, issuedOn est en millisecondes epoch, ce qui correspond exactement à ce que renvoie Datetime.getTime(). Deuxièmement, la réponse n’inclut pas l’URL de vérification : le code la construit donc à partir de l’identifiant d’attribution, https://badges.ninja/awards/<awardId>.

Étape 4 : le déclencheur

Gardez le déclencheur léger. Il décide seulement quels enregistrements sont éligibles et met en file un job par enregistrement.

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 vérification wasCompleted est importante. Sans elle, toute modification ultérieure d’un enregistrement terminé relancerait la logique. Combinée au garde-fou de l’identifiant d’attribution vide dans le job, elle garantit qu’un enregistrement ne peut jamais produire qu’un seul justificatif.

Une limite à respecter : Salesforce n’autorise qu’un petit nombre de jobs Queueable mis en file depuis une même transaction (50 en contexte synchrone). Si vous chargez des achèvements en masse, par exemple un import de 2 000 lignes, le déclencheur ci-dessus atteindra ce plafond. Pour les chargements en masse, téléversez plutôt la liste via l’attribution en masse par CSV du tableau de bord, ou passez à une classe Batchable avec Database.AllowsCallouts qui traite quelques enregistrements par portée.

API keys list showing the masked prefix

Gestion des erreurs et nouvelles tentatives

L’API renvoie des codes de statut standard, et chacun appelle une réponse différente de votre code :

StatutSignificationQue faire
400Un champ était manquant ou invalide, y compris un nom de destinataire de moins de cinq caractèresNe réessayez pas. Corrigez les données et écrivez le message dans Badge_Error__c.
401Clé d’API incorrecte ou absenteVérifiez le Named Credential. Réessayer ne servira à rien tant que ce n’est pas corrigé.
402Plus de justificatifs ou de quota pour votre formuleArrêtez l’émission et alertez un administrateur ; réessayez après une mise à niveau ou la réinitialisation du quota.
404Le badgeId n’existe pasCorrigez Badge_Id__c sur l’enregistrement ou le cours.
5xx ou délai dépasséDéfaillance transitoireVous pouvez réessayer plus tard sans risque.

Comme le job écrit l’erreur sur l’enregistrement et laisse Badge_Award_Id__c vide, une nouvelle tentative se résume à cocher une case ou à réenregistrer l’enregistrement. Une petite classe Apex planifiée qui recherche les inscriptions terminées sans identifiant d’attribution et avec une erreur transitoire, puis les remet en file, vous offre une file de nouvelles tentatives automatique sans infrastructure supplémentaire. Plafonnez le nombre de tentatives avec un champ compteur pour qu’un enregistrement définitivement défectueux ne boucle pas indéfiniment.

Vérifiez votre formule avant de passer en production. La formule Free couvre 1 200 justificatifs par an ; Starter coûte $9 par mois et Pro $29 par mois. Un déclencheur qui s’active sur chaque Lead épuiserait vite une petite formule, alors limitez les critères aux vraies réussites.

Rendre le justificatif visible dans Salesforce

Une fois Badge_Url__c renseigné, vous pouvez l’utiliser partout :

  • Alertes e-mail et modèles : fusionnez le champ dans un e-mail « Félicitations, voici votre justificatif ».
  • Rapports : un rapport sur Badge_Award_Id__c != null vous donne le nombre d’émissions par cours, par région ou par propriétaire de compte.
  • Experience Cloud : affichez le lien sur la page de certification d’un partenaire pour que les acheteurs puissent le vérifier eux-mêmes.
  • Mises en page : ajoutez le champ URL pour que le support puisse répondre à « a-t-elle reçu son badge ? » d’un coup d’œil.

La page de vérification est publique et ne demande aucune inscription, et c’est tout l’intérêt. Un destinataire, un recruteur ou l’équipe achats d’un client peut ouvrir le lien et confirmer qui a émis le justificatif, ce qu’il certifie et quand. Pour des vérifications lisibles par machine, le JSON-LD Open Badge v2.0 de n’importe quelle attribution est disponible à l’adresse https://api.badges.ninja/certify-badge/award/<awardId>.

Les destinataires bénéficient aussi des extras habituels : une URL de vérification unique, un code QR, un certificat PDF au format A4 et une option Add to LinkedIn depuis le portail destinataire, où l’on se connecte par lien magique plutôt que par mot de passe.

Pourquoi c’est préférable à un plugin de badges AppExchange

Les plugins de badges d’AppExchange sont souvent facturés par siège Salesforce ou par licence de package géré. Ce coût évolue avec la taille de votre équipe Salesforce, et non avec le nombre de justificatifs que vous émettez ; une équipe de formation de dix personnes et un programme de dix mille apprenants paient donc très différemment pour le même résultat.

Une intégration par API inverse ce modèle. Vous payez au volume de justificatifs avec une formule forfaitaire, le code du déclencheur est à vous pour le lire et le modifier, et le résultat est du Open Badge v2.0 standard : les destinataires ne sont donc pas enfermés dans une visionneuse propriétaire. Vous gardez aussi votre liberté de conception : le concepteur visuel propose plus de 80 modèles, des formes, des icônes et des téléversements personnalisés, plutôt qu’une mise en page figée dans un package.

Le compromis, en toute honnêteté : un plugin s’installe en un clic et ne demande pas d’Apex. Si personne dans votre équipe ne peut maintenir quelques dizaines de lignes de code, un plugin ou un connecteur no-code conviendra peut-être mieux. Si vous comparez des plateformes en général plutôt que des intégrations, la comparaison de l’alternative à Credly détaille côte à côte les différences de prix et de fonctionnalités.

Tester avant la mise en production

Exécutez d’abord tout le flux dans une sandbox.

  1. Créez un badge de test et un destinataire de test avec une adresse e-mail que vous contrôlez.
  2. Dans les tests Apex, implémentez un HttpCalloutMock qui renvoie le statut 200 et {"awardId":"test-award-id"} ; Salesforce n’autorise pas les vrais callouts en contexte de test, et cette couverture est nécessaire pour déployer.
  3. Dans la sandbox, passez une inscription à Completed et vérifiez que Badge_Award_Id__c et Badge_Url__c se remplissent en moins d’une minute.
  4. Ouvrez l’URL dans une fenêtre de navigation privée pour confirmer que la page de vérification publique s’affiche sans connexion.
  5. Provoquez un échec (videz l’identifiant du badge, ou utilisez un nom de destinataire de moins de cinq caractères) et confirmez que l’erreur arrive dans Badge_Error__c.

Renouvelez la clé d’API si elle fuite un jour dans un journal de débogage ou une capture d’écran. La révocation est immédiate depuis la page API Keys, et vous n’avez qu’à mettre à jour l’External Credential, pas votre code.

En résumé

Le schéma est simple : un déclencheur léger décide du moment, un Queueable effectue le callout, un Named Credential garde la clé, et trois champs sur l’enregistrement stockent le résultat. Il fonctionne pour les étapes de formation, les paliers partenaires, la présence à des événements, ou tout changement d’état que vous pouvez exprimer dans Salesforce.

Commencez par un objet et un badge, observez le résultat pendant une semaine, puis étendez-le quand le comportement des nouvelles tentatives convient à vos données.

Prêt à émettre votre première certification vérifiable ? Commencez gratuitement sur badges.ninja — concepteur visuel, page de vérification publique, certificat PDF, sortie Open Badge v2.0. Aucune carte bancaire requise.

Nacho Coll

À propos de l'auteur

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.

Retour au blog

Articles similaires