نشانی API سازمان و اعتبارنامهای با دامنهٔ دسترسی مشخص را به کار ببرید. با درخواست خواندن آغاز کنید، پاسخ را بررسی کنید و رازها را بیرون از کنترل نسخه و نمونههای مستندات نگه دارید.
Quire یک API عمومی دارد: REST روی HTTPS که در سند OpenAPI 3.1 شرح داده شده است؛ برای رویدادها وبهوک امضاشده دارد و برای دستیارهای هوش مصنوعی سرور MCP. مرجع API همهٔ endpointها و رویدادها را فهرست میکند.
نشانیها
هر سازمان نشانی خودش را دارد و API زیر همان نشانی است:
https://acme.quirelms.com/api/v1/coursesاعتبارنامه سازمان را تعیین میکند. استفاده از کلید یک سازمان در نشانی سازمان دیگر رد میشود.
سند OpenAPI در نشانی هر سازمان از /api/v1/openapi.json ارائه میشود، پس مولدهای کارخواه همیشه نسخهای را میبینند که فراخوانی میکنید.
احراز هویت
کلیدهای API برای اسکریپتها و یکپارچهسازیهای سروربهسرورند. مدیر در /admin/integrations/api-keys کلیدی میسازد، دامنههایش را انتخاب میکند و فقط یکبار میبیندش. آن را بهصورت bearer token بفرستید:
curl -H "Authorization: Bearer qk_live_..." https://acme.quirelms.com/api/v1/users?limit=50کلیدها با qk_live_ یا qk_test_ آغاز میشوند. برای هر یکپارچهسازی کلید جداگانهای بسازید.
OAuth 2.1 برای برنامههایی است که از طرف شخصی واردشده عمل میکنند. در /admin/integrations/oauth-clients کارخواهی ثبت کنید و سپس از جریان authorization code همراه PKCE (/oauth/authorize، /oauth/token) یا اعتبارنامهٔ کارخواه برای کارخواه ماشینی استفاده کنید. کشف در /.well-known/oauth-authorization-server است. دامنه، کارهایی را که token میتواند انجام دهد محدود میکند و هرگز اجازهای فراتر از توان آن شخص نمیدهد.
دامنهها resource:read، resource:write و resource:delete هستند؛ مانند courses:read یا enrolments:write. چهار دامنه امتیاز ویژه دارند و در صفحهٔ رضایت همراه هشدار نشان داده میشوند: audit:read، roles:write، tenants:write و users:delete.
درخواستها
- صفحهبندی: همهٔ فهرستها با cursor صفحهبندی میشوند.
limitرا بفرستید وnext_cursorازpageرا بهعنوانcursorبفرستید، تا وقتیhas_moreدرست است (نمونه در پایین). offset وجود ندارد. - تغییرها از زمانی مشخص:
updated_sinceمواردی را برمیگرداند که پس از زمان مشخصی تغییر کردهاند. آن را باinclude_deleted=trueهمراه کنید یا/<resource>/deletionsرا بخوانید تا بفهمید چه چیزی برداشته شده است. - شناسههای بیرونی: بیشتر منابع
external_idخودتان را میپذیرند و/<resource>/ext:{external_id}بر پایهٔ آن میخواند یا upsert میکند؛ پس برای همگامسازی لازم نیست شناسههای Quire را ذخیره کنید. - تکرارپذیری: سرآیند
Idempotency-Keyرا برای درخواستهایPOST،PATCHوDELETEبفرستید. تکرار درخواست با همان کلید، پاسخ نخست را میدهد و کار را دوباره انجام نمیدهد. endpointهای گروهی به این کلید نیاز دارند. - نسخهها: نسخهٔ اصلی در مسیر است (
/v1). درون آن، هر تغییر ناسازگار بازنگری تاریخداری است و با سرآیندQuire-Versionانتخاب میشود؛ برای نمونهQuire-Version: 2026-09-20. اگر سرآیند نفرستید، بازنگری هنگام صدور اعتبارنامه را میگیرید.
یک صفحه از فهرست:
{"data": [...], "page": {"next_cursor": "eyJ2Ijox...", "has_more": true, "limit": 100}}خطاها
هر خطا یک problem document به قالب RFC 9457 است:
{"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 تصمیم بگیرید؛ این مقدار ثابت است. detail برای افراد نوشته شده، نمایش آن امن است و ممکن است تغییر کند. اگر کدی را نشناختید، بر پایهٔ category دستهبندی کنید:
| دسته | وضعیت | تکرار درخواست |
|---|---|---|
validation |
422، با جزئیات فیلد در errors |
خیر |
authentication |
401 | خیر |
authorization |
403 | خیر |
not_found |
404 | خیر |
conflict |
409 | گاهی |
precondition |
412 | خیر |
quota |
402 برای طرح، 413 برای اندازه | خیر |
rate_limit |
429، با Retry-After |
بله |
upstream |
502 یا 504 | بله |
internal |
500 | بله |
هنگام تماس با پشتیبانی request_id را بیاورید.
وبهوکها
در /admin/webhooks یا از راه API در /webhook_subscriptions مشترک شوید. رویدادها را بر پایهٔ نام (enrolment.created)، حوزه (enrolment.*) یا همه (*) انتخاب کنید. Quire ابتدا webhook.ping میفرستد؛ پس از پاسخ endpoint شما اشتراک آغاز میشود.
تحویلها از مشخصات Standard Webhooks پیروی میکنند:
POST /hooks/quire
webhook-id: 01JB7XQK4Z8FQ2M3N4P5R6S7T8
webhook-timestamp: 1790000000
webhook-signature: v1,g0hM9SsE+OTPJTGt/tmIKtSyZlE3uFJELVlNIOLJ1OE=برای اعتبارسنجی یک تحویل:
- از بایتهای دقیق دریافتی و پیش از هرگونه تجزیهٔ JSON، رشتهٔ
{webhook-id}.{webhook-timestamp}.{raw body}را بسازید. - با راز اشتراک HMAC-SHA256 را روی آن محاسبه و نتیجه را به base64 تبدیل کنید.
- با مقایسهٔ ثابتزمان، آن را با هر مقدار
v1,درwebhook-signatureبسنجید. هنگام چرخش راز ممکن است دو مقدار باشد؛ تطبیق هرکدام معتبر است. - 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 موارد تکراری را حذف کنید؛ ممکن است یک تحویل بیش از یکبار برسد. بدنه شناسهها و خلاصهای کوتاه دارد؛ منبع را بگیرید تا وضعیت کنونیاش را بخوانید. تحویل ناموفق تا ۷۲ ساعت با فاصلهٔ فزاینده دوباره فرستاده میشود و از گزارش تحویل میتوان آن را بازپخش کرد.
MCP
سرور MCP کوایر روی نشانی سازمان در /mcp و از راه HTTP جریانی در دسترس است. کارخواه MCP سرور OAuth را از /.well-known/oauth-protected-resource کشف میکند و شخص مانند هر کارخواه OAuth دیگری وارد میشود و رضایت میدهد. ابزارها با مجوزهای همان شخص عمل میکنند و ابزارهای مخرب تأیید میخواهند. مدیران در /admin/integrations/mcp انتخاب میکنند کدام ابزارها در دسترس باشند.
طرحها و API
کلیدهای API، کارخواههای OAuth، وبهوکها و سرور MCP در سهمیهٔ API طرح قرار میگیرند و همهٔ طرحهای استاندارد آن را دارند. در طرحی که این سهمیه را ندارد، ساخت کلید، کارخواه یا اشتراک رد میشود، نوشتن REST و اتصال MCP رد میشوند و خواندن REST همچنان کار میکند تا داده قابل خروجی گرفتن بماند. ردشدن یک problem document با کد commerce.plan_entitlement در دستهٔ precondition است.
افزونهها
نوع فعالیتها، بلوکها، روشهای ثبتنام، روشهای ورود، نوع پرسش، گزارشها، پوستهها و یکپارچهسازیهای خود Quire از راه همان فهرست افزونهای تعریف میشوند که نصب خودمیزبان هم میتواند به آن بیفزاید. افزونهها در برنامه کامپایل میشوند: بارگذار افزونهٔ زماناجرا وجود ندارد و سازمان میزبانیشده نمیتواند افزونه بیفزاید. مدیران هر افزونه را برای سازمانشان در /admin/extensions روشن یا خاموش میکنند؛ راهنمای مدیران را ببینید.
برای نوشتن افزونه، از بلوک و پوستهٔ نمونه در packages/integration/extensions/src/sample.ts آغاز کنید. نقطهٔ افزونه را انتخاب و قرارداد آن را در points.ts بخوانید؛ سپس افزونه را با شناسه، نسخه، مجوز، مواردی که فراهم و نیاز دارد و امکان روشن یا خاموش کردنش از سوی سازمان تعریف کنید. آن را در جایی ثبت کنید که برنامهٔ وب و worker با هم ساخته میشوند تا هر دو برداشت یکسانی داشته باشند. فهرست هنگام ساخته شدن و هر بار که register را فراخوانی میکنید قواعد همان نقطه را بررسی میکند؛ مجموعهای را که نامعتبر باشد همراه نام همهٔ مشکلات رد میکند و در صورت ردشدن، فهرست را بیتغییر میگذارد. آزمونهای افزونه باید تأیید کنند که extensionContractProblems برای آن خالی است و خاموش کردن افزونه چیزی را که بر آن اثر دارد تغییر میدهد.