Administrasi
Integrasi: token API dan webhook
Menghubungkan sistem lain: membuat dan membaca tiket lewat API, menerima peristiwa lewat webhook bertanda tangan.
Halaman Integrasi menghubungkan RANCAQ dengan sistem lain di organisasi Anda, misalnya alat monitoring, sistem HR, chat tim, atau otomasi seperti n8n. Halaman ini ada di Administrasi → Integrasi dan punya dua bagian:
- Token API: sistem lain membuat dan membaca tiket lewat REST API, tanpa akun orang.
- Webhook: RANCAQ mengirim peristiwa tiket ke alamat HTTPS milik Anda begitu terjadi.
Siapa yang dapat mengelola
Mengelola token dan webhook memerlukan izin Kelola integrasi. Secara bawaan izin ini hanya dimiliki Tenant Admin, karena token bisa membuka tiket ke sistem lain. Auditor dapat melihat daftar token, webhook, dan riwayat pengiriman tanpa mengubah apa pun. Lihat Pengguna, tim, dan peran.
Token API
Membuat token
- Buka Administrasi → Integrasi, tab Token API, lalu klik Token baru.
- Isi Nama yang menjelaskan pemakainya, mis. "Zabbix kantor pusat".
- Pilih Izin. Pilih sesempit mungkin:
| Izin | Artinya |
|---|---|
| Baca tiket buatan integrasi ini | Hanya tiket yang dibuat token ini sendiri. |
| Baca seluruh tiket workspace | Semua tiket, tanpa catatan internal. Pilih hanya bila sistem tujuan memang perlu melihat semua. |
| Buat tiket | Tiket baru berkanal API, dengan pelapor identitas integrasi. |
| Tulis komentar publik | Komentar publik pada tiket yang bisa dibaca token. Butuh salah satu izin baca. |
| Buat atas nama pelapor lain | Izin khusus. Tiket dicatat atas nama anggota aktif workspace ini, dan audit mencatat token serta pelapor yang diwakili. Butuh Buat tiket. |
- Pilih Masa berlaku, lalu klik Buat token.
- Salin token yang muncul (
rqa_…) ke pengelola rahasia sistem tujuan. Token hanya tampil sekali. Bila hilang, cabut lalu buat token baru.
Satu workspace dapat memiliki paling banyak 10 token aktif.
Identitas integrasi
Setiap token punya identitas sendiri bernama Integrasi:
- tidak bisa masuk ke aplikasi dan tidak menerima email;
- tidak tampil di daftar pengguna dan tidak dihitung sebagai kursi agen;
- tidak bisa diberi peran atau dimasukkan ke tim.
Memakai token
Kirim token di header Authorization:
curl -s https://app.rancaq.com/api/v1/tickets?limit=20 \
-H "Authorization: Bearer rqa_…"
Endpoint yang menerima token:
| Endpoint | Izin |
|---|---|
GET /api/v1/tickets dan GET /api/v1/tickets/{id} | Baca |
GET /api/v1/tickets/{id}/comments dan …/activities | Baca |
POST /api/v1/tickets | Buat tiket |
POST /api/v1/tickets/{id}/comments | Tulis komentar publik |
Endpoint lain menolak token dengan 401.
Membuat tiket:
curl -s -X POST https://app.rancaq.com/api/v1/tickets \
-H "Authorization: Bearer rqa_…" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: zabbix-event-48213" \
-d '{"kind":"INCIDENT","subject":"Disk server DB 95%","description":"Dari Zabbix","urgency":"HIGH"}'
Idempotency-Key: kirim kunci unik per kejadian di sistem Anda. Permintaan ulang dengan kunci yang sama tidak membuat tiket kedua. Kunci berlaku per token, jadi dua integrasi yang kebetulan memakai kunci sama tidak saling mengganggu.- Atas nama pelapor: dengan izin khusus, tambahkan
"requested_for_email": "[email protected]"(ataurequested_for_id). Pelapor itu harus anggota aktif workspace ini. Ia melihat tiketnya di portal dan menerima email seperti biasa. - Komentar:
POST …/commentsdengan{"body": "…"}selalu publik. Token tidak bisa membaca maupun menulis catatan internal. Komentar integrasi tidak dihitung sebagai respons pertama tim dan tidak menutup penanda Pelapor membalas.
Setiap token dibatasi 120 permintaan per menit. Bila terlampaui, jawabannya 429 dengan header Retry-After. Workspace yang masa trial-nya berakhir hanya menerima permintaan baca.
Mencabut token
Klik Cabut pada baris token. Sejak saat itu setiap permintaan dengan token itu ditolak 401, dan langkah ini tidak bisa dibatalkan. Riwayat tindakan token tetap tersimpan.
Webhook
Membuat webhook
- Buka tab Webhook, lalu klik Webhook baru.
- Isi Nama dan URL penerima. URL harus
https://dan menuju alamat publik. Alamat jaringan privat, alamat loopback seperti127.0.0.1, dan alamat khusus ditolak. Pemeriksaan berlangsung dua kali. Saat Simpan, RANCAQ menolak URL yang berbentuk alamat IP privat atau khusus dan nama host internal (misalnya*.local,*.internal). Nama host biasa belum dicek ke DNS, karena alamatnya bisa berubah. Saat mengirim, nama host dicek ke DNS: bila mengarah ke alamat privat, kiriman tidak dibuka dan tercatat Gagal di riwayat dengan pesanditolak: alamat tujuan tidak diizinkan …. - Pilih Peristiwa:
| Peristiwa | Kapan dikirim |
|---|---|
ticket.created.v1 | Tiket baru dibuat lewat jalur apa pun. |
ticket.status_changed.v1 | Status tiket berubah, termasuk perubahan otomatis. |
ticket.assigned.v1 | Tim atau petugas tiket berubah. |
ticket.comment_added.v1 | Komentar publik ditambahkan. Catatan internal tidak pernah dikirim. |
sla.breached.v1 | Tenggat SLA respons atau penyelesaian terlampaui. |
Peristiwa boleh dikosongkan. Webhook tanpa peristiwa hanya menerima kiriman aturan automation yang memilihnya (automation.rule_triggered.v1). Lihat Automation. Kartu webhook menyebut aturan yang mengirim ke sana.
- Klik Simpan, lalu salin rahasia penanda tangan (
whsec_…). Rahasia hanya tampil sekali. Bila hilang, pakai Ganti rahasia. - Klik Kirim uji pada kartu webhook untuk mengirim
ping.v1ke penerima.
Satu workspace dapat memiliki paling banyak 10 webhook aktif. Webhook hanya menerima peristiwa yang terjadi sesudah ia dibuat.
Isi kiriman
RANCAQ mengirim POST berisi JSON:
{
"event_id": "5d0b…",
"event_type": "ticket.status_changed.v1",
"tenant_id": "…",
"occurred_at": "2026-10-06T13:20:05Z",
"actor": { "type": "user", "id": "…", "name": "Agus" },
"subject": { "type": "ticket", "id": "…", "number": "INC-2026-000123" },
"data": {
"ticket": { "number": "INC-2026-000123", "subject": "VPN putus", "status": "TRIAGED", "priority": "P2", "…": "…" },
"change": { "from": "NEW", "to": "TRIAGED" }
}
}
actor.type:useruntuk orang,integrationuntuk token API,systemuntuk perubahan otomatis RANCAQ.data.ticket: keadaan tiket saat peristiwa diproses, beberapa detik sesudah kejadian.- Data tambahan per peristiwa:
changeuntuk perubahan,commentuntuk komentar,slauntuk pelanggaran SLA.
Header yang ikut dikirim:
| Header | Isi |
|---|---|
X-ITSM-Event | Jenis peristiwa, sama dengan event_type. |
X-ITSM-Event-ID | Sama dengan event_id. |
X-ITSM-Delivery-ID | Pengenal kiriman, tetap untuk semua percobaan dan kirim ulang. |
X-ITSM-Delivery-Attempt | Nomor percobaan: 1, 2, dan seterusnya. |
X-ITSM-Timestamp | Detik Unix saat percobaan dikirim. |
X-ITSM-Signature | sha256= diikuti HMAC-SHA256. |
Memverifikasi tanda tangan
Hitung HMAC-SHA256 atas <X-ITSM-Timestamp>.<body mentah> dengan rahasia penanda tangan utuh (termasuk awalan whsec_) sebagai kunci. Lalu:
- bandingkan hasilnya dengan
X-ITSM-Signaturesecara constant-time; - tolak bila timestamp berselisih lebih dari 5 menit dari jam Anda.
Hitung atas byte body apa adanya, sebelum diurai JSON.
import crypto from 'node:crypto'
function sah(rahasia, timestamp, bodyMentah, tandaTangan) {
const hitung = 'sha256=' + crypto.createHmac('sha256', rahasia)
.update(`${timestamp}.${bodyMentah}`).digest('hex')
const a = Buffer.from(hitung), b = Buffer.from(tandaTangan)
const segar = Math.abs(Date.now() / 1000 - Number(timestamp)) < 300
return segar && a.length === b.length && crypto.timingSafeEqual(a, b)
}
import hmac, hashlib, time
def sah(rahasia: str, timestamp: str, body_mentah: bytes, tanda_tangan: str) -> bool:
hitung = "sha256=" + hmac.new(rahasia.encode(), timestamp.encode() + b"." + body_mentah,
hashlib.sha256).hexdigest()
return abs(time.time() - int(timestamp)) < 300 and hmac.compare_digest(hitung, tanda_tangan)
Contoh untuk menguji kode Anda: rahasia whsec_contoh, timestamp 1759750000, dan body {"event_id":"x"} menghasilkan sha256=b65486071794a9af8c19a14c7882303172b0131257324735b6abd3e060ddf454.
Kiriman ganda dan urutan
Pengiriman bersifat at-least-once: satu peristiwa bisa tiba lebih dari sekali, misalnya bila penerima memproses kiriman tetapi jawabannya tidak sampai sebelum batas waktu. Agar aman:
- simpan
event_idyang sudah diproses, lalu abaikan kiriman berikutnya denganevent_idyang sama; - jawab secepatnya dengan kode 2xx, lalu kerjakan prosesnya di belakang;
- jangan mengandalkan urutan tiba. Gunakan
occurred_atdan status didata.ticket.
Percobaan ulang dan riwayat
Kiriman dianggap berhasil bila penerima menjawab 2xx dalam 10 detik. Redirect tidak diikuti. Bila gagal, RANCAQ mencoba lagi 1 menit, 5 menit, 30 menit, 2 jam, dan 6 jam kemudian, dengan Delivery-ID dan body yang sama. Sesudah enam percobaan gagal, kiriman berstatus Gagal.
Tab Riwayat pengiriman menampilkan setiap kiriman beserta semua percobaannya: waktu, kode HTTP, pesan galat, dan cuplikan jawaban penerima. Saring per webhook, status, peristiwa, atau nomor tiket. Kirim ulang mengirim kiriman yang sudah selesai sekali lagi, dengan Delivery-ID dan event_id yang sama.
Nonaktif otomatis
Bila 5 kiriman berturut-turut berakhir Gagal (masing-masing sudah dicoba enam kali), webhook dinonaktifkan otomatis. Kartu webhook menampilkan alasan dan waktunya, dan Audit mencatatnya. Perbaiki penerima, lalu Aktifkan kembali. Kiriman yang masih menunggu akan dilanjutkan, dan kiriman yang sudah gagal dapat dikirim ulang dari riwayat.
Kegagalan webhook tidak pernah membatalkan perubahan tiket dan tidak menunda email notifikasi.
Lihat juga
- Audit log: jejak pembuatan, pencabutan, dan tindakan token.
- Antrean tiket: tiket berkanal API dapat disaring di antrean.