Cómo emitir Open Badges desde WordPress (sin un plugin pesado)
Emite Open Badges desde cualquier plugin de cursos/LMS de WordPress (LearnDash, LifterLMS, Tutor) llamando a la API de Badges Ninja al completar el curso — sin instalar un plugin de insignias aparte.
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.
Si administras cursos en WordPress, ya conoces la rutina: alguien termina un módulo en LearnDash, LifterLMS o Tutor LMS, el LMS lo marca como “completado” y… no pasa nada verificable. Tal vez le envías un PDF por correo. Tal vez instalas un plugin de insignias dedicado para WordPress que agrega sus propias tablas de base de datos, su propia biblioteca de imágenes y su propia idea de lo que es una “insignia” — una que nadie fuera de tu sitio puede verificar.
Hay un camino más simple. Los plugins de cursos de WordPress ya disparan un action hook en el momento en que alguien completa un curso. Puedes capturar ese hook y hacer una sola llamada HTTP a la API de Badges Ninja. Sin plugin adicional, sin hosting adicional, sin formato de insignia propietario — solo una credencial Open Badge v2.0 compatible con el estándar que tu destinatario puede verificar en cualquier lugar, agregar a LinkedIn y descargar como PDF.
Este artículo explica el patrón una sola vez y luego muestra el hook específico para LearnDash, LifterLMS y Tutor LMS.
¿Por qué no usar simplemente un plugin de insignias para WordPress?
Los plugins de insignias dedicados para WordPress resuelven un problema más limitado de lo que parece. Son buenos para mostrar una imagen en una página de “mis logros” dentro de tu sitio. Suelen ser mucho más débiles en las cosas que realmente importan para una credencial:
- Portabilidad. Una insignia que solo existe como un shortcode en tu sitio de WordPress no es una credencial — es una decoración. En el momento en que el destinatario cambia de trabajo, cambia de bandeja de entrada, o tu sitio se cae, la “prueba” se va con él.
- Verificación. Cualquiera debería poder comprobar que una credencial es real sin iniciar sesión en tu panel de administración de WordPress. Open Badge v2.0 te da una URL de verificación pública y JSON-LD legible por máquina por diseño.
- Superficie de mantenimiento. Cada plugin de WordPress es una cosa más que parchear, una tabla de base de datos más que respaldar, un punto de fallo más durante una actualización del núcleo.
Llamar a una API externa al completar el curso evita los tres problemas. WordPress sigue siendo responsable de lo que hace bien — entrega de contenido y seguimiento de progreso — y la credencial en sí vive en un sistema construido específicamente para emitirla, verificarla y compartirla.
El patrón: un hook, una llamada HTTP
Todo plugin de LMS importante para WordPress dispara una acción cuando un usuario completa un curso. La integración siempre son los mismos tres pasos:
- Engancharte a la acción de finalización de tu LMS específico.
- Buscar (o crear) la identidad del destinatario — normalmente solo su correo de cuenta de WordPress y su nombre visible.
- Llamar a
POST /awardsen la API de Badges Ninja conwp_remote_post(), pasando el ID de la insignia y los datos del destinatario.
Primero necesitarás una clave de API. Genera una desde tu panel en API Keys — consulta la guía de claves de API para ver el recorrido completo. Las claves se muestran una sola vez al crearlas, así que guárdala en wp-config.php como una constante en lugar de en la base de datos:
define( 'BADGES_NINJA_API_KEY', 'bws_your_32_hex_key_here' );
define( 'BADGES_NINJA_BADGE_ID', 'your-badge-id' );

Una función auxiliar compartida mantiene delgado cada hook del LMS:
function badges_ninja_issue_award( $recipient_email, $recipient_name, $badge_id ) {
$response = wp_remote_post( 'https://api.badges.ninja/awards', array(
'headers' => array(
'X-Api-Key' => BADGES_NINJA_API_KEY,
'Content-Type' => 'application/json',
),
'body' => wp_json_encode( array(
'badgeId' => $badge_id,
'recipient' => array(
'name' => $recipient_name, // must be at least 5 characters
'email' => $recipient_email,
),
'issuedOn' => round( microtime( true ) * 1000 ), // epoch milliseconds
) ),
'timeout' => 15,
) );
if ( is_wp_error( $response ) ) {
error_log( 'Badges Ninja award failed: ' . $response->get_error_message() );
return false;
}
$code = wp_remote_retrieve_response_code( $response );
if ( $code >= 400 ) {
error_log( 'Badges Ninja award failed with HTTP ' . $code . ': ' . wp_remote_retrieve_body( $response ) );
return false;
}
return json_decode( wp_remote_retrieve_body( $response ), true );
}
El correo del destinatario se hashea con SHA-256 en el servidor una vez que llega a Badges Ninja, y la respuesta incluye la URL de verificación del award — útil si quieres mostrar un enlace de “ver tu credencial” justo ahí en WordPress después de que la llamada tenga éxito.
LearnDash
LearnDash dispara learndash_course_completed con un único argumento tipo array que contiene user y course:
add_action( 'learndash_course_completed', function( $data ) {
$user = $data['user'];
$course = $data['course'];
// Map LearnDash course ID → your Badges Ninja badge ID.
// A simple approach: store the badge ID in a course custom field.
$badge_id = get_post_meta( $course->ID, 'badges_ninja_badge_id', true );
if ( ! $badge_id ) {
return; // no badge configured for this course
}
badges_ninja_issue_award( $user->user_email, $user->display_name, $badge_id );
} );
Guardar el ID de la insignia como metadato del curso (en lugar de una única constante global BADGES_NINJA_BADGE_ID) es la decisión correcta en cuanto tengas más de un curso — cada curso se corresponde con su propio diseño de insignia.
LifterLMS
LifterLMS dispara lifterlms_course_completed con $user_id y $course_id:
add_action( 'lifterlms_course_completed', function( $user_id, $course_id ) {
$user = get_userdata( $user_id );
$badge_id = get_post_meta( $course_id, 'badges_ninja_badge_id', true );
if ( ! $user || ! $badge_id ) {
return;
}
badges_ninja_issue_award( $user->user_email, $user->display_name, $badge_id );
}, 10, 2 );
Tutor LMS
Tutor LMS dispara tutor_course_complete_after con el ID del curso, y obtienes al usuario actual desde la sesión:
add_action( 'tutor_course_complete_after', function( $course_id ) {
$user_id = get_current_user_id();
$user = get_userdata( $user_id );
$badge_id = get_post_meta( $course_id, 'badges_ninja_badge_id', true );
if ( ! $user || ! $badge_id ) {
return;
}
badges_ninja_issue_award( $user->user_email, $user->display_name, $badge_id );
} );
Si tu configuración de Tutor LMS dispara la finalización desde un proceso en segundo plano (por ejemplo, mediante una calificación automática de quiz), reemplaza get_current_user_id() por el ID de usuario que provea tu hook específico — revisa el payload con error_log( print_r( func_get_args(), true ) ) una vez durante la configuración para confirmar los argumentos.
Diseña la insignia antes de conectar el hook
Antes de que nada de esto se dispare, necesitas una insignia que otorgar. El diseñador visual cubre esto sin necesitar un diseñador en plantilla — más de 80 plantillas de forma, colores personalizados, biblioteca de íconos y carga de logo, todo con ajuste a cuadrícula. Si eres nuevo en el diseñador, Diseñando tu primer certificado digital verificable recorre cómo elegir una plantilla y publicar algo que los destinatarios realmente querrán compartir.
Una vez que la insignia existe, toma su ID desde el panel (o mediante GET /badges) y colócalo en el campo personalizado de tu curso.
Qué recibe realmente el destinatario
Esta es la parte que un plugin de insignias casero para WordPress no puede replicar. Cuando POST /awards tiene éxito, el destinatario recibe:
- Una URL de verificación única que cualquiera puede abrir — sin necesidad de iniciar sesión en WordPress — mostrando que la credencial es real, quién la emitió y cuándo.
- Un código QR y un certificado en PDF tamaño A4, generados automáticamente.
- Un botón de Agregar a tu perfil de LinkedIn, si tu emisor tiene configurado un ID de organización de LinkedIn — consulta Agrega un botón “Add to Profile” de LinkedIn para la configuración única.
- Acceso a su propio portal de destinatario en
badges.ninja/me, mediante inicio de sesión con magic link — sin contraseña que olvidar, sin una cuenta aparte que administrar en tu sitio de WordPress. - Open Badge v2.0 JSON-LD compatible con el estándar, de modo que cualquier verificador compatible con OB (no solo Badges Ninja) pueda validarla.
Nada de eso es trabajo de WordPress construirlo, y nada de eso debería vivir únicamente dentro de tu base de datos de WordPress.
Manejar los fallos con elegancia
Los hooks de finalización de curso se disparan durante una solicitud de página en vivo, y una llamada a la API lenta o fallida no debería bloquear la pantalla de “felicidades” del alumno. Dos ajustes prácticos una vez que superas la prueba de concepto:
No dejes que un award fallido bloquee la interfaz. La función auxiliar de arriba ya registra el error y devuelve false en lugar de lanzar una excepción — LearnDash, LifterLMS y Tutor continúan su flujo normal de finalización sin importar lo que devuelva badges_ninja_issue_award().
Ponlo en cola en lugar de llamarlo en línea, a escala. Si estás moviendo cohortes grandes a través de un mismo curso a la vez (una fecha de inicio de cohorte, un desbloqueo de repetición de webinar), dispara un evento programado de WP-Cron desde el hook en lugar de llamar a la API de forma síncrona:
add_action( 'learndash_course_completed', function( $data ) {
wp_schedule_single_event( time() + 30, 'badges_ninja_deferred_award', array(
$data['user']->user_email,
$data['user']->display_name,
get_post_meta( $data['course']->ID, 'badges_ninja_badge_id', true ),
) );
} );
add_action( 'badges_ninja_deferred_award', 'badges_ninja_issue_award', 10, 3 );
Esto distribuye la carga y evita que una sola solicitud lenta se convierta en el problema del alumno. Para lotes genuinamente grandes (una cohorte entera del pasado, migrada de una sola vez), evita por completo el camino del hook de WordPress y usa awards masivos vía CSV — súbelo una vez, y la plataforma pagina la emisión del lado del servidor con pausa/reanudación incorporadas.
Una nota sobre la idempotencia
Si tu LMS alguna vez dispara su hook de finalización más de una vez para el mismo usuario (un caso límite común en LearnDash con repeticiones de quiz, o una resincronización de Tutor LMS), no quieres otorgar la misma insignia dos veces. La protección más simple es un indicador de user-meta de WordPress que estableces justo después de una llamada exitosa:
if ( get_user_meta( $user_id, 'badges_ninja_awarded_' . $course_id, true ) ) {
return; // already issued
}
$result = badges_ninja_issue_award( $user->user_email, $user->display_name, $badge_id );
if ( $result ) {
update_user_meta( $user_id, 'badges_ninja_awarded_' . $course_id, true );
}
Si estás emitiendo a un volumen real y quieres manejar esto de forma centralizada en lugar de por sitio, revisa el manejo de eventos basado en webhooks o el inicio rápido completo de la API para conocer las formas de solicitud/respuesta de todos los endpoints.
Cuando este patrón se queda corto para un solo curso
Los ejemplos anteriores asumen una insignia por curso. Una vez que empieces a manejar credenciales apilables — una insignia de track que se desbloquea después de varias insignias de curso, o una insignia final que depende de múltiples prerrequisitos — mueve el mapeo de “qué insignia, para qué finalización” fuera de los metadatos del post y hacia una pequeña tabla de referencia, o dirígelo desde una automatización respaldada por hoja de cálculo (Airtable o Google Sheets) que dispare la misma llamada a POST /awards. La llamada a la API en sí no cambia; solo cambia qué decide cuándo hacerla.
Solución de problemas de la integración
Un puñado de problemas explica la mayor parte de la fricción que la gente encuentra al conectar esto por primera vez:
El hook nunca se dispara. Confirma que estás enganchándote a la acción correcta para la versión real de tu plugin — LearnDash en particular ha cambiado los nombres de sus hooks de finalización entre versiones mayores (algunas instalaciones antiguas todavía dependen de que learndash_course_completed se dispare desde una ruta de código distinta a la de las más nuevas). Agrega un error_log() temporal al inicio de tu callback y observa wp-content/debug.log mientras completas un curso de prueba como un usuario descartable.
wp_remote_post() se agota por tiempo de espera. Los entornos de hosting compartido a veces bloquean las conexiones HTTPS salientes hacia hosts desconocidos, o limitan los tiempos de espera de solicitud por debajo de los 15 segundos configurados arriba. Si las llamadas se agotan de forma consistente, consulta con tu proveedor de hosting si se permiten conexiones salientes hacia api.badges.ninja, y confirma que tu extensión curl de PHP tenga certificados CA actualizados — un paquete de certificados desactualizado es una falla silenciosa común en pilas de hosting compartido más antiguas.
401 Unauthorized. La constante de la clave de API no se está cargando, o fue regenerada después de que se estableció la constante. Las claves se muestran una sola vez al crearse y no se pueden recuperar de nuevo — si perdiste el rastro de cuál clave está activa, elimina la obsoleta y emite una nueva en lugar de adivinar.
Insignia emitida, pero con el diseño de insignia equivocado. Esto casi siempre es un valor de post-meta badges_ninja_badge_id obsoleto que quedó de una prueba. Como el mapeo vive en el post del curso, es fácil olvidar que lo cambiaste después de duplicar un curso para una nueva cohorte — vale la pena revisarlo rápidamente cada vez que clonas un curso.
Awards duplicados para la misma persona. Cubierto arriba con la protección de user-meta, pero vale la pena repetirlo: no está garantizado que los hooks de finalización del LMS se disparen exactamente una vez. Trata “ya se otorgó” como un caso normal a verificar, no como un caso límite a ignorar.
Preguntas frecuentes
¿Esto funciona con paquetes de cursos de WooCommerce? Sí — si la compra de un paquete debería disparar una insignia independientemente de la finalización del curso (por ejemplo, una insignia de “miembro certificado” para quien compre un paquete específico), engancha woocommerce_order_status_completed en lugar de una acción de finalización del LMS, y busca el ID de la insignia en el metadato del producto en lugar del curso.
¿Los destinatarios pueden recibir la insignia sin una cuenta de WordPress? Sí, y ese es precisamente el punto. El award está vinculado a su dirección de correo en Badges Ninja, no a un registro de usuario de WordPress. Si tu sitio permite checkout como invitado o finalización anónima de quiz, solo asegúrate de capturar una dirección de correo real para pasarla a badges_ninja_issue_award().
¿Qué pasa si quiero revisar los awards antes de que salgan? Evita disparar la llamada directamente desde el hook de finalización. En su lugar, escribe el award pendiente (usuario, curso, marca de tiempo) en una tabla personalizada o tipo de post, y emítelo desde una tarea programada o un botón de administración “Aprobar y otorgar” que llame a la misma función auxiliar bajo demanda.
¿Necesito una insignia separada por curso, o una puede cubrir varios? Ambas opciones funcionan. Algunos emisores crean una insignia por curso para mayor granularidad; otros crean una única insignia de “programa completado” y solo la otorgan una vez que se completó cada curso requerido, verificando la finalización de los prerrequisitos dentro del hook antes de llamar a la API.
¿Listo para emitir tu primera credencial verificable? Comienza gratis en badges.ninja — diseñador visual, página de verificación pública, certificado en PDF, salida Open Badge v2.0. No se requiere tarjeta de crédito.
Cómo se hizo este artículo
Algunos artículos de este blog se redactan con la ayuda de un asistente de IA y luego son revisados, verificados y editados por el equipo de Badges Ninja antes de publicarse. Cada ejemplo de código y precio se verifica con el producto en vivo. Más información sobre nuestro proceso editorial y de IA en nuestra página de proceso editorial .

Sobre el 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
- El mejor software de certificados digitales en 2026 (gratis y de pago comparados)10 sept 2026 · 11min de lectura
- Diseña tu primer certificado digital verificable (sin necesitar un diseñador)3 sept 2026 · 11min de lectura
- Reemplaza las Open Badges nativas de Moodle con Badges Ninja (Mejor Diseñador, Misma API)31 ago 2026 · 8min de lectura
