Salesforce Open Badges: видача верифікованих посвідчень із тригерів CRM
Запускайте видачу Open Badge за будь-якою подією об’єкта Salesforce — Lead виграно, Account підвищено, етап навчання пройдено — за допомогою виклику Apex до API 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.
Більшість команд навчання вже фіксують у Salesforce, хто що завершив. Запис на курс переходить у статус «Completed», акаунт партнера досягає рівня сертифікації, клієнт завершує онбординг. Запис змінюється, а за тиждень хтось експортує список і вручну розсилає сертифікати електронною поштою.
Цей посібник показує, як закрити цю прогалину: коли запис досягає потрібного вам статусу, Salesforce викликає API https://badges.ninja, видається посвідчення Open Badge v2.0, а посилання для верифікації зберігається назад у записі. Потім ви можете вставити це посилання в шаблон листа, звіт або сторінку Experience Cloud.
Вам знадобляться адміністратор Salesforce (або пісочниця розробника), значок, уже створений на https://badges.ninja, і ключ API. Якщо ви ніколи раніше не викликали цей API, спершу прочитайте швидкий старт з API; це займе десять хвилин.
Коли тригер CRM — правильний інструмент
Перш ніж писати Apex, перевірте, чи він вам потрібен. Якщо ви видаєте посвідчення пакетами раз на семестр чи раз на квартал, завантаження CSV у панелі швидше й не потребує жодного коду. Шлях через Salesforce виправдовує себе, коли:
- Видача має відбуватися в момент зміни запису, без участі людини.
- Дані про те, «хто це здобув», уже зберігаються в Salesforce, і ви не хочете другого джерела істини.
- Ви хочете зберігати посилання на посвідчення в записі Contact, Lead або власному навчальному записі для звітності.
Якщо ваш інструмент — Zapier, а не Apex, той самий виклик API працює і там; дивіться автоматизацію Open Badges у Zapier.
Що ви будуєте
Потік складається з чотирьох частин:
- Значок, створений у візуальному дизайнері. Скопіюйте його ідентифікатор (поле
id, яке повертаєGET /badges). - Ключ API, створений на сторінці API Keys у вашій панелі. Ключ показується один раз, тож збережіть його одразу.
- Named Credential у Salesforce, що зберігає ключ, щоб він ніколи не потрапляв у код.
- Тригер Apex і клас Queueable, які видають нагороду та записують посилання на неї в запис.

Крок 1: Збережіть ключ у Named Credential
Жорстке вшивання ключа API в Apex — помилка, якої слід уникати. У Setup створіть External Credential із власним заголовком, а потім Named Credential, що вказує на хост API:
- URL:
https://api.badges.ninja - Назва власного заголовка:
X-Api-Key - Значення власного заголовка: ваш ключ у форматі
bws_YOUR_KEY_HERE - Назва Named Credential:
BadgesNinja
Надайте набору дозволів, який запускає вашу автоматизацію, доступ до принципала External Credential. Коли Named Credential налаштовано, окремий Remote Site Setting не потрібен; Salesforce авторизує виклик через це посвідчення. Якщо ваша організація досі використовує застарілі Named Credentials або звичайну кінцеву точку, додайте https://api.badges.ninja як Remote Site Setting і надсилайте заголовок із коду.
Крок 2: Додайте поля до запису
В об’єкті, що відображає досягнення (ми використаємо власний об’єкт Training_Enrollment__c), додайте:
Badge_Id__c(Text): значок, який потрібно видати. Зберігання його для кожного курсу дає змогу одному тригеру обслуговувати багато значків.Badge_Award_Id__c(Text, unique): ідентифікатор нагороди, який повертає API.Badge_Url__c(URL): публічна сторінка верифікації.Badge_Error__c(Long Text): остання помилка, щоб адміністратори бачили збої без відкриття журналів налагодження.
Поле Badge_Award_Id__c виконує подвійну роль. Це ваш захист від дублікатів: тригер видає посвідчення, лише коли воно порожнє.
Крок 3: Виклик Apex
Тригер не може виконувати виклик безпосередньо, оскільки зовнішні виклики заборонені в одній транзакції з незафіксованим DML. Передайте роботу класу Queueable, що реалізує Database.AllowsCallouts.
Контракт API для POST /awards короткий. Тіло містить badgeId, вкладений об’єкт recipient з полями name та email і обов’язкове issuedOn. Успішний виклик повертає HTTP 200 з { "awardId": "..." }. Ім’я отримувача має містити щонайменше п’ять символів, тож Contact на ім’я «Al Li» буде відхилено; перевіряйте дані перед викликом.
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;
}
}
Варто звернути увагу на дві деталі. По-перше, issuedOn — це epoch у мілісекундах, саме те, що повертає Datetime.getTime(). По-друге, відповідь не містить URL верифікації, тож код будує його з ідентифікатора нагороди: https://badges.ninja/awards/<awardId>.
Крок 4: Тригер
Нехай тригер буде тонким. Він лише вирішує, які записи підходять, і ставить у чергу одне завдання на запис.
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));
}
}
}
Перевірка wasCompleted важлива. Без неї будь-яке пізніше редагування завершеного запису знову запускало б логіку. У поєднанні з перевіркою порожнього ідентифікатора нагороди всередині завдання запис може створити лише одне посвідчення.
Одне обмеження варто враховувати: Salesforce дозволяє ставити в чергу з однієї транзакції невелику кількість завдань Queueable (50 у синхронному контексті). Якщо ви завантажуєте завершення масово, скажімо, імпортом 2000 рядків, наведений тригер досягне цієї стелі. Для масових завантажень або завантажте список через масові нагороди CSV у панелі, або перейдіть на клас Batchable з Database.AllowsCallouts, що обробляє кілька записів за один блок.

Обробка помилок і повторні спроби
API повертає стандартні коди стану, і кожен із них потребує іншої реакції вашого коду:
| Статус | Значення | Що робити |
|---|---|---|
| 400 | Поле відсутнє або недійсне, зокрема ім’я отримувача коротше за п’ять символів | Не повторюйте. Виправте дані й запишіть повідомлення в Badge_Error__c. |
| 401 | Хибний або відсутній ключ API | Перевірте Named Credential. Повтор не допоможе, доки це не виправлено. |
| 402 | Вичерпано посвідчення або квоту вашого плану | Припиніть видачу та сповістіть адміністратора; повторіть після оновлення плану або скидання квоти. |
| 404 | badgeId не існує | Виправте Badge_Id__c у записі чи курсі. |
| 5xx або тайм-аут | Тимчасовий збій | Можна безпечно повторити пізніше. |
Оскільки завдання записує помилку в запис і залишає Badge_Award_Id__c порожнім, повторна спроба зводиться до перемикання прапорця або повторного збереження запису. Невеликий запланований клас Apex, що шукає завершені записи без ідентифікатора нагороди з тимчасовою помилкою й знову ставить їх у чергу, дає автоматичну чергу повторів без додаткової інфраструктури. Обмежте кількість спроб полем-лічильником, щоб назавжди хибний запис не зациклювався.
Перевірте свій план, перш ніж підключати це до продакшну. План Free покриває 1200 посвідчень на рік; Starter коштує $9 на місяць, а Pro — $29 на місяць. Тригер, що спрацьовує на кожен Lead, швидко вичерпав би малий план, тож обмежте критерії справжніми досягненнями.
Як зробити посвідчення видимим у Salesforce
Коли Badge_Url__c заповнено, ви можете використовувати його будь-де:
- Сповіщення й шаблони листів: вставте поле в лист «Вітаємо, ось ваше посвідчення».
- Звіти: звіт за умовою
Badge_Award_Id__c != nullдає кількість видач за курсом, регіоном чи власником акаунта. - Experience Cloud: покажіть посилання на сторінці сертифікації партнера, щоб покупці могли самі його перевірити.
- Макети сторінок: додайте поле URL, щоб служба підтримки могла відповісти на питання «вона отримала свій значок?» одним поглядом.
Сторінка верифікації публічна й не потребує реєстрації, і в цьому весь сенс. Отримувач, рекрутер або відділ закупівель клієнта може відкрити посилання й підтвердити, хто видав посвідчення, що воно засвідчує і коли. Для машинних перевірок JSON-LD Open Badge v2.0 для будь-якої нагороди доступний за адресою https://api.badges.ninja/certify-badge/award/<awardId>.
Отримувачі також отримують звичні додатки: унікальну URL-адресу верифікації, QR-код, PDF-сертифікат формату A4 і опцію Add to LinkedIn з порталу отримувача, який входить за магічним посиланням, а не за паролем.
Чому це краще за плагін значків з AppExchange
Плагіни значків в AppExchange зазвичай оцінюються за місце Salesforce або за ліцензію керованого пакета. Ця вартість зростає разом із розміром вашої команди Salesforce, а не з кількістю виданих посвідчень, тож команда навчання з десяти людей і програма для десяти тисяч слухачів платять за один і той самий результат зовсім по-різному.
Інтеграція через API перевертає цю модель. Ви платите за обсяг посвідчень за фіксованим планом, код тригера можна читати й змінювати, а результат — стандартний Open Badge v2.0, тож отримувачі не прив’язані до власницького засобу перегляду. Ви також зберігаєте свободу дизайну: візуальний дизайнер пропонує понад 80 шаблонів, форм, піктограм і власні завантаження замість фіксованого макета всередині пакета.
Чесний компроміс: плагін встановлюється одним кліком і не потребує Apex. Якщо ніхто у вашій команді не зможе підтримувати кілька десятків рядків коду, кращим вибором може бути плагін або no-code конектор. Якщо ви порівнюєте платформи загалом, а не інтеграції, огляд альтернативи Credly зіставляє відмінності в цінах і можливостях.
Тестування перед запуском
Спершу прогоніть увесь потік у пісочниці.
- Створіть тестовий значок і тестового отримувача з адресою електронної пошти, яку ви контролюєте.
- У тестах Apex реалізуйте
HttpCalloutMock, що повертає статус 200 і{"awardId":"test-award-id"}; Salesforce не дозволяє реальних викликів у тестовому контексті, а це покриття потрібне для розгортання. - У пісочниці встановіть один запис у Completed і перевірте, що
Badge_Award_Id__cтаBadge_Url__cзаповнюються протягом хвилини. - Відкрийте URL у приватному вікні браузера, щоб переконатися, що публічна сторінка верифікації відображається без входу.
- Спровокуйте збій (очистіть ідентифікатор значка або використайте ім’я отримувача коротше за п’ять символів) і переконайтеся, що помилка потрапляє в
Badge_Error__c.
Змініть ключ API, якщо він колись потрапить у журнал налагодження чи на знімок екрана. Відкликання відбувається миттєво на сторінці API Keys, а оновити потрібно лише External Credential, а не ваш код.
Підсумок
Шаблон невеликий: тонкий тригер вирішує, коли, Queueable виконує виклик, Named Credential зберігає ключ, а три поля в записі фіксують результат. Він працює для етапів навчання, рівнів партнерів, відвідування подій та будь-якої зміни стану, яку можна виразити в Salesforce.
Почніть з одного об’єкта й одного значка, спостерігайте за ним тиждень і розширюйте, коли поведінка повторних спроб підійде вашим даним.
Готові видати своє перше верифіковане посвідчення? Почніть безкоштовно на badges.ninja — візуальний дизайнер, публічна сторінка верифікації, PDF-сертифікат, вивід Open Badge v2.0. Кредитна картка не потрібна.
Як створено цю статтю
Деякі публікації в цьому блозі створюються за допомогою ШІ-асистента, а потім перевіряються, звіряються з фактами й редагуються командою Badges Ninja перед публікацією. Кожен приклад коду та ціна звіряються з актуальним продуктом. Докладніше про наш редакційний процес і процес роботи з ШІ читайте на сторінці редакційного процесу .

Про автора
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.

