আপনার প্রতিষ্ঠানের API address ও সীমিত scope-এর credential ব্যবহার করুন। read request দিয়ে শুরু করে response যাচাই করুন; source control ও documentation-এর উদাহরণের বাইরে secret রাখুন।
Quire-এর একটি public API আছে: OpenAPI 3.1 document-এ বর্ণিত HTTPS-এর ওপর REST, event-এর জন্য signed webhook এবং AI assistant-এর জন্য MCP server। API reference-এ প্রতিটি endpoint ও event তালিকাভুক্ত।
ঠিকানা
প্রতিটি প্রতিষ্ঠানের নিজস্ব address আছে এবং API তার অধীনে থাকে:
https://acme.quirelms.com/api/v1/coursesCredential-ই প্রতিষ্ঠান নির্ধারণ করে। এক প্রতিষ্ঠানের address-এ অন্য প্রতিষ্ঠানের key ব্যবহার করলে তা প্রত্যাখ্যাত হয়।
যেকোনো প্রতিষ্ঠানের address-এ /api/v1/openapi.json-এ OpenAPI document পাওয়া যায়, তাই client generator সবসময় ব্যবহৃত সংস্করণ দেখতে পায়।
Authentication
API key script ও server-to-server integration-এর জন্য। প্রশাসক /admin/integrations/api-keys-এ একটি তৈরি করে scope বেছে নেন এবং key একবারই দেখতে পান। bearer token হিসেবে পাঠান:
curl -H "Authorization: Bearer qk_live_..." https://acme.quirelms.com/api/v1/users?limit=50Key-এর শুরু qk_live_ অথবা qk_test_ দিয়ে। প্রতিটি integration-কে নিজস্ব key দিন।
OAuth 2.1 sign-in করা ব্যক্তির পরিচয়ে কাজ করা application-এর জন্য। /admin/integrations/oauth-clients-এ client নিবন্ধন করে PKCE-সহ authorization code flow (/oauth/authorize, /oauth/token) অথবা machine client-এর জন্য client credentials ব্যবহার করুন। Discovery-র ঠিকানা /.well-known/oauth-authorization-server। Scope token কী করতে পারবে তা সীমিত করে; ব্যক্তির অনুমতির বাইরে কিছু করতে দেয় না।
Scope হলো resource:read, resource:write ও resource:delete; যেমন courses:read বা enrolments:write। চারটি privileged scope consent screen-এ সতর্কতাসহ দেখানো হয়: audit:read, roles:write, tenants:write এবং users:delete।
Request
- Pagination: প্রতিটি list cursor দিয়ে paginated।
limitদিন;next_cursorনিন (pageobject-এ থাকে) এবংcursorহিসেবে পাঠান, যতক্ষণhas_moretrue থাকে (নিচে উদাহরণ)। offset নেই। - এরপরের পরিবর্তন:
updated_sinceএকটি সময়ের পর বদলানো তথ্য দেয়। কী মুছেছে জানতে এটিinclude_deleted=true-এর সঙ্গে ব্যবহার করুন অথবা/<resource>/deletionsপড়ুন। - বাহ্যিক identifier: বেশিরভাগ resource-এ নিজের
external_idদেওয়া যায়;/<resource>/ext:{external_id}দিয়ে সেটি পড়া বা upsert করা যায়, তাই sync-এ Quire-এর identifier রাখতে হয় না। - Idempotency:
Idempotency-KeyheaderPOST,PATCHওDELETE-এ পাঠান। একই key দিয়ে retry করলে কাজ দুবার না করে প্রথম response ফেরত দেয়। Bulk endpoint-এ এটি বাধ্যতামূলক। - সংস্করণ: major version path-এ (
/v1) থাকে। এর মধ্যে breaking change-গুলো তারিখ দেওয়া revision;Quire-Versionheader দিয়ে বেছে নিন, যেমনQuire-Version: 2026-09-20। Header না দিলে credential দেওয়ার সময় যে revision বর্তমান ছিল সেটি পাবেন।
একটি list-এর page:
{"data": [...], "page": {"next_cursor": "eyJ2Ijox...", "has_more": true, "limit": 100}}Error
প্রতিটি error হলো RFC 9457 problem document:
{"type": "https://quire.com/errors/enrolment.seat_limit_reached",
"title": "Seat limit reached", "status": 409,
"code": "enrolment.seat_limit_reached", "category": "conflict",
"detail": "The course has no seats left, so this enrolment was not created. ...",
"request_id": "01JB7XQK4Z..."}code দেখে branch করুন, এটি স্থিতিশীল; detail মানুষের জন্য লেখা, দেখানো নিরাপদ এবং বদলাতে পারে। code চিনতে না পারলে category অনুযায়ী ভাগ করুন:
| Category | Status | Retry |
|---|---|---|
validation |
422, errors-এ field-এর বিবরণসহ |
না |
authentication |
401 | না |
authorization |
403 | না |
not_found |
404 | না |
conflict |
409 | কখনো |
precondition |
412 | না |
quota |
plan-এর জন্য 402, আকারের জন্য 413 | না |
rate_limit |
429, Retry-After-সহ |
হ্যাঁ |
upstream |
502 বা 504 | হ্যাঁ |
internal |
500 | হ্যাঁ |
Support-এর সঙ্গে যোগাযোগ করলে request_id দিন।
Webhook
/admin/webhooks-এ অথবা API-র /webhook_subscriptions দিয়ে subscribe করুন। event-এর নাম (enrolment.created), area (enrolment.*) অথবা সব event (*) বেছে নিন। Quire প্রথমে webhook.ping পাঠায়; endpoint উত্তর দিলে subscription চালু হয়।
Delivery-গুলো Standard Webhooks specification অনুসরণ করে:
POST /hooks/quire
webhook-id: 01JB7XQK4Z8FQ2M3N4P5R6S7T8
webhook-timestamp: 1790000000
webhook-signature: v1,g0hM9SsE+OTPJTGt/tmIKtSyZlE3uFJELVlNIOLJ1OE=Delivery যাচাই করতে:
- JSON parse করার আগে পাওয়া হুবহু byte থেকে
{webhook-id}.{webhook-timestamp}.{raw body}string তৈরি করুন। - subscription secret দিয়ে এর ওপর HMAC-SHA256 হিসাব করে base64 করুন।
v1,-এর প্রতিটি value-কেwebhook-signature-এর সঙ্গে constant time-এ তুলনা করুন। Secret rotation চললে দুটি থাকতে পারে; যেকোনো একটির সঙ্গে মিললেই বৈধ।- আপনার clock থেকে পাঁচ মিনিটের বেশি ব্যবধান থাকা timestamp প্রত্যাখ্যান করুন।
import { createHmac, timingSafeEqual } from 'node:crypto';
function verify(secret, id, timestamp, rawBody, header) {
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;
const expected = createHmac('sha256', Buffer.from(secret.replace(/^whsec_/, ''), 'base64'))
.update(`${id}.${timestamp}.${rawBody}`).digest();
return header.split(' ').some((part) => {
const [version, value] = part.split(',');
const given = Buffer.from(value ?? '', 'base64');
return version === 'v1' && given.length === expected.length && timingSafeEqual(given, expected);
});
}webhook-id ধরে duplicate delivery বাদ দিন: একই delivery একাধিকবার আসতে পারে। Body-তে identifier ও সংক্ষিপ্ত সারাংশ থাকে; resource-এর বর্তমান অবস্থা পেতে সেটি fetch করুন। ব্যর্থ delivery-তে সর্বোচ্চ 72 ঘণ্টা backoff দিয়ে retry হয় এবং delivery log থেকে আবার চালানো যায়।
MCP
Quire-এর MCP server streamable HTTP দিয়ে প্রতিষ্ঠানের address-এ /mcp-তে থাকে। MCP client /.well-known/oauth-protected-resource থেকে OAuth server খুঁজে পায়; যেকোনো OAuth client-এর মতো ব্যক্তি sign in করে সম্মতি দেন। Tool-গুলো সেই ব্যক্তির অনুমতিতে তাঁর পরিচয়ে কাজ করে, আর ধ্বংসাত্মক tool-এ নিশ্চিতকরণ চাওয়া হয়। /admin/integrations/mcp-এ প্রশাসকেরা কোন tool পাওয়া যাবে তা বেছে নেন।
Plan ও API
API entitlement-এর মধ্যে API key, OAuth client, webhook ও MCP server পড়ে এবং প্রতিটি standard plan-এ এটি থাকে। যে plan-এ এটি নেই, সেখানে key, client বা subscription তৈরি প্রত্যাখ্যাত হয়, REST write ও MCP connection প্রত্যাখ্যাত হয়, তবে data export করা যায় বলে REST read চলে। প্রত্যাখ্যানের problem document-এ commerce.plan_entitlement code থাকে, যার category precondition।
Extension
Quire-এর নিজস্ব activity type, block, enrolment method, sign-in method, question type, report, theme ও integration একই extension registry-তে ঘোষণা করা হয়; নিজে host করা install-এ অতিরিক্ত extension যোগ করা যায়। Extension compile করে যুক্ত হয়: runtime plugin loader নেই এবং hosted প্রতিষ্ঠান কোনো extension যোগ করতে পারে না। /admin/extensions-এ প্রশাসকেরা প্রতিষ্ঠানের জন্য প্রতিটি extension চালু বা বন্ধ করেন (দেখুন প্রশাসক নির্দেশিকা)।
Extension লিখতে packages/integration/extensions/src/sample.ts-এর sample block ও theme দিয়ে শুরু করুন। Extension point বেছে নিয়ে points.ts-এ তার contract পড়ুন, তারপর id, version, licence, কী সরবরাহ ও প্রয়োজন করে এবং প্রতিষ্ঠান এটি বন্ধ করতে পারবে কি না—এসব দিয়ে extension ঘোষণা করুন। Web application ও worker যেখানে একত্র হয় সেখানে নিবন্ধন করুন, যাতে উভয়ের registry মেলে। Build-এর সময় এবং register call করলে registry প্রতিটি point-এর নিজস্ব নিয়ম পরীক্ষা করে; কোনো সমস্যাসহ অবৈধ set প্রত্যাখ্যান করে এবং প্রত্যাখ্যান করলে registry অপরিবর্তিত রাখে। Extension-এর test-এ যাচাই করা উচিত extensionContractProblems ফাঁকা এবং এটি বন্ধ করলে এর প্রভাবিত বিষয় বদলে যায়।