ডেভেলপার
দুটো পথ: এমবেড (চাবি লাগে না, সব প্ল্যানে) আর REST API (ইনস্টিটিউশন/প্রিমিয়াম প্ল্যানে)।
১) এমবেড — কপি-পেস্ট, ফ্রি
যেকোনো ওয়েবসাইট, WordPress, Google Sites বা LMS-এ বসান। হোস্ট-পাতার শেয়ার-বারে "এমবেড" বোতাম চাপলেই কোডটা কপি হয়ে যায়।
জয়েন-কার্ড (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>ফলাফল তালিকা
<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>খেলা ফ্রেমের ভেতরেই (নতুন)
<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>- • জয়েন-কার্ডে খেলা নতুন ট্যাবে খোলে; আর উপরের /play এমবেডে খেলা ফ্রেমের ভেতরেই চলে — লম্বা ফ্রেম (কমপক্ষে 640px) আর `allow="autoplay; fullscreen"` দিন।
- • কিছু ব্রাউজার (পুরনো Safari, লকডাউন-মোড) এমবেড-করা পাতার স্টোরেজ বন্ধ রাখে — তখন পাতাটা নিজেই "নতুন ট্যাবে খেলুন" বোতাম দেখায়, ছাত্র মাঝপথে আটকায় না।
- • `lang=bn` বা `lang=en` — আপনি যে ভাষায় কোড কপি করবেন, দর্শক সেটাই দেখবে।
- • আপনার LMS যদি `sandbox` অ্যাট্রিবিউট ব্যবহার করে, তাতে `allow-same-origin allow-scripts allow-popups` রাখুন — `allow-same-origin` ছাড়া ব্রাউজার পাতাটিকে স্টোরেজ-বিহীন "opaque" করে দেয়, খেলা চালানোই যায় না।
- • "Powered by কুইজঝড়" লেখাটা white-label প্ল্যানে থাকে না।
২) REST API
ওয়ার্কস্পেসের মালিক ড্যাশবোর্ড → ডেভেলপার থেকে চাবি বানাবেন। চাবিটা একবারই দেখানো হয়।
curl -H "Authorization: Bearer qj_live_..." \
-H "X-API-Version: 1" \
https://quizjhor.com/api/v1/me| এন্ডপয়েন্ট | কী দেয় |
|---|---|
GET /api/v1/me | চাবি ও ওয়ার্কস্পেস যাচাই — প্রথম কলেই সব গেট প্রমাণ হয় |
GET /api/v1/quizzes | কুইজ-তালিকা (শিরোনাম, বিষয়, প্রশ্ন-সংখ্যা) |
GET /api/v1/games | সেশন-তালিকা; `?since=` দিয়ে ইনক্রিমেন্টাল সিঙ্ক |
GET /api/v1/games/:id/results | এক সেশনের ফল — নাম, নম্বর, র্যাংক, পার্সেন্টাইল |
POST /api/v1/games | নতুন সেশন চালু (write-চাবি লাগে) — ফেরত দেয় PIN, joinUrl, embedUrl |
নিয়ম
- •
?limit=— ডিফল্ট 50, সর্বোচ্চ 100। - • চলমান সেশনে `results` হয় `null` — পরীক্ষা শেষ না হওয়া পর্যন্ত ফল দেওয়া হয় না।
- • চাবি যে ওয়ার্কস্পেসের, শুধু তারই ডেটা পড়া যায়; অন্যের আইডি দিলে ৪০৪।
- • অভিভাবকের ফোন, রোল-নম্বর বা সনদ-কোড API-তে কখনো যায় না।
- • রেসপন্স-হেডারে সার্ভারের API-ভার্সন থাকে; নতুন ফিল্ড যোগ হতে পারে, পুরনো ফিল্ডের নাম বদলায় না।
- • চাবি ডিফল্টে শুধু পড়তে পারে। সেশন তৈরি করতে চাবি বানানোর সময় "গেম তৈরির অনুমতি" চালু করুন।
- • সেশন তৈরিতে ওয়েবের সব নিয়মই খাটে — প্ল্যান-সীমা, কুইজে প্রশ্ন থাকা, খালি প্রশ্ন না থাকা। একই কুইজে চলমান গেম থাকলে নতুন PIN না বানিয়ে সেটাই ফেরত আসে।
এররগুলো
- • 401 — চাবি নেই, ভুল, বা বাতিল করা।
- • 403 — চাবি ঠিক আছে কিন্তু প্ল্যানে API নেই, ওয়ার্কস্পেস স্থগিত, বা scope নেই।
- • 409 — সেশন তৈরিতে: ওয়ার্কস্পেসে কোনো হোস্ট নেই।
- • 429 — খুব দ্রুত অনুরোধ — একটু ধীরে।
৩) Webhook — ফল আপনা-আপনি
ড্যাশবোর্ড → ডেভেলপার-এ আপনার https ঠিকানা দিন। পরীক্ষা শেষ হলেই আমরা POST করব — বারবার API কল করার দরকার নেই।
POST <your-url>
X-QJ-Event: game.ended
X-QJ-Timestamp: 1730000000000
X-QJ-Signature: <hex>
{"event":"game.ended","deliveryId":"...","game":{...},"results":[...]}স্বাক্ষর যাচাই
const expected = crypto.createHmac("sha256", secret)
.update(timestamp + "." + rawBody).digest("hex");
// crypto.timingSafeEqual(expected, headerSignature)- • ২০০-রেঞ্জ উত্তর না পেলে ৫ বার পর্যন্ত আবার চেষ্টা হয়, তারপর ব্যর্থ হিসেবে দেখানো হয়।
- • এক সেশনের এক ইভেন্ট একবারই পাঠানো হয় (deliveryId দিয়ে মিলিয়ে নিতে পারেন)।
- • URL বদলালে নতুন সিক্রেট তৈরি হয়; পুরনো সিক্রেট আর বৈধ নয়।