Salesforce Open Badges: Menerbitkan Credential Terverifikasi dari Trigger CRM
Picu penerbitan Open Badge dari event objek Salesforce apa pun — Lead menang, Account naik paket, milestone pelatihan — dengan callout Apex ke 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.
Sebagian besar tim pelatihan sudah mencatat siapa yang menyelesaikan apa di dalam Salesforce. Pendaftaran kursus berubah menjadi “Completed”, akun mitra mencapai tingkat sertifikasi, pelanggan menyelesaikan onboarding. Rekaman berubah, lalu seminggu kemudian seseorang mengekspor daftar dan mengirim sertifikat lewat email secara manual.
Panduan ini menunjukkan cara menutup celah itu: ketika sebuah rekaman mencapai status yang Anda inginkan, Salesforce memanggil API https://badges.ninja, credential Open Badge v2.0 diterbitkan, dan tautan verifikasi disimpan kembali ke rekaman tersebut. Setelah itu Anda dapat menaruh tautan tersebut di template email, laporan, atau halaman Experience Cloud.
Anda memerlukan admin Salesforce (atau sandbox developer), badge yang sudah dirancang di https://badges.ninja, dan sebuah API key. Jika Anda belum pernah memanggil API sebelumnya, baca dulu API quickstart; hanya butuh sepuluh menit.
Kapan trigger CRM menjadi alat yang tepat
Sebelum menulis Apex, periksa dulu apakah Anda benar-benar membutuhkannya. Jika Anda menerbitkan credential secara batch sekali per semester atau sekali per kuartal, unggah CSV di dasbor lebih cepat dan tidak butuh kode sama sekali. Jalur Salesforce sepadan ketika:
- Penerbitan harus terjadi seketika rekaman berubah, tanpa langkah manual.
- Data “siapa yang berhak” sudah ada di Salesforce dan Anda tidak ingin sumber kebenaran kedua.
- Anda ingin menyimpan tautan credential pada Contact, Lead, atau rekaman pelatihan kustom untuk keperluan pelaporan.
Jika alat alur kerja Anda adalah Zapier dan bukan Apex, panggilan API yang sama juga berfungsi di sana; lihat Zapier Open Badges automation.
Apa yang Anda bangun
Alurnya terdiri dari empat bagian:
- Sebuah badge yang dirancang di visual designer. Salin id-nya (
idyang dikembalikan olehGET /badges). - Sebuah API key yang dibuat di halaman API Keys pada dasbor Anda. Key hanya ditampilkan sekali, jadi simpan segera.
- Sebuah Named Credential di Salesforce yang menyimpan key tersebut, sehingga tidak pernah muncul di kode.
- Sebuah trigger Apex beserta kelas Queueable yang menerbitkan award dan menulis tautan award kembali ke rekaman.

Langkah 1: Simpan key di Named Credential
Menulis API key langsung di Apex adalah kesalahan yang harus dihindari. Di Setup, buat External Credential dengan header kustom, lalu Named Credential yang mengarah ke host API:
- URL:
https://api.badges.ninja - Custom header name:
X-Api-Key - Custom header value: key Anda, dalam format
bws_YOUR_KEY_HERE - Named Credential name:
BadgesNinja
Berikan akses ke principal External Credential kepada permission set yang menjalankan otomatisasi Anda. Dengan adanya Named Credential, Anda tidak memerlukan Remote Site Setting terpisah; Salesforce mengotorisasi callout melalui credential tersebut. Jika org Anda masih memakai Named Credential lama atau endpoint biasa, tambahkan https://api.badges.ninja sebagai Remote Site Setting dan kirim header dari kode.
Langkah 2: Tambahkan field pada rekaman
Pada objek yang merepresentasikan pencapaian (kita akan memakai objek kustom bernama Training_Enrollment__c), tambahkan:
Badge_Id__c(Text): badge yang akan diterbitkan. Menyimpannya per kursus memungkinkan satu trigger melayani banyak badge.Badge_Award_Id__c(Text, unique): id award yang dikembalikan API.Badge_Url__c(URL): halaman verifikasi publik.Badge_Error__c(Long Text): error terakhir, agar admin bisa melihat kegagalan tanpa membuka debug log.
Field Badge_Award_Id__c punya dua fungsi. Ia adalah pelindung duplikasi Anda: trigger hanya menerbitkan ketika field ini kosong.
Langkah 3: Callout Apex
Trigger tidak bisa melakukan callout secara langsung, karena callout tidak diizinkan dalam transaksi yang sama dengan DML yang belum di-commit. Serahkan pekerjaan itu ke Queueable yang mengimplementasikan Database.AllowsCallouts.
Kontrak API untuk POST /awards singkat. Body berisi badgeId, objek recipient bersarang dengan name dan email, serta issuedOn yang wajib. Panggilan yang berhasil mengembalikan HTTP 200 dengan { "awardId": "..." }. Nama penerima harus minimal lima karakter, sehingga Contact bernama “Al Li” akan ditolak; validasi sebelum memanggil.
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;
}
}
Dua hal yang patut diperhatikan. Pertama, issuedOn berupa epoch milidetik, persis seperti yang dikembalikan Datetime.getTime(). Kedua, respons tidak menyertakan URL verifikasi, sehingga kode membentuknya dari award id: https://badges.ninja/awards/<awardId>.
Langkah 4: Trigger
Buat trigger tetap ramping. Ia hanya menentukan rekaman mana yang memenuhi syarat dan memasukkan satu job per rekaman ke antrean.
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));
}
}
}
Pemeriksaan wasCompleted itu penting. Tanpanya, setiap pengeditan berikutnya pada rekaman yang sudah selesai akan menjalankan ulang logika. Dipadukan dengan pelindung award id kosong di dalam job, satu rekaman hanya dapat menghasilkan satu credential.
Satu batasan yang perlu dihormati: Salesforce hanya mengizinkan sejumlah kecil job Queueable dimasukkan ke antrean dari satu transaksi (50 dalam konteks sinkron). Jika Anda memuat penyelesaian secara massal, misalnya impor data 2.000 baris, trigger di atas akan menabrak batas itu. Untuk pemuatan massal, unggah daftarnya lewat bulk awards CSV di dasbor, atau beralih ke kelas Batchable dengan Database.AllowsCallouts yang memproses beberapa rekaman per scope.

Penanganan error dan percobaan ulang
API mengembalikan kode status standar, dan masing-masing menuntut respons berbeda dari kode Anda:
| Status | Arti | Yang harus dilakukan |
|---|---|---|
| 400 | Ada field yang hilang atau tidak valid, termasuk nama penerima di bawah lima karakter | Jangan coba ulang. Perbaiki datanya dan tulis pesan ke Badge_Error__c. |
| 401 | API key salah atau tidak ada | Periksa Named Credential. Mencoba ulang tidak akan membantu sebelum diperbaiki. |
| 402 | Credential atau kuota paket Anda habis | Hentikan penerbitan dan beri tahu admin; coba ulang setelah upgrade atau setelah kuota direset. |
| 404 | badgeId tidak ada | Perbaiki Badge_Id__c pada rekaman atau kursus. |
| 5xx atau timeout | Kegagalan sementara | Aman untuk dicoba ulang nanti. |
Karena job menulis error ke rekaman dan membiarkan Badge_Award_Id__c kosong, percobaan ulang semudah mencentang kotak atau menyimpan ulang rekaman. Kelas Apex terjadwal kecil yang mencari enrollment selesai tanpa award id dengan error sementara, lalu memasukkannya kembali ke antrean, memberi Anda antrean percobaan ulang otomatis tanpa infrastruktur tambahan. Batasi jumlah percobaan dengan field penghitung agar rekaman yang memang rusak tidak berputar selamanya.
Periksa paket Anda sebelum menghubungkannya ke produksi. Paket Free mencakup 1.200 credential per tahun; Starter $9 per bulan dan Pro $29 per bulan. Trigger yang aktif pada setiap Lead akan cepat menghabiskan paket kecil, jadi batasi kriterianya pada pencapaian yang nyata.
Menampilkan credential di Salesforce
Setelah Badge_Url__c terisi, Anda dapat memakainya di mana saja:
- Email alert dan template: gabungkan field ini ke email “Selamat, ini credential Anda”.
- Laporan: laporan pada
Badge_Award_Id__c != nullmemberi Anda jumlah penerbitan per kursus, wilayah, atau pemilik akun. - Experience Cloud: tampilkan tautan di halaman sertifikasi mitra agar pembeli dapat memverifikasinya sendiri.
- Page layout: tambahkan field URL agar staf dukungan bisa menjawab “apakah dia sudah dapat badge-nya?” dalam sekali lihat.
Halaman verifikasi bersifat publik dan tidak memerlukan pendaftaran, dan itulah intinya. Penerima, manajer perekrutan, atau tim pengadaan pelanggan dapat membuka tautan dan memastikan siapa penerbit credential, apa yang disertifikasi, dan kapan. Untuk pemeriksaan yang dapat dibaca mesin, JSON-LD Open Badge v2.0 untuk award mana pun tersedia di https://api.badges.ninja/certify-badge/award/<awardId>.
Penerima juga mendapatkan tambahan yang lazim: URL verifikasi unik, kode QR, sertifikat PDF ukuran A4, dan opsi Add to LinkedIn dari portal penerima, yang masuk dengan magic link, bukan kata sandi.
Mengapa ini lebih baik daripada plugin badge AppExchange
Plugin badge di AppExchange cenderung dihargai per seat Salesforce atau per lisensi managed package. Biaya itu mengikuti ukuran tim Salesforce Anda, bukan jumlah credential yang Anda terbitkan, sehingga tim pelatihan sepuluh orang dan program sepuluh ribu pelajar membayar sangat berbeda untuk hasil yang sama.
Integrasi API membalik model itu. Anda membayar berdasarkan volume credential pada paket tetap, kode trigger milik Anda untuk dibaca dan diubah, dan keluarannya adalah Open Badge v2.0 standar, sehingga penerima tidak terkunci pada penampil proprietari. Anda juga tetap bebas merancang: visual designer menyediakan 80+ template, bentuk, ikon, dan unggahan kustom, bukan tata letak tetap di dalam sebuah paket.
Kompromi yang jujur: plugin cukup diinstal dengan satu klik dan tidak memerlukan Apex. Jika tidak ada seorang pun di tim Anda yang bisa memelihara beberapa puluh baris kode, plugin atau konektor no-code mungkin lebih cocok. Jika Anda membandingkan platform secara umum, bukan integrasi, ulasan Credly alternative membahas perbedaan harga dan fitur secara berdampingan.
Menguji sebelum go live
Jalankan seluruh alur di sandbox terlebih dahulu.
- Buat badge uji dan penerima uji dengan alamat email yang Anda kuasai.
- Pada tes Apex, implementasikan
HttpCalloutMockyang mengembalikan status 200 dan{"awardId":"test-award-id"}; Salesforce tidak mengizinkan callout nyata dalam konteks tes, dan Anda memerlukan cakupan itu untuk deploy. - Di sandbox, ubah satu enrollment menjadi Completed dan periksa bahwa
Badge_Award_Id__cdanBadge_Url__cterisi dalam satu menit. - Buka URL di jendela browser pribadi untuk memastikan halaman verifikasi publik tampil tanpa login.
- Paksa terjadinya kegagalan (kosongkan badge id, atau gunakan nama penerima di bawah lima karakter) dan pastikan error masuk ke
Badge_Error__c.
Rotasi API key jika sampai bocor ke debug log atau tangkapan layar. Pencabutan berlaku seketika dari halaman API Keys, dan Anda hanya perlu memperbarui External Credential, bukan kode Anda.
Penutup
Polanya kecil: trigger ramping menentukan kapan, Queueable melakukan callout, Named Credential menyimpan key, dan tiga field pada rekaman menyimpan hasilnya. Pola ini cocok untuk milestone pelatihan, tingkat mitra, kehadiran acara, atau perubahan status apa pun yang dapat Anda ungkapkan di Salesforce.
Mulailah dengan satu objek dan satu badge, amati selama seminggu, lalu perluas setelah perilaku percobaan ulang sesuai dengan data Anda.
Siap menerbitkan credential terverifikasi pertama Anda? Mulai gratis di badges.ninja — visual designer, halaman verifikasi publik, sertifikat PDF, keluaran Open Badge v2.0. Tanpa kartu kredit.
Bagaimana artikel ini dibuat
Beberapa artikel di blog ini disusun dengan bantuan asisten AI, lalu ditinjau, diperiksa faktanya, dan disunting oleh tim Badges Ninja sebelum dipublikasikan. Setiap contoh kode dan harga diverifikasi terhadap produk yang aktif. Baca selengkapnya tentang proses editorial dan AI kami di halaman proses editorial .

Tentang penulis
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.

