---
title: "دليل المطور"
description: "REST API في Quire وOAuth وخطافات الويب وخادم MCP والإضافات."
image: "https://docs.quirelms.com/og.png"
---

> Documentation Index
> Fetch the complete documentation index at: https://docs.quirelms.com/ar/llms.txt
> Use this file to discover all available pages before exploring further.

# دليل المطور

<span id="developer-guide"></span>

استخدم عنوان API الخاص بمؤسستك وبيانات اعتماد محددة النطاقات. ابدأ بطلب قراءة، وافحص الاستجابة، واحفظ الأسرار خارج التحكم بالمصدر وأمثلة الوثائق.

لدى Quire واجهة API عامة واحدة: REST عبر HTTPS موصوفة بمستند OpenAPI 3.1، وخطافات ويب موقعة للأحداث، وخادم MCP لمساعدات الذكاء الاصطناعي. يسرد [مرجع API](https://docs.quirelms.com/api/) كل نقطة نهاية وحدث.

## العناوين <!--quire:addresses-->

لكل مؤسسة عنوانها، وتوجد API ضمنه:

```
https://acme.quirelms.com/api/v1/courses
```

تحدد بيانات الاعتماد المؤسسة. ويُرفض استخدام مفتاح مؤسسة على عنوان مؤسسة أخرى.

يُقدم مستند OpenAPI على `/api/v1/openapi.json` في عنوان أي مؤسسة، لذا ترى مولدات العملاء دائمًا الإصدار الذي تستدعيه.

## المصادقة <!--quire:authentication-->

تُستخدم **مفاتيح API** للبرامج النصية والتكاملات بين الخوادم. ينشئ المسؤول مفتاحًا في `/admin/integrations/api-keys` ويختار نطاقاته ولا يراه إلا مرة واحدة. أرسله كرمز حامل:

```
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`، ثم استخدم تدفق رمز التفويض مع PKCE (`/oauth/authorize` و`/oauth/token`) أو بيانات اعتماد العميل لعميل آلي. يتوفر الاكتشاف في `/.well-known/oauth-authorization-server`. يضيّق النطاق ما يمكن للرمز فعله، ولا يمنحه صلاحيات أكثر مما لدى الشخص.

النطاقات هي `resource:read` و`resource:write` و`resource:delete`، مثل `courses:read` أو `enrolments:write`. أربعة نطاقات ذات امتيازات خاصة وتظهر معها علامة تحذير في شاشة الموافقة: `audit:read` و`roles:write` و`tenants:write` و`users:delete`.

<figure class="quire-shot" lang="en" dir="ltr"><img src="/screenshots/admin-api-keys.webp" alt="The API keys page with one key, the person it acts as, its scopes and its status, and a form to create another." width="944" height="700" loading="lazy" decoding="async"><figcaption>API keys list who each key acts as and what it may reach.</figcaption></figure>

## الطلبات <!--quire:requests-->

- **تقسيم الصفحات**: تستخدم كل قائمة تقسيمًا بمؤشر. أرسل `limit` ثم مرر `next_cursor` من `page` كقيمة `cursor` ما دامت `has_more` تساوي true (انظر المثال أدناه). لا يوجد ترقيم بالإزاحة.
- **التغييرات منذ وقت معين**: تعيد `updated_since` ما تغير بعد وقت معين. اقرنها بـ`include_deleted=true` أو اقرأ `/<resource>/deletions` لمعرفة ما أُزيل.
- **معرّفات خارجية**: تقبل معظم الموارد `external_id` خاصًا بك، ويقرأ `/<resource>/ext:{external_id}` السجل أو ينشئه ويحدّثه بحسب هذا المعرف، فلا تحتاج عملية المزامنة إلى تخزين معرّفات Quire.
- **مفتاح عدم التكرار**: أرسل رأس `Idempotency-Key` مع `POST` و`PATCH` و`DELETE`. تعيد المحاولة بالمفتاح نفسه الاستجابة الأولى بدل تنفيذ العمل مرتين. وتتطلب نقاط النهاية المجمعة هذا الرأس.
- **الإصدارات**: يوجد الإصدار الرئيسي في المسار (`/v1`). ويحدد رأس `Quire-Version` مراجعة مؤرخة لكل تغيير غير متوافق، مثل `Quire-Version: 2026-09-20`. ودون الرأس تحصل على المراجعة الحالية عند إصدار بيانات اعتمادك.

صفحة من قائمة:

```
{"data": [...], "page": {"next_cursor": "eyJ2Ijox...", "has_more": true, "limit": 100}}
```

## الأخطاء <!--quire:errors-->

يأتي كل خطأ في مستند مشكلة وفق 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` عند التواصل مع الدعم.

## خطافات الويب <!--quire:webhooks-->

اشترك في `/admin/webhooks` أو عبر API من خلال `/webhook_subscriptions`. اختر الأحداث بالاسم (`enrolment.created`) أو المجال (`enrolment.*`) أو كلها (`*`). يرسل Quire أولًا `webhook.ping`؛ ويبدأ الاشتراك بعد أن ترد عليه نقطة النهاية.

تتبع عمليات التسليم مواصفة Standard Webhooks:

```
POST /hooks/quire
webhook-id: 01JB7XQK4Z8FQ2M3N4P5R6S7T8
webhook-timestamp: 1790000000
webhook-signature: v1,g0hM9SsE+OTPJTGt/tmIKtSyZlE3uFJELVlNIOLJ1OE=
```

للتحقق من عملية التسليم:

1. كوّن النص `{webhook-id}.{webhook-timestamp}.{raw body}` من البايتات المستلمة نفسها قبل تحليل JSON.
2. احسب HMAC-SHA256 عليه بسر الاشتراك ثم حوّله إلى base64.
3. قارن بقيم `v1,` في `webhook-signature` في وقت ثابت. قد توجد قيمتان أثناء تدوير السر؛ ويكفي تطابق إحداهما.
4. ارفض طابعًا زمنيًا يبعد أكثر من خمس دقائق عن ساعتك.

```
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` فقد تصل عملية التسليم أكثر من مرة. يحمل المحتوى المعرّفات وملخصًا قصيرًا؛ استرجع المورد لمعرفة حالته الحالية. يُعاد إرسال عمليات التسليم الفاشلة بمحاولات متباعدة لمدة تصل إلى 72 ساعة، ويمكن تشغيلها مجددًا من سجل التسليم.

## MCP <!--quire:mcp-->

يوجد خادم MCP في Quire على `/mcp` ضمن عنوان المؤسسة عبر HTTP القابل للبث. ويكتشف عميل MCP خادم OAuth من `/.well-known/oauth-protected-resource`، ثم يسجل الشخص الدخول ويوافق كما يفعل مع أي عميل OAuth. وتعمل الأدوات بصلاحيات ذلك الشخص، وتطلب الأدوات المدمرة تأكيدًا. ويختار المسؤولون الأدوات المتاحة في `/admin/integrations/mcp`.

<figure class="quire-shot" lang="en" dir="ltr"><img src="/screenshots/admin-mcp.webp" alt="The AI assistants page with the server address to give an assistant and a table of the tools it can use." width="944" height="700" loading="lazy" decoding="async"><figcaption>AI assistants (MCP): the server address, and the tools an assistant may call.</figcaption></figure>

## الخطط وAPI <!--quire:plans-and-the-api-->

تندرج مفاتيح API وعملاء OAuth وخطافات الويب وخادم MCP ضمن استحقاق API في الخطة، وكل الخطط القياسية تتضمنه. وفي خطة لا تتضمنه، يُرفض إنشاء مفتاح أو عميل أو اشتراك، كما تُرفض كتابات REST واتصالات MCP؛ أما قراءات REST فتظل متاحة لإبقاء البيانات قابلة للتصدير. ويأتي الرفض كمستند مشكلة بالرمز `commerce.plan_entitlement` ضمن فئة `precondition`.

## الإضافات <!--quire:extensions-->

تُعرّف أنواع الأنشطة والكتل وطرق التسجيل وتسجيل الدخول وأنواع الأسئلة والتقارير والسمات وعمليات التكامل في Quire عبر سجل الإضافات نفسه الذي يمكن للتثبيت المستضاف ذاتيًا توسيعه. تُضمّن الإضافات عند البناء؛ فلا يوجد محمل إضافات أثناء التشغيل ولا يمكن للمؤسسة المستضافة إضافة واحدة. ويمكن للمسؤولين تفعيل كل إضافة لمؤسستهم أو إيقافها في `/admin/extensions` (راجع [دليل المسؤول](/ar/admin/extensions/)).

لبناء إضافة، ابدأ بالكتلة والسمة النموذجيتين في `packages/integration/extensions/src/sample.ts`. اختر نقطة الإضافة واقرأ عقدها في `points.ts`، ثم عرّف الإضافة بمعرف وإصدار وترخيص وما توفره وما تحتاج إليه، وما إذا كان يمكن للمؤسسة إيقافها. سجّلها عند تركيب تطبيق الويب والعامل كي يتفقا. يفحص السجل قواعد كل نقطة عند بنائه وكلما استدعيت `register`، ويرفض مجموعة غير صالحة مع ذكر كل المشكلات، ويبقي السجل كما هو عند الرفض. وينبغي لاختبارات الإضافة أن تؤكد أن `extensionContractProblems` فارغة لها وأن إيقافها يغير ما تؤثر فيه.

Source: https://docs.quirelms.com/ar/developer/index.mdx
