Langkau ke kandungan

Panduan pembangun

REST API Quire, OAuth, webhook, pelayan MCP dan sambungan.

Guna alamat API organisasi anda dan satu kelayakan berskop. Mula dengan satu permintaan baca, semak respons, dan simpan rahsia di luar kawalan sumber dan contoh dokumentasi.

Quire mempunyai satu API awam: REST merentasi HTTPS, diterangkan oleh satu dokumen OpenAPI 3.1, dengan webhook bertandatangan untuk peristiwa dan satu pelayan MCP untuk pembantu AI. Rujukan API menyenaraikan setiap titik akhir dan peristiwa.

Alamat

Setiap organisasi mempunyai alamatnya sendiri, dan API berada di bawahnya:

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

Kelayakan menentukan organisasi. Kunci untuk satu organisasi yang digunakan pada alamat organisasi lain ditolak.

Dokumen OpenAPI disajikan di /api/v1/openapi.json pada mana-mata alamat organisasi, jadi penjana klien sentiasa melihat versi yang anda panggil.

Pengesahan

Kunci API adalah untuk skrip dan integrasi pelayan-ke-pelayan. Seorang pentadbir menciptanya di /admin/integrations/api-keys, memilih skopnya, dan melihatnya sekali. Hantarkannya sebagai satu token pembawa:

curl -H "Authorization: Bearer qk_live_..." https://acme.quirelms.com/api/v1/users?limit=50

Kunci bermula qk_live_ atau qk_test_. Berikan setiap integrasi kuncinya sendiri.

OAuth 2.1 adalah untuk aplikasi yang bertindak sebagai seseorang yang sudah log masuk. Daftarkan satu pelanggan di /admin/integrations/oauth-clients, kemudian guna aliran kod kebenaran dengan PKCE (/oauth/authorize, /oauth/token), atau kelayakan pelanggan untuk satu pelanggan mesin. Penemuan berada di /.well-known/oauth-authorization-server. Satu skop mengehadkan apa yang boleh dilakukan oleh satu token; ia tidak pernah membenarkannya melakukan lebih daripada apa yang mampu dilakukan oleh orang itu.

Skop ialah resource:read, resource:write dan resource:delete, contohnya courses:read atau enrolments:write. Empat daripadanya berkuasa dan dipaparkan dengan satu amaran pada skrin persetujuan: audit:read, roles:write, tenants:write dan users:delete.

The API keys page with one key, the person it acts as, its scopes and its status, and a form to create another.
API keys list who each key acts as and what it may reach.

Permintaan

  • Penghalaman: setiap senarai menggunakan penghalaman kursor. Hantar limit, kemudian next_cursor daripada page sebagai cursor selagi has_more bernilai benar (contoh di bawah). Tiada offset.
  • Perubahan sejak: updated_since mengembalikan apa yang berubah selepas satu masa. Pasangkannya dengan include_deleted=true, atau baca /<resource>/deletions, untuk mengetahui apa yang dibuang.
  • Pengenal luaran: kebanyakan sumber menerima external_id anda sendiri, dan /<resource>/ext:{external_id} membaca atau mengemas kini mengikutnya, jadi satu penyegerakan tidak pernah perlu menyimpan pengenal Quire.
  • Keidempotenan: hantar satu tajuk Idempotency-Key pada POST, PATCH dan DELETE. Satu percubaan semula dengan kunci yang sama memulangkan respons pertama dan bukannya melakukan kerja itu dua kali. Titik akhir pukal memerlukannya.
  • Versi: versi utama berada dalam laluan (/v1). Dalamnya, setiap perubahan yang memecahkan ialah satu semakan bertarikh, dipilih dengan tajuk Quire-Version, contohnya Quire-Version: 2026-09-20. Tanpa tajuk itu, anda mendapat semakan yang semasa apabila kelayakan anda dikeluarkan.

Sebuah halaman senarai:

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

Ralat

Setiap ralat ialah satu dokumen masalah 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..."}

Cabangkan pada code, yang stabil; detail ditulis untuk manusia, selamat dipaparkan kepada mereka, dan mungkin berubah. Apabila anda tidak mengecam satu kod, ketuakan pada category:

Kategori Status Cuba lagi
validation 422, dengan butiran medan dalam errors Tidak
authentication 401 Tidak
authorization 403 Tidak
not_found 404 Tidak
conflict 409 Kadangkala
precondition 412 Tidak
quota 402 untuk pelan, 413 untuk saiz Tidak
rate_limit 429, dengan Retry-After Ya
upstream 502 atau 504 Ya
internal 500 Ya

Petik request_id apabila anda menghubungi sokongan.

Webhook

Langgan di /admin/webhooks, atau melalui API di /webhook_subscriptions. Pilih peristiwa mengikut nama (enrolment.created), mengikut bidang (enrolment.*) atau semuanya (*). Quire mula-mula menghantar satu webhook.ping; langganan bermula sebaik sahaja titik akhir anda menjawabnya.

Penghantaran mengikut spesifikasi Standard Webhooks:

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

Untuk menyahkan satu penghantaran:

  1. Bina rentetan {webhook-id}.{webhook-timestamp}.{raw body} daripada bait tepat yang diterima, sebelum sebarang penghuraian JSON.
  2. Kira HMAC-SHA256 ke atasnya dengan rahsia langganan anda, dan base64-kan.
  3. Bandingkan dengan setiap nilai v1, dalam webhook-signature pada masa pemalar. Mungkin ada dua semasa satu pusingan rahsia; mana-mana yang sepadan adalah sah.
  4. Tolak satu cap masa yang lebih lima minit daripada jam anda.
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);
  });
}

Nyahganda pada webhook-id: satu penghantaran mungkin tiba lebih daripada sekali. Badan itu membawa pengenal dan satu ringkasan pendek; ambil sumber tersebut untuk keadaan semasanya. Penghantaran yang gagal dicuba semula dengan backoff sehingga 72 jam, dan boleh dimainkan semula daripada log penghantaran.

MCP

Pelayan MCP Quire berada di /mcp pada alamat organisasi, merentasi HTTP boleh strim. Sebuah klien MCP menemui pelayan OAuth daripada /.well-known/oauth-protected-resource, dan orang itu log masuk dan memberi persetujuan seperti mana-mana pelanggan OAuth. Alat bertindak sebagai orang itu, dengan keizinan mereka, dan alat yang memusnahkan meminta pengesahan. Pentadbir memilih alat mana yang tersedia di /admin/integrations/mcp.

The AI assistants page with the server address to give an assistant and a table of the tools it can use.
AI assistants (MCP): the server address, and the tools an assistant may call.

Pelan dan API

Kunci API, pelanggan OAuth, webhook dan pelayan MCP tergolong dalam hak API pelan tersebut, dan setiap pelan standard menyertainya. Dalam pelan tanpanya, penciptaan satu kunci, pelanggan atau langganan ditolak, tulisan REST dan sambungan MCP ditolak, dan bacaan REST terus berfungsi supaya data kekal boleh dieksport. Penolakan tersebut ialah satu dokumen masalah dengan kod commerce.plan_entitlement, dalam kategori precondition.

Sambungan

Jenis aktiviti, blok, kaedah pendaftaran, kaedah log masuk, jenis soalan, laporan, tema dan integrasi milik Quire sendiri diisytiharkan melalui registri sambungan yang sama yang boleh ditambah oleh sebuah pemasangan kendiri. Sambungan dikompilasi masuk: tiada pemuat pemalam masa laksana, dan sebuah organisasi hos tidak boleh menambah satu. Pentadbir menghidupkan atau mematikan setiap sambungan untuk organisasi mereka di /admin/extensions (lihat panduan pentadbir).

Untuk menulis satu, mulakan daripada blok sampel dan tema dalam packages/integration/extensions/src/sample.ts. Pilih titik sambungan dan baca kontraknya dalam points.ts, kemudian isytiharkan sambungannya dengan satu id, versi, lesen, apa yang ia sediakan dan perlukan, dan sama ada sebuah organisasi boleh mematikannya. Daftarkan ia di mana aplikasi web dan pekerja digabungkan, supaya kedua-duanya bersetuju. Registri menyemak peraturan setiap titik semasa ia dibina dan setiap kali anda memanggil register, menolak satu set yang akan tidak sah dengan setiap masalah dinamakan, dan meninggalkan registri tanpa perubahan apabila ia berbuat demikian. Ujian sambungan itu sendiri sepatutnya menegaskan bahawa extensionContractProblems kosong baginya dan bahawa mematikannya mengubah apa yang dipengaruhinya.

Navigasi

Taip untuk mencari…

↑↓ navigasi↵ pilihEsc tutup