---
title: "מדריך למפתחים"
description: "REST API של Quire,‏ OAuth,‏ webhooks, שרת MCP והרחבות."
image: "https://docs.quirelms.com/og.png"
---

> Documentation Index
> Fetch the complete documentation index at: https://docs.quirelms.com/he/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,‏ webhooks
חתומים לאירועים ושרת MCP לעוזרי AI. [מדריך ה-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`, בוחר את ההיקפים שלו ורואה אותו פעם אחת. שלחו אותו
כאסימון bearer:

```
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 (דוגמה בהמשך).
  אין offset.
- **שינויים מאז**: `updated_since` מחזיר את מה שהשתנה לאחר מועד מסוים. שלבו אותו עם
  `include_deleted=true` או קראו את `/<resource>/deletions` כדי לדעת מה הוסר.
- **מזהים חיצוניים**: רוב המשאבים מקבלים `external_id` משלכם, ו-`/<resource>/ext:{external_id}`
  קורא או מעדכן לפיו, כך שסנכרון אינו צריך לשמור את המזהים של Quire.
- **Idempotency**: שלחו כותרת `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`.

## Webhooks <!--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,‏ webhooks ושרת MCP כלולים בזכאות ה-API של התוכנית, וכל
תוכנית רגילה כוללת אותה. בתוכנית שאינה כוללת אותה, יצירת מפתח, לקוח או מינוי נדחית,
כתיבות REST וחיבורי MCP נדחים, וקריאות REST ממשיכות לפעול כדי שהנתונים יישארו
ניתנים לייצוא. הסירוב הוא מסמך בעיה עם הקוד `commerce.plan_entitlement` בקטגוריית
`precondition`.

## הרחבות <!--quire:extensions-->

סוגי הפעילויות, הבלוקים, שיטות ההרשמה, שיטות הכניסה, סוגי השאלות, הדוחות, ערכות
העיצוב והאינטגרציות של Quire עצמו מוצהרים באמצעות אותו מרשם הרחבות שגם התקנה
באירוח עצמי יכולה להוסיף לו. ההרחבות מקומפלות בתוך היישום: אין טוען תוספים בזמן
ריצה, וארגון בשירות אירוח אינו יכול להוסיף אחד.
מנהלי מערכת מפעילים או מכבים כל הרחבה לארגון שלהם ב-`/admin/extensions` (ראו את
[מדריך מנהלי המערכת](/he/admin/extensions/)).

כדי לכתוב הרחבה, התחילו בבלוק ובערכת העיצוב לדוגמה שב-`packages/integration/extensions/src/sample.ts`.
בחרו נקודת הרחבה וקראו את החוזה שלה ב-`points.ts`, ואז הצהירו על ההרחבה עם מזהה,
גרסה, רישיון, מה היא מספקת ומה היא דורשת, והאם ארגון יכול לכבות אותה. רשמו אותה
במקום שבו מרכיבים את יישום האינטרנט ואת ה-worker כדי ששניהם יסכימו על ההגדרה. המרשם
בודק את הכללים הייחודיים לכל נקודה בעת בנייתו ובכל קריאה ל-`register`, דוחה קבוצה
לא תקפה ומפרט את כל הבעיות, ומשאיר את המרשם ללא שינוי. בדיקות ההרחבה שלכם צריכות
לוודא ש-`extensionContractProblems` ריק עבורה ושכיבויה משנה את החלקים שעליהם היא
משפיעה.

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