Hoe het samenhangt
- Maak sleutels aan en voeg uw websites toe in de console.
- Plak voor oefentoetsen het fragment in uw pagina.
- Voor eigen toetsen start uw server een afname en krijgt een startadres.
- Uw pagina opent dat, de kandidaat maakt de toets en het resultaat bereikt u via een webhook of de API.
Sleutels
pk_test_pk_live_- Publiceerbare sleutels horen in uw webpagina's. Ze openen alleen oefentoetsen op de websites die u hebt opgegeven.
sk_test_sk_live_- Serversleutels handelen namens uw organisatie. Bewaar ze op uw server en stuur ze nooit naar een browser.
Testsleutels werken meteen en tellen niet mee voor uw abonnement. Live-sleutels vragen een goedgekeurd account.
Oefentoetsen
Voeg het script één keer toe en plaats een toets waar u wilt. Het kader past zich zelf aan de inhoud aan.
<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>
De toets is de id uit de fragmentbouwer in uw console. Voeg mode: "exam" toe voor examenomstandigheden met tijdslimiet.
Uw eigen toetsen
Maak toetsen in de console onder Toetsen en zet ze open. Zodra een kandidaat klaar is, start uw server een afname:
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 is uw eigen id voor de persoon, maximaal 128 tekens. Naam en e-mail zijn optioneel; we bewaren alleen wat u stuurt.
language is optioneel: een van de, en, es, fr, yo, ig, ha, nl, pt, sw. Knoppen, timer en meldingen van de afname verschijnen in die taal; uw vragen blijven zoals u ze schreef. Zonder dit veld is de afname in het Engels.
Het antwoord bevat een startadres dat één keer werkt, binnen 10 minuten. Open het op uw pagina:
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>
Eenmaal geopend duurt een afname tot 24 uur en vernieuwen hervat hem. Elke kandidaat maakt elke toets één keer.
Zo vraagt u uw toetsen en hun id's op:
curl https://www.supergb.com/cbt/partner-api/v1/tests -H "Authorization: Bearer $GREEN_BRIDGE_KEY"
Berichten uit het kader
onEvent ontvangt deze berichten, en alleen uit ons kader:
| Gebeurtenis | Betekenis |
|---|---|
ready | De pagina is geladen. |
resize | De hoogte van de inhoud is veranderd. Het kader volgt vanzelf. |
completed | Een oefentoets is nagekeken. detail bevat score en max_score. |
submitted | Een toets is ingeleverd. detail bevat attempt_id. Haal het resultaat op via uw server, niet in de browser. |
Resultaten
Ingeleverde afnames, nieuwste eerst, 50 per pagina. Filter op test_id, candidate_id of beide.
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"
Een afname ziet er zo uit. questions zit erbij vanaf het Growth-abonnement.
{
"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 is fully_graded zodra er niets meer met de hand na te kijken is, anders pending_manual_review of pending_transcription.
Webhooks
Voeg tot 5 https-adressen toe in uw console. Elke gebeurtenis gaat als ondertekende POST en wordt 3 dagen opnieuw verstuurd tot uw server antwoordt met een 2xx-status.
| Gebeurtenis | Betekenis |
|---|---|
attempt.started | De kandidaat heeft de afname geopend. |
attempt.submitted | De kandidaat heeft ingeleverd. |
attempt.graded | Alle cijfers staan vast. Opnieuw verstuurd telkens als een cijfer verandert. |
attempt.integrity_flagged | De kandidaat heeft de toets verlaten of 3 keer geprobeerd te kopiëren of te plakken. |
ping | Een testgebeurtenis vanuit uw console. |
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" }
}
De id van een gebeurtenis verandert nooit, dus een gebeurtenis die u al hebt verwerkt kunt u gerust negeren.
De handtekening controleren
Bereken HMAC-SHA256 van t, een punt en de onbewerkte inhoud met uw ondertekeningsgeheim en vergelijk dat met v1. Weiger een tijdstempel ouder dan vijf minuten.
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", ""))
Fouten
Fouten komen terug als JSON met een vaste code:
HTTP/1.1 404 Not Found
{"error": {"code": "test_not_found"}}
| Code | HTTP | Betekenis |
|---|---|---|
invalid_key |
401 | De sleutel ontbreekt, is onbekend of ingetrokken. |
partner_suspended |
403 | Uw account is geschorst. Neem contact met ons op. |
live_keys_need_approval |
403 | Live-sleutels werken zodra uw account is goedgekeurd. |
not_on_plan |
403 | Uw abonnement bevat dit niet. |
test_not_found |
404 | Geen van uw toetsen heeft die id. |
attempt_not_found |
404 | Geen van uw afnames heeft die id. |
candidate_not_found |
404 | U hebt geen kandidaat met die id. |
test_not_open |
409 | De toets is nog niet open of al gesloten. |
already_submitted |
409 | Deze kandidaat heeft deze toets al ingeleverd. |
invalid_request |
400 | Er ontbreekt een veld of het heeft niet de verwachte vorm. |
monthly_limit_reached |
429 | Het tegoed van deze maand is op. Testsleutels werken nog. |
internal_error |
500 | Er ging bij ons iets mis. Probeer het opnieuw. |
Limieten en gegevens
- Tot 300 verzoeken per minuut per serversleutel. Daarboven is het antwoord 429 zonder inhoud; wacht een minuut en probeer het opnieuw.
- Live-afnames en AI-beoordeling tellen mee voor het maandtegoed van uw abonnement. Afnames gestart met een testsleutel tellen niet.
Uw gegevens
Wat we bewaren over uw toetsen en kandidaten, hoe lang, en hoe u het terugkrijgt.
- Toetsen en uw vragen
- Bewaard totdat u ze verwijdert of uw account opheft.
- Kandidaten
- De id die u stuurt, en een naam en e-mail alleen als u die stuurt. Bewaard tot een jaar nadat de kandidaat voor het laatst is gezien.
- Afnames en resultaten
- Antwoorden, opnames, punten en integriteitsgebeurtenissen. Bewaard tot een jaar na de start van de afname, daarna gewist.
- Oefentoetsen
- Een jaar bewaard, alleen om uw gebruik te tellen. De score bereikt uw pagina in de gebeurtenis completed.
- Webhook-leveringen
- 30 dagen bewaard, in het leveringslogboek van uw console.
- API-gebruik
- Dagelijkse aantallen per sleutel, 400 dagen bewaard, op het scherm Gebruik van uw console.
Haal resultaten op elk moment op met GET /attempts. Met de abonnementen Growth en Institution kunt u de resultaten van elke toets ook als CSV downloaden via het menu van de toets in uw console: één regel per afname met de punten voor elke vraag, en het antwoord van de kandidaat op de vragen die u zelf hebt geschreven. Vragen uit de Green Bridge-vragenbank tonen alleen hun punten.
Zo wist u een kandidaat eerder:
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"}'
Een resultaat dat een kandidaat in zijn eigen Green Bridge-account opslaat, is vanaf dat moment van hem. Het wissen van de kandidaat of het opheffen van uw account verwijdert het niet.
De eigenaar van uw account kan het opheffen onder Websites en sleutels. Sleutels en webhooks stoppen meteen en alles hierboven wordt binnen een dag gewist, dus download eerst wat u nodig hebt.
Iets nodig wat de abonnementen niet dekken? Gebruik Contact op het scherm Abonnement in uw console.