Cómo encaja todo
- Cree claves y añada sus sitios web en la consola.
- Para pruebas de práctica, pegue el fragmento en su página.
- Para sus propias pruebas, su servidor inicia un intento y recibe una dirección de inicio.
- Su página la abre, el candidato hace la prueba y el resultado le llega por webhook o desde la API.
Claves
pk_test_pk_live_- Las claves publicables van en sus páginas web. Solo abren pruebas de práctica en los sitios que indicó.
sk_test_sk_live_- Las claves de servidor actúan en nombre de su organización. Guárdelas en su servidor y no las envíe nunca a un navegador.
Las claves de prueba funcionan de inmediato y no se descuentan de su plan. Las claves live requieren que su cuenta esté aprobada.
Pruebas de práctica
Añada el script una vez y coloque una prueba donde quiera. El marco se ajusta solo a su contenido.
<div id="gb-test"></div>
<script src="https://www.supergb.com/cbt/js/embed/v1.js"></script>
<script>
GreenBridge.mount("#gb-test", { key: "pk_live_...", paper: "PAPER_ID" });
</script>
La prueba es el id que muestra el generador de fragmentos de su consola. Añada mode: "exam" para condiciones de examen con tiempo.
Sus propias pruebas
Escriba pruebas en la consola, en Pruebas, y ábralas. Cuando un candidato esté listo, su servidor inicia un intento:
curl -X POST https://www.supergb.com/cbt/partner-api/v1/sessions \
-H "Authorization: Bearer $GREEN_BRIDGE_KEY" \
-H "Content-Type: application/json" \
-d '{"test_id": "TEST_ID", "language": "fr", "candidate": {"id": "learner-42", "name": "Ada Obi", "email": "ada@example.com"}}'
candidate.id es su propio id para la persona, hasta 128 caracteres. El nombre y el correo son opcionales; solo guardamos lo que envíe.
language es opcional: uno de de, en, es, fr, yo, ig, ha, nl, pt, sw. Los botones, el temporizador y los mensajes del intento aparecen en ese idioma; sus preguntas quedan tal como las escribió. Sin este campo, el intento es en inglés.
La respuesta incluye una dirección de inicio que funciona una vez, durante 10 minutos. Ábrala en su página:
HTTP/1.1 201 Created
{
"attempt_id": "att_...",
"launch_token": "lt_...",
"launch_url": "https://www.supergb.com/cbt/fr/embed/v1/test?launch=lt_...",
"launch_expires_at": "2026-10-23T09:10:00Z",
"live": true,
"language": "fr"
}
<div id="gb-test"></div>
<script src="https://www.supergb.com/cbt/js/embed/v1.js"></script>
<script>
GreenBridge.mountTest("#gb-test", {
launchUrl: "LAUNCH_URL_FROM_YOUR_SERVER",
onEvent: function (event) {
if (event.type === "submitted") {
showThanks(event.detail.attempt_id);
}
}
});
</script>
Una vez abierto, un intento dura hasta 24 horas y al recargar se reanuda. Cada candidato hace cada prueba una vez.
Para listar sus pruebas y sus ids:
curl https://www.supergb.com/cbt/partner-api/v1/tests -H "Authorization: Bearer $GREEN_BRIDGE_KEY"
Mensajes del marco
onEvent recibe estos mensajes, y solo desde nuestro marco:
| Evento | Significado |
|---|---|
ready | La página se ha cargado. |
resize | El contenido cambió de altura. El marco lo sigue solo. |
completed | Se corrigió una prueba de práctica. detail incluye score y max_score. |
submitted | Se entregó una prueba. detail incluye attempt_id. Obtenga el resultado desde su servidor, no desde el navegador. |
Resultados
Intentos entregados, del más reciente al más antiguo, 50 por página. Filtre por test_id, candidate_id o ambos.
curl "https://www.supergb.com/cbt/partner-api/v1/attempts?test_id=TEST_ID&page=0" -H "Authorization: Bearer $GREEN_BRIDGE_KEY"
curl https://www.supergb.com/cbt/partner-api/v1/attempts/ATTEMPT_ID -H "Authorization: Bearer $GREEN_BRIDGE_KEY"
Un intento tiene este aspecto. questions se incluye desde el plan Growth.
{
"id": "att_...",
"test_id": "TEST_ID",
"candidate_id": "learner-42",
"live": true,
"language": "fr",
"started_at": "2026-10-23T09:02:11Z",
"submitted_at": "2026-10-23T09:41:57Z",
"integrity_events": 0,
"score": 34.0,
"max_score": 40.0,
"percent": 85.0,
"grading_status": "fully_graded",
"questions": [
{"question_id": "q1", "type": "multiple_choice_question", "score": 1.0, "max_score": 1.0}
]
}
grading_status es fully_graded cuando no queda nada por corregir a mano; si no, pending_manual_review o pending_transcription.
Webhooks
Añada hasta 5 direcciones https en su consola. Cada evento se envía como POST firmado y se reintenta durante 3 días hasta que su servidor responda con un estado 2xx.
| Evento | Significado |
|---|---|
attempt.started | El candidato abrió el intento. |
attempt.submitted | El candidato entregó. |
attempt.graded | Todas las notas son definitivas. Se envía de nuevo cada vez que cambia una nota. |
attempt.integrity_flagged | El candidato salió de la prueba o intentó copiar o pegar 3 veces. |
ping | Un evento de prueba enviado desde su consola. |
POST /hooks/green-bridge
Content-Type: application/json
Green-Bridge-Event: attempt.graded
Green-Bridge-Delivery: whd_...
Green-Bridge-Signature: t=1792834917,v1=5f0c...
{
"id": "evt_graded_att_..._1",
"type": "attempt.graded",
"created_at": "2026-10-23T10:21:57Z",
"data": { "id": "att_...", "candidate_id": "learner-42", "score": 34.0, "max_score": 40.0, "grading_status": "fully_graded" }
}
El id de un evento nunca cambia, así que puede ignorar sin riesgo uno que ya haya procesado.
Comprobar la firma
Calcule el HMAC-SHA256 de t, un punto y el cuerpo sin procesar con su secreto de firma, y compárelo con v1. Rechace una marca de tiempo de más de cinco minutos.
Node.js
const crypto = require("crypto");
function isFromGreenBridge(header, rawBody, secret) {
const parts = Object.fromEntries(header.split(",").map(part => part.split("=")));
if (!parts.t || !parts.v1 || Math.abs(Date.now() / 1000 - Number(parts.t)) > 300) {
return false;
}
const expected = crypto.createHmac("sha256", secret).update(parts.t + "." + rawBody).digest("hex");
return expected.length === parts.v1.length
&& crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));
}
Python
import hashlib, hmac, time
def is_from_green_bridge(header, raw_body, secret):
parts = dict(part.split("=", 1) for part in header.split(","))
if "t" not in parts or abs(time.time() - int(parts["t"])) > 300:
return False
signed = parts["t"].encode() + b"." + raw_body
expected = hmac.new(secret.encode(), signed, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, parts.get("v1", ""))
Errores
Los errores llegan como JSON con un código estable:
HTTP/1.1 404 Not Found
{"error": {"code": "test_not_found"}}
| Código | HTTP | Significado |
|---|---|---|
invalid_key |
401 | Falta la clave, no se reconoce o está revocada. |
partner_suspended |
403 | Su cuenta está suspendida. Contáctenos. |
live_keys_need_approval |
403 | Las claves live funcionan cuando su cuenta está aprobada. |
not_on_plan |
403 | Su plan no incluye esto. |
test_not_found |
404 | Ninguna de sus pruebas tiene ese id. |
attempt_not_found |
404 | Ninguno de sus intentos tiene ese id. |
candidate_not_found |
404 | No tiene ningún candidato con ese id. |
test_not_open |
409 | La prueba aún no está abierta o ya se cerró. |
already_submitted |
409 | Este candidato ya entregó esta prueba. |
invalid_request |
400 | Falta un campo o no tiene la forma esperada. |
monthly_limit_reached |
429 | Se agotó la cuota del mes. Las claves de prueba siguen funcionando. |
internal_error |
500 | Algo falló de nuestro lado. Inténtelo de nuevo. |
Límites y datos
- Hasta 300 solicitudes por minuto por cada clave de servidor. Por encima, la respuesta es 429 sin contenido; espere un minuto y vuelva a intentarlo.
- Los intentos live y la corrección con IA se descuentan de la cuota mensual de su plan. Los intentos iniciados con una clave de prueba no cuentan.
Sus datos
Qué guardamos de sus pruebas y candidatos, durante cuánto tiempo y cómo recuperarlo.
- Pruebas y sus preguntas
- Se guardan hasta que las elimine o cierre su cuenta.
- Candidatos
- El id que envíe, y un nombre y un correo solo si los envía. Se guardan durante un año desde la última vez que se vio al candidato.
- Intentos y resultados
- Respuestas, grabaciones, notas y eventos de integridad. Se guardan durante un año desde el inicio del intento y después se borran.
- Pruebas de práctica
- Se guardan durante un año, solo para contar su consumo. La puntuación llega a su página en el evento completed.
- Entregas de webhooks
- Se guardan 30 días, en el registro de entregas de su consola.
- Consumo de la API
- Recuentos diarios por clave, guardados durante 400 días, en la pantalla Consumo de su consola.
Obtenga los resultados en cualquier momento con GET /attempts. Con los planes Growth e Institution también puede descargar los resultados de cada prueba en CSV desde el menú de la prueba en su consola: una fila por intento con la nota de cada pregunta y la respuesta del candidato en las preguntas que usted escribió. Las preguntas del banco de Green Bridge solo muestran sus notas.
Para borrar a un candidato antes:
curl -X POST https://www.supergb.com/cbt/partner-api/v1/candidates/erase \
-H "Authorization: Bearer $GREEN_BRIDGE_KEY" \
-H "Content-Type: application/json" \
-d '{"candidate_id": "learner-42"}'
Un resultado que un candidato guarda en su propia cuenta de Green Bridge le pertenece desde ese momento. Borrar al candidato o cerrar su cuenta no lo elimina.
El propietario de su cuenta puede cerrarla en Sitios web y claves. Las claves y los webhooks se detienen de inmediato y todo lo anterior se borra en un día, así que descargue antes lo que necesite.
¿Necesita algo que los planes no cubren? Use Contáctenos en la pantalla Plan de su consola.