---
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/km/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-->

- **ការបំបែកទំព័រ**៖ បញ្ជីទាំងអស់បំបែកទំព័រដោយ cursor។ បញ្ជូល `limit` រួច `next_cursor` ពី `page` ជា `cursor` ខណៈ `has_more` នៅតែជា true (ឧទាហរណ៍ខាងក្រោម)។ គ្មាន offset ទេ។
- **ការផ្លាស់ប្តូរចាប់តាំងពី**៖ `updated_since` ត្រឡប់អ្វីដែលបានផ្លាស់ប្តូរបន្ទាប់ពីពេលវេលាមួយ។ ភ្ជាប់វាជាមួយ `include_deleted=true` ឬអាន `/<resource>/deletions` ដើម្បីដឹងថាអ្វីដែលបានលុប។
- **អត្តសញ្ញាណក្រៅ**៖ ធនធានភាគច្រើនទទួល `external_id` ផ្ទាល់របស់អ្នក ហើយ `/<resource>/ext:{external_id}` អាន ឬ upsert តាមវា ដូច្នេះការសមកាលកម្មមិនដែលត្រូវការរក្សាអត្តសញ្ញាណរបស់ 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` នៅពេលអ្នកទាក់ទងការគាំទ្រ។

## Webhooks <!--quire:webhooks-->

ចុះឈ្មោះនៅ `/admin/webhooks` ឬតាម API នៅ `/webhook_subscriptions`។ ជ្រើសរើសព្រឹត្តិការណ៍តាមឈ្មោះ (`enrolment.created`) តាមផ្នែក (`enrolment.*`) ឬទាំងអស់ (`*`)។ Quire ផ្ញើ `webhook.ping` ជាមុនសិន ការចុះឈ្មោះចាប់ផ្តើមនៅពេលចំណុចបញ្ចប់របស់អ្នកឆ្លើយតបវា។

ការផ្ញើធ្វើតាមសេចក្តីជំនួយការ 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`៖ ការផ្ញើមួយអាចមកដល់ច្រើនដង។ ខ្លឹមសារផ្ទុកអត្តសញ្ញាណ និងសេចក្តីសង្ខេបខ្លី ទាញយកធនធានសម្រាប់សភាពបច្ចុប្បន្នរបស់វា។ ការផ្ញើដែលបរាជ័យត្រូវបានសាកឡើងវិញជាមួយ backoff រហូតដល់ 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 ប្លុក វិធីចុះឈ្មោះ វិធីចូល ប្រភេទសំណួរ របាយការណ៍ រចនាបថ និងការរួមបញ្ចូល ត្រូវបានប្រកាសតាមបញ្ជីផ្នែកបន្ថែមដដែលដែលការដំឡើងដោយខ្លួនឯងអាចបន្ថែម។ ផ្នែកបន្ថែមត្រូវបានកូឌូរ៖ គ្មាកម្មវិធីរត់ផ្ទុក plugin ទេ ហើយអង្គការដែល hosting មិនអាចបន្ថែមមួយបានទេ។ អ្នកគ្រប់គ្រងបិត ឬបើកផ្នែកបន្ថែមនីមួយៗសម្រាប់អង្គការរបស់ពួកគេនៅ `/admin/extensions` (សូមមើល[មគ្គុទ្ទេសអ្នកគ្រប់គ្រង](/km/admin/extensions/))។

ដើម្បីសរសេរមួយ ចាប់ផ្តើមពីប្លុក និងរចនាបថគំរូនៅក្នុង `packages/integration/extensions/src/sample.ts`។ ជ្រើសរើសចំណុចផ្នែកបន្ថែម ហើយអានកិច្ចសន្យារបស់វានៅ `points.ts` រួចប្រកាសផ្នែកបន្ថែមជាមួយ id កំណែអាជ្ញាប័ណ្ណ អ្វីដែលវាផ្តល់ និងទាមទារ និងថាតើអង្គការអាចបិតវាបានឬអត់។ ចុះឈ្មោះវានៅកន្លែងដែលកម្មវិធី web និង worker ត្រូវបានបង្កើតឡើង ដូច្នេះទាំងពីរយល់ស្របគ្នា។ បញ្ជីពិនិត្យច្បាប់ផ្ទាល់របស់ចំណុចនីមួយៗនៅពេលវាត្រូវបានសង់ ហើយនៅពេលអ្នកហៅ `register` បដិសេធបញ្ជីដែលនឹងមិនត្រឹមត្រូវដោយដាក់ឈ្មោះបញ្ហាទាំងអស់ ហើយទុកបញ្ជីមិនផ្លាស់ប្តូរនៅពេលវាធ្វើដូច្នេះ។ ការសាកល្បងផ្ទាល់របស់ផ្នែកបន្ថែមគួរតែអះអាងថា `extensionContractProblems` ទទេសម្រាប់វា ហើយការបិតវាផ្លាស់ប្តូរអ្វីដែលវាប៉ះពាល់។

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