Lewati ke konten

Panduan pengembang

REST API Quire, OAuth, webhook, server MCP, dan ekstensi.

Gunakan alamat API organisasi dan kredensial dengan cakupan terbatas. Mulailah dengan permintaan baca, periksa responsnya, serta simpan rahasia di luar kontrol sumber dan contoh dokumentasi.

Quire memiliki satu API publik: REST melalui HTTPS yang dijelaskan dalam dokumen OpenAPI 3.1, webhook bertanda tangan untuk peristiwa, dan server MCP bagi asisten AI. Referensi API mencantumkan setiap endpoint dan peristiwa.

Alamat

Setiap organisasi memiliki alamat sendiri, dan API berada di bawah alamat tersebut:

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

Kredensial menentukan organisasi. Kunci milik satu organisasi yang digunakan di alamat organisasi lain akan ditolak.

Dokumen OpenAPI tersedia di /api/v1/openapi.json pada alamat organisasi mana pun, sehingga generator klien selalu mendapatkan versi yang sedang Anda panggil.

Autentikasi

Kunci API digunakan untuk skrip dan integrasi server-ke-server. Administrator membuatnya di /admin/integrations/api-keys, memilih cakupannya, lalu melihatnya sekali. Kirim sebagai bearer token:

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

Awalan kunci adalah qk_live_ atau qk_test_. Berikan kunci tersendiri untuk setiap integrasi.

OAuth 2.1 digunakan untuk aplikasi yang bertindak sebagai orang yang sudah masuk. Daftarkan klien di /admin/integrations/oauth-clients, lalu gunakan alur kode otorisasi dengan PKCE (/oauth/authorize, /oauth/token) atau kredensial klien untuk klien mesin. Discovery tersedia di /.well-known/oauth-authorization-server. Cakupan membatasi tindakan token; cakupan tidak pernah memberikan kemampuan melebihi hak orang tersebut.

Cakupannya adalah resource:read, resource:write, dan resource:delete, misalnya courses:read atau enrolments:write. Empat cakupan bersifat istimewa dan diberi peringatan pada layar persetujuan: audit:read, roles:write, tenants:write, dan users:delete.

Permintaan

  • Paginasi: setiap daftar dipaginasi menggunakan cursor. Kirim limit, lalu teruskan next_cursor dari page sebagai cursor selama has_more bernilai true (lihat contoh di bawah). Tidak ada offset.
  • Perubahan sejak waktu tertentu: updated_since mengembalikan perubahan setelah waktu yang diberikan. Pasangkan dengan include_deleted=true atau baca /<resource>/deletions untuk mengetahui hal yang dihapus.
  • ID eksternal: sebagian besar sumber daya menerima external_id sendiri, dan /<resource>/ext:{external_id} dapat membaca atau melakukan upsert berdasarkan ID tersebut, sehingga sinkronisasi tidak perlu menyimpan ID Quire.
  • Idempotensi: kirim header Idempotency-Key pada POST, PATCH, dan DELETE. Pengulangan dengan kunci yang sama mengembalikan respons pertama alih-alih menjalankan pekerjaan dua kali. Endpoint massal mewajibkannya.
  • Versi: versi utama ada di jalur (/v1). Di dalamnya, setiap perubahan yang tidak kompatibel merupakan revisi bertanggal yang dipilih melalui header Quire-Version, misalnya Quire-Version: 2026-09-20. Tanpa header, Anda mendapatkan revisi yang berlaku saat kredensial diterbitkan.

Contoh halaman daftar:

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

Kesalahan

Setiap kesalahan berupa 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..."}

Gunakan code sebagai dasar logika karena nilainya stabil; detail ditulis untuk pengguna, aman untuk ditampilkan, dan dapat berubah. Jika tidak mengenali kode, kelompokkan berdasarkan category:

Kategori Status Coba lagi
validation 422, dengan detail kolom di errors Tidak
authentication 401 Tidak
authorization 403 Tidak
not_found 404 Tidak
conflict 409 Kadang
precondition 412 Tidak
quota 402 untuk paket, 413 untuk ukuran Tidak
rate_limit 429, dengan Retry-After Ya
upstream 502 atau 504 Ya
internal 500 Ya

Sebutkan request_id saat menghubungi dukungan.

Webhook

Berlangganan melalui /admin/webhooks atau API di /webhook_subscriptions. Pilih peristiwa berdasarkan nama (enrolment.created), area (enrolment.*), atau semua peristiwa (*). Quire mengirim webhook.ping terlebih dahulu; langganan dimulai setelah endpoint Anda menjawabnya.

Pengiriman mengikuti spesifikasi Standard Webhooks:

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

Untuk memverifikasi pengiriman:

  1. Dari byte persis yang diterima, sebelum mengurai JSON, susun string {webhook-id}.{webhook-timestamp}.{raw body}.
  2. Hitung HMAC-SHA256 dengan rahasia langganan, lalu enkode sebagai base64.
  3. Bandingkan dengan setiap nilai v1, pada webhook-signature dalam waktu konstan. Saat rotasi rahasia mungkin ada dua nilai; salah satu yang cocok sudah valid.
  4. Tolak timestamp yang selisihnya lebih dari lima menit dari 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);
  });
}

Hindari duplikasi berdasarkan webhook-id: pengiriman yang sama dapat tiba lebih dari sekali. Isi pesan membawa ID dan ringkasan singkat; ambil sumber daya untuk mendapatkan status terkini. Pengiriman gagal dicoba ulang dengan jeda bertahap hingga 72 jam dan dapat diputar ulang dari log pengiriman.

MCP

Server MCP Quire berada di /mcp pada alamat organisasi melalui HTTP streaming. Klien MCP menemukan server OAuth melalui /.well-known/oauth-protected-resource; pengguna masuk dan memberikan persetujuan seperti pada klien OAuth lainnya. Alat bertindak sebagai pengguna tersebut dengan izinnya; alat destruktif meminta konfirmasi. Administrator memilih alat yang tersedia di /admin/integrations/mcp.

Paket dan API

Kunci API, klien OAuth, webhook, dan server MCP termasuk dalam hak API paket; semua paket standar menyertakannya. Pada paket yang tidak memiliki hak tersebut, pembuatan kunci, klien, atau langganan ditolak; penulisan REST dan koneksi MCP juga ditolak, sedangkan pembacaan REST tetap berfungsi agar data dapat diekspor. Penolakan berupa dokumen masalah dengan kode commerce.plan_entitlement dalam kategori precondition.

Ekstensi

Jenis aktivitas, blok, metode pendaftaran, metode masuk, jenis soal, laporan, tema, dan integrasi bawaan Quire dideklarasikan melalui registri ekstensi yang juga dapat ditambahkan oleh instalasi hosting mandiri. Ekstensi dikompilasi ke dalam Quire: tidak ada pemuat plugin saat runtime dan organisasi hosting tidak dapat menambahkan ekstensi. Administrator mengaktifkan atau menonaktifkan ekstensi untuk organisasinya di /admin/extensions (lihat panduan administrator).

Untuk membuat ekstensi, mulai dari contoh blok dan tema di packages/integration/extensions/src/sample.ts. Pilih titik ekstensi dan baca kontraknya di points.ts, lalu deklarasikan ekstensi dengan ID, versi, lisensi, hal yang disediakan dan dibutuhkan, serta apakah organisasi dapat menonaktifkannya. Daftarkan ekstensi di tempat aplikasi web dan worker dirangkai agar keduanya selaras. Saat dibangun dan setiap kali Anda memanggil register, registri memeriksa aturan tiap titik; registri menolak kumpulan yang tidak valid dengan menyebutkan semua masalah, tanpa mengubah isinya. Pengujian ekstensi sebaiknya memastikan extensionContractProblems kosong untuk ekstensi itu dan penonaktifannya mengubah hal yang dipengaruhinya.

Navigasi

Ketik untuk mencari…

↑↓ navigasi↵ pilihEsc tutup