QuizJhor

Developers

Two paths: embeds (no key needed, every plan) and the REST API (Institution/Premium plans).

1) Embeds — copy-paste, free

Paste into any website, WordPress, Google Sites or LMS. The "Embed" button on the host screen copies the code for you.

Join card (enter by PIN)
<iframe src="https://quizjhor.com/embed/join?pin=482013&lang=bn"
        width="100%" height="380" style="border:0;border-radius:16px"
        title="QuizJhor" loading="lazy"></iframe>
Results list
<iframe src="https://quizjhor.com/embed/m/<token>?lang=bn"
        width="100%" height="520" style="border:0;border-radius:16px"
        title="QuizJhor results" loading="lazy"></iframe>
Play inside the frame (new)
<iframe src="https://quizjhor.com/play?pin=482013&lang=bn"
        width="100%" height="720" style="border:0;border-radius:16px"
        title="QuizJhor" allow="autoplay; fullscreen" loading="lazy"></iframe>

2) REST API

The workspace owner creates a key from Dashboard → Developers. The key is shown only once.

curl -H "Authorization: Bearer qj_live_..." \
     -H "X-API-Version: 1" \
     https://quizjhor.com/api/v1/me
EndpointWhat it returns
GET /api/v1/meVerify key & workspace — proves every gate in one call
GET /api/v1/quizzesList quizzes (title, subject, question count)
GET /api/v1/gamesList sessions; `?since=` for incremental sync
GET /api/v1/games/:id/resultsResults for one session — name, score, rank, percentile
POST /api/v1/gamesStart a session (needs a write key) — returns PIN, joinUrl, embedUrl

Rules

Errors

3) Webhook — results pushed to you

Set your https URL in Dashboard → Developers. When an assessment finishes we POST to it — no polling.

POST <your-url>
X-QJ-Event: game.ended
X-QJ-Timestamp: 1730000000000
X-QJ-Signature: <hex>

{"event":"game.ended","deliveryId":"...","game":{...},"results":[...]}
Verify the signature
const expected = crypto.createHmac("sha256", secret)
  .update(timestamp + "." + rawBody).digest("hex");
// crypto.timingSafeEqual(expected, headerSignature)
Create a keySee plans