---
title: "ഡവലപ്പർ ഗൈഡ്"
description: "Quire REST API, OAuth, വെബ്ഹുക്കുകൾ, MCP സെർവർ, എക്സ്റ്റൻഷനുകൾ."
image: "https://docs.quirelms.com/og.png"
---

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

# ഡവലപ്പർ ഗൈഡ്

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

നിങ്ങളുടെ സ്ഥാപനത്തിന്റെ API വിലാസവും ഒരു സ്കോപ്പ് ചെയ്ത ക്രെഡൻഷ്യലും ഉപയോഗിക്കൂ. ഒരു റീഡ് അഭ്യർത്ഥനയിൽ നിന്ന് ആരംഭിക്കൂ, പ്രതികരണം പരിശോധിക്കൂ, രഹസ്യങ്ങൾ സോർസ് കൺട്രോളിനും ഡോക്യുമെന്റേഷൻ ഉദാഹരണങ്ങൾക്കും പുറത്ത് സൂക്ഷിക്കൂ.

Quire-ന് ഒരു പബ്ലിക് API മാത്രമേയുള്ളൂ: HTTPS വഴിയുള്ള REST, ഒരു OpenAPI 3.1 രേഖ വഴി വിവരിക്കപ്പെട്ടത്, സംഭവങ്ങൾക്ക് ഒപ്പം ഒപ്പിട്ട വെബ്ഹുക്കുകളും AI അസിസ്റ്റന്റുകൾക്കുള്ള ഒരു 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. ലഭിച്ച കൃത്യമായ ബൈറ്റുകളിൽ നിന്ന്, ഏതു JSON പാഴ്സിംഗിനും മുമ്പ്, `{webhook-id}.{webhook-timestamp}.{raw body}` എന്ന സ്ട്രിംഗ് നിർമ്മിക്കൂ.
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-->

Quire-ന്റെ MCP സെർവർ സ്ഥാപനത്തിന്റെ വിലാസത്തിൽ `/mcp`-ൽ ആണ്, streamable HTTP വഴി. ഒരു MCP ക്ലയന്റ് `/.well-known/oauth-protected-resource`-ൽ നിന്ന് OAuth സെർവർ കണ്ടെത്തും, ഏതു 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`-ൽ ഓണാക്കുകയോ ഓഫാക്കുകയോ ചെയ്യും ([അഡ്മിനിസ്ട്രേറ്റർ ഗൈഡ്](/ml/admin/extensions/) കാണുക).

ഒന്ന് എഴുതാൻ, `packages/integration/extensions/src/sample.ts`-ലെ മാതൃക ബ്ലോക്കിലും തീമിലും നിന്ന് ആരംഭിക്കൂ. എക്സ്റ്റൻഷൻ പോയിന്റ് തിരഞ്ഞെടുക്കൂ, `points.ts`-ൽ അതിന്റെ കരാർ വായിക്കൂ, പിന്നെ ഒരു ഐഡി, പതിപ്പ്, ലൈസൻസ്, അത് നൽകുന്നതും ആവശ്യപ്പെടുന്നതും, ഒരു സ്ഥാപനത്തിന് അത് ഓഫാക്കാൻ അനുവദിക്കുന്നുണ്ടോ എന്നതും സഹിതം എക്സ്റ്റൻഷൻ പ്രഖ്യാപിക്കൂ. വെബ് ആപ്ലിക്കേഷനും വർക്കറും ചേർക്കപ്പെടുന്നിടത്ത് അത് രജിസ്റ്റർ ചെയ്യൂ, അങ്ങനെ രണ്ടും യോജിക്കും. രജിസ്റ്റർ ബിൽഡ് ചെയ്യുമ്പോഴും നിങ്ങൾ `register` വിളിക്കുമ്പോഴും ഓരോ പോയിന്റിന്റെയും സ്വന്തം നിയമങ്ങൾ പരിശോധിക്കും, ഓരോ പ്രശ്നവും പേരെടുത്ത് പറഞ്ഞ് അസാധുവാകുമായിരുന്ന ഒരു കൂട്ടം നിരസിക്കും, അങ്ങനെ സംഭവിക്കുമ്പോൾ രജിസ്റ്റർ മാറ്റമില്ലാതെ നിലനിർത്തും. എക്സ്റ്റൻഷന്റെ സ്വന്തം ടെസ്റ്റുകൾ അതിന് `extensionContractProblems` ശൂന്യമാണെന്നും അത് ഓഫാക്കിയാൽ അത് ബാധിക്കുന്നത് മാറുമെന്നും ഉറപ്പാക്കണം.

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