API alábàáṣiṣẹ́pọ̀, ẹ̀dà 1

Ìdánwò nínú ojú-òpó wẹ́ẹ̀bù tiyín

Ẹ fi àwọn ìdánwò àdáṣe wa hàn nínú ojú-ewé yín, tàbí kí ẹ lo ìdánwò tí ẹ kọ fúnra yín: olupin yín bẹ̀rẹ̀ ìjókòó, olùdíje ṣe é nínú ojú-ewé yín, àbájáde sì padà sọ́dọ̀ yín.

Àdírẹ́sì API
https://www.supergb.com/cbt/partner-api/v1

Bí gbogbo rẹ̀ ṣe so pọ̀

  1. Ẹ ṣe kọ́kọ́rọ́ kí ẹ sì fi ojú-òpó wẹ́ẹ̀bù yín kún un nínú console.
  2. Fún ìdánwò àdáṣe, ẹ lẹ̀ àyọkà kóòdù náà mọ́ ojú-ewé yín.
  3. Fún ìdánwò tiyín, olupin yín bẹ̀rẹ̀ ìjókòó, ó sì gba àdírẹ́sì ìbẹ̀rẹ̀.
  4. Ojú-ewé yín ṣí i, olùdíje ṣe ìdánwò náà, àbájáde sì dé ọ̀dọ̀ yín nípasẹ̀ webhook tàbí API.

Kọ́kọ́rọ́

pk_test_ pk_live_
Kọ́kọ́rọ́ tí a lè gbé jáde máa ń wà nínú ojú-ewé wẹ́ẹ̀bù yín. Ìdánwò àdáṣe nìkan ni wọ́n ń ṣí, lórí àwọn ojú-òpó tí ẹ kọ sílẹ̀.
sk_test_ sk_live_
Kọ́kọ́rọ́ olupin ń ṣiṣẹ́ fún àjọ yín. Ẹ tọ́jú wọn sórí olupin yín, ẹ má sì fi ránṣẹ́ sí aṣàwákiri.

Kọ́kọ́rọ́ ìdánwò ń ṣiṣẹ́ lẹ́sẹ̀kẹsẹ̀, a kò sì kà á mọ́ ètò yín. Kọ́kọ́rọ́ live nílò kí a fọwọ́ sí àkọọ́lẹ̀ yín.

Ìdánwò àdáṣe

Ẹ fi script náà kún un lẹ́ẹ̀kan, lẹ́yìn náà ẹ gbé ìdánwò sí ibi tí ẹ bá fẹ́. Fírémù náà máa ń ṣe ìwọ̀n ara rẹ̀ bí àkóónú ṣe rí.

<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>

Ìdánwò náà ni id tí ẹ̀rọ àyọkà kóòdù nínú console yín fi hàn. Ẹ fi mode: "exam" kún un fún ìdánwò onígbà.

Ìdánwò tiyín

Ẹ kọ ìdánwò nínú console lábẹ́ Ìdánwò, kí ẹ sì ṣí wọn. Nígbà tí olùdíje bá ṣetán, olupin yín bẹ̀rẹ̀ ìjókòó:

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 ni id tiyín fún ẹni náà, tí kò ju lẹ́tà 128 lọ. Orúkọ àti ímeèlì kò pọn dandan; ohun tí ẹ fi ránṣẹ́ nìkan ni a ń tọ́jú.

language kò pọn dandan: ọ̀kan nínú de, en, es, fr, yo, ig, ha, nl, pt, sw. Àwọn bọ́tìnnì, aago àti ìránṣẹ́ ìjókòó náà yóò hàn ní èdè yẹn; àwọn ìbéèrè yín yóò wà bí ẹ ṣe kọ wọ́n. Láìsí rẹ̀, ìjókòó náà yóò wà ní Gẹ̀ẹ́sì.

Ìdáhùn náà ní àdírẹ́sì ìbẹ̀rẹ̀ tí ó ń ṣiṣẹ́ lẹ́ẹ̀kan ṣoṣo, láàárín ìṣẹ́jú 10. Ẹ ṣí i nínú ojú-ewé yín:

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>

Lẹ́yìn tí a ṣí i, ìjókòó lè tó wákàtí 24, títún ojú-ewé ṣe sì máa ń bá a lọ. Olùdíje kọ̀ọ̀kan ń ṣe ìdánwò kọ̀ọ̀kan lẹ́ẹ̀kan.

Láti to àwọn ìdánwò yín àti id wọn:

curl https://www.supergb.com/cbt/partner-api/v1/tests -H "Authorization: Bearer $GREEN_BRIDGE_KEY"

Ìránṣẹ́ láti inú fírémù

onEvent ń gba àwọn wọ̀nyí, láti inú fírémù wa nìkan:

Ìṣẹ̀lẹ̀Ìtumọ̀
readyOjú-ewé ti ṣí tán.
resizeGíga àkóónú ti yí padà. Fírémù náà ń tẹ̀lé e fúnra rẹ̀.
completedA ti máàkì ìdánwò àdáṣe kan. detail ní score àti max_score.
submittedA ti fi ìdánwò kan ránṣẹ́. detail ní attempt_id. Ẹ gba àbájáde láti olupin yín, kì í ṣe láti aṣàwákiri.

Àbájáde

Àwọn ìjókòó tí a fi ránṣẹ́, láti tuntun jù lọ, 50 lójú-ewé kan. Ẹ yan nípa test_id, candidate_id tàbí méjèèjì.

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"

Báyìí ni ìjókòó kan ṣe rí. questions wà nínú rẹ̀ láti ètò Growth sókè.

{
  "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 jẹ́ fully_graded nígbà tí kò sí ohun tó kù láti fi ọwọ́ máàkì, bí bẹ́ẹ̀ kọ́ pending_manual_review tàbí pending_transcription.

Webhook

Ẹ fi àdírẹ́sì https tí kò ju 5 lọ kún un nínú console yín. A ń fi ìṣẹ̀lẹ̀ kọ̀ọ̀kan ránṣẹ́ bí POST tí a fọwọ́ sí, a sì ń tún un gbìyànjú fún ọjọ́ 3 títí olupin yín yóò fi dáhùn pẹ̀lú ipò 2xx.

Ìṣẹ̀lẹ̀Ìtumọ̀
attempt.startedOlùdíje ti ṣí ìjókòó náà.
attempt.submittedOlùdíje ti fi ránṣẹ́.
attempt.gradedGbogbo máàkì ti dájú. A tún ń fi ránṣẹ́ nígbàkúùgbà tí máàkì bá yí padà.
attempt.integrity_flaggedOlùdíje kúrò nínú ìdánwò tàbí gbìyànjú láti ṣe ẹ̀dà tàbí lẹ̀ ọ̀rọ̀ nígbà 3.
pingÌṣẹ̀lẹ̀ ìdánwò tí a fi ránṣẹ́ láti console yín.
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" }
}

Id ìṣẹ̀lẹ̀ kì í yí padà, nítorí náà ẹ lè fojú fo èyí tí ẹ ti ṣiṣẹ́ lé lórí láìléwu.

Ṣíṣàyẹ̀wò ìfọwọ́sí

Ẹ ṣírò HMAC-SHA256 ti t, àmì ìdúró kan àti ara ìbéèrè bí ó ṣe wà, pẹ̀lú àṣírí ìfọwọ́sí yín, kí ẹ sì fi wé v1. Ẹ kọ àmì àkókò tí ó ti ju ìṣẹ́jú márùn-ún lọ.

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", ""))

Àṣìṣe

Àṣìṣe máa ń padà bí JSON pẹ̀lú kóòdù tí kì í yí padà:

HTTP/1.1 404 Not Found

{"error": {"code": "test_not_found"}}
Kóòdù HTTP Ìtumọ̀
invalid_key 401 Kọ́kọ́rọ́ kò sí, a kò mọ̀ ọ́n, tàbí a ti fagi lé e.
partner_suspended 403 A ti dá àkọọ́lẹ̀ yín dúró. Ẹ kàn sí wa.
live_keys_need_approval 403 Kọ́kọ́rọ́ live ń ṣiṣẹ́ lẹ́yìn tí a bá fọwọ́ sí àkọọ́lẹ̀ yín.
not_on_plan 403 Ètò yín kò ní èyí nínú.
test_not_found 404 Kò sí ìdánwò yín tí ó ní id yẹn.
attempt_not_found 404 Kò sí ìjókòó yín tí ó ní id yẹn.
candidate_not_found 404 Ẹ kò ní olùdíje kankan pẹ̀lú id yẹn.
test_not_open 409 Ìdánwò náà kò tíì ṣí, tàbí ó ti tì.
already_submitted 409 Olùdíje yìí ti fi ìdánwò yìí ránṣẹ́ tẹ́lẹ̀.
invalid_request 400 Àyè kan kò sí tàbí kò rí bí a ṣe ń retí.
monthly_limit_reached 429 Ìpín oṣù yìí ti tán. Kọ́kọ́rọ́ ìdánwò ṣì ń ṣiṣẹ́.
internal_error 500 Nǹkan kan ṣẹlẹ̀ ní ọ̀dọ̀ wa. Ẹ tún gbìyànjú.

Ààlà àti dátà

  • Ìbéèrè tí kò ju 300 lọ ní ìṣẹ́jú kan fún kọ́kọ́rọ́ olupin kọ̀ọ̀kan. Tí ó bá ju bẹ́ẹ̀ lọ, ìdáhùn jẹ́ 429 láìsí àkóónú; ẹ dúró fún ìṣẹ́jú kan kí ẹ tún gbìyànjú.
  • Ìjókòó live àti máàkì AI ń ka mọ́ ìpín oṣooṣù ètò yín. A kò ka ìjókòó tí a fi kọ́kọ́rọ́ ìdánwò bẹ̀rẹ̀.

Dátà yín

Ohun tí a ń tọ́jú nípa àwọn ìdánwò àti olùdíje yín, fún ìgbà tí ó tó, àti bí ẹ ṣe lè rí i gbà padà.

Àwọn ìdánwò àti ìbéèrè yín
A ń tọ́jú wọn títí ẹ ó fi pa wọ́n rẹ́ tàbí tí ẹ ó fi ti àkáǹtì yín pa.
Àwọn olùdíje
Id tí ẹ fi ránṣẹ́, àti orúkọ àti ímeèlì bí ẹ bá fi wọ́n ránṣẹ́ nìkan. A ń tọ́jú wọn fún ọdún kan lẹ́yìn ìgbà tí a rí olùdíje náà kẹ́yìn.
Ìjókòó àti àbájáde
Ìdáhùn, ohùn tí a gbà sílẹ̀, máàkì àti ìṣẹ̀lẹ̀ òtítọ́. A ń tọ́jú wọn fún ọdún kan lẹ́yìn tí ìjókòó bẹ̀rẹ̀, lẹ́yìn náà a pa wọ́n rẹ́.
Ìdánwò àdáṣe
A ń tọ́jú wọn fún ọdún kan, láti ka ìlò yín nìkan. Máàkì náà ń dé ojú-ewé yín nínú ìṣẹ̀lẹ̀ completed.
Ìfiránṣẹ́ webhook
A ń tọ́jú wọn fún ọjọ́ 30, nínú àkọsílẹ̀ ìfiránṣẹ́ ti dáṣíbọ́ọ̀dù yín.
Ìlò API
Iye ojoojúmọ́ fún kọ́kọ́rọ́ kọ̀ọ̀kan, tí a ń tọ́jú fún ọjọ́ 400, lójú-ewé Ìlò nínú dáṣíbọ́ọ̀dù yín.

Ẹ gba àbájáde nígbàkígbà pẹ̀lú GET /attempts. Lórí ètò Growth àti Institution, ẹ tún lè ṣe ìgbàsílẹ̀ àbájáde ìdánwò kọ̀ọ̀kan gẹ́gẹ́ bí CSV láti inú àkójọ ìdánwò náà nínú dáṣíbọ́ọ̀dù yín: ìlà kan fún ìjókòó kọ̀ọ̀kan pẹ̀lú máàkì ìbéèrè kọ̀ọ̀kan, àti ìdáhùn olùdíje lórí àwọn ìbéèrè tí ẹ kọ. Àwọn ìbéèrè láti inú àkójọ ìbéèrè Green Bridge ń fi máàkì wọn nìkan hàn.

Láti pa olùdíje kan rẹ́ ní kíákíá:

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"}'

Àbájáde tí olùdíje bá fi pamọ́ sínú àkáǹtì Green Bridge tirẹ̀ di tirẹ̀ láti ìgbà náà lọ. Pípa olùdíje náà rẹ́ tàbí títi àkáǹtì yín pa kò ní yọ ọ́ kúrò.

Ẹni tí ó ni àkáǹtì yín lè tì í pa lábẹ́ Wẹ́ẹ̀bùsáìtì àti kọ́kọ́rọ́. Àwọn kọ́kọ́rọ́ àti webhook dúró lẹ́sẹ̀kẹsẹ̀, a sì pa gbogbo ohun tí ó wà lókè rẹ́ láàárín ọjọ́ kan, nítorí náà ẹ kọ́kọ́ ṣe ìgbàsílẹ̀ ohun tí ẹ nílò.

Àwọn ìlérí tí ó wà lẹ́yìn èyí wà nínú Àwọn Alábàáṣiṣẹ́pọ̀ àti Ìṣàkóso Dátà nínú Awọn ofin ati Awọn ipo wa.

Ṣé ẹ nílò ohun tí àwọn ètò kò bò? Ẹ lo Kàn sí wa lórí ojú-ewé Ètò nínú console yín.