Webhook
Kirim event tugas, proyek, dan komentar ke layanan Anda sendiri sebagai callback HTTP bertanda tangan.
Webhook memberi tahu layanan Anda setiap kali sesuatu berubah di MyPlan. Saat tugas, proyek, atau komentar dibuat, diubah, atau dihapus, MyPlan mengirim permintaan POST berisi JSON ke URL yang Anda tentukan. Gunakan webhook untuk menyinkronkan data ke sistem lain, memicu otomatisasi, atau mengirim notifikasi ke alat internal.
Halaman ini menjelaskan cara mengaturnya, format payload, header, dan cara memverifikasi tanda tangan.
Tersedia di paket Business ke atas.
Event yang tersedia
| Grup | Event |
|---|---|
| Tugas | work_item.created, work_item.updated, work_item.deleted, work_item.moved |
| Proyek | project.created, project.updated, project.archived, project.restored, project.deleted, project.moved |
| Komentar | comment.created, comment.updated, comment.deleted |
Di dialog webhook, Anda bisa mencentang event satu per satu atau memilih semua untuk seluruh event dalam satu grup. Pilih minimal satu event. Event ping hanya dikirim oleh tombol Tes.
Langkah-langkah
Buka pengaturan Webhook
Buka Pengaturan workspace, lalu pilih Webhook.
Tambah webhook
Klik Tambah webhook. Isi URL payload dengan alamat http atau https lengkap milik layanan Anda, lalu pilih Event yang ingin dikirim. Klik Tambah webhook untuk menyimpan.
Simpan rahasia penandatangan
Setelah disimpan, MyPlan menampilkan Signing secret satu kali. Salin sekarang; ini tidak akan ditampilkan lagi. Layanan Anda memakai rahasia ini untuk memastikan permintaan benar-benar dari MyPlan.
Kirim tes
Klik Tes pada webhook. MyPlan mengirim event ping, lalu hasilnya muncul di Pengiriman.
Cara pengiriman bekerja
- Setiap pengiriman adalah
POSTJSON dengan header nama event, ID pengiriman yang unik, dan tanda tangan. - Tanda tangan adalah
sha256=diikuti HMAC-SHA256 heksadesimal dari body mentah, dengan kunci rahasia webhook. Hitung di sisi Anda dan bandingkan dalam waktu konstan. Lihat Memverifikasi tanda tangan. - Pengiriman habis waktu setelah 10 detik dan pengalihan (redirect) tidak diikuti.
- Setiap respons
2xxdihitung Terkirim; selain itu (atau tanpa respons) dihitung Gagal. - Pengiriman event yang gagal dicoba ulang otomatis setelah 1 menit, 5 menit, dan 30 menit (paling banyak empat percobaan). Di Pengiriman, percobaan ulang ditandai percobaan ke-2 dan seterusnya, dan pengiriman gagal yang masih punya jadwal menampilkan dicoba lagi beserta waktunya.
- Kirim ulang mengirim payload yang sama sekarang juga dan membatalkan percobaan ulang otomatis yang masih menunggu untuk event itu. Pengiriman Tes tidak dicoba ulang otomatis.
- Hanya webhook yang aktif yang menerima event.
Webhook tidak boleh mengarah ke alamat privat atau lokal (misalnya localhost, 127.0.0.1, 10.x.x.x, 192.168.x.x). MyPlan menolak URL seperti itu dengan pesan Webhook tidak boleh mengarah ke alamat privat atau lokal. Untuk pengujian lokal, gunakan layanan tunnel yang memberi alamat publik.
Isi data per event
| Event | Kapan dikirim | Isi data |
|---|---|---|
work_item.created | Work item dibuat (termasuk lewat impor) | Objek work item. Untuk impor: { "workItem": ..., "source": "import" } |
work_item.updated | Work item diubah, termasuk lewat bulk edit dan pemulihan versi | Objek work item setelah perubahan |
work_item.deleted | Work item dihapus | { "id", "projectId", "reference" } |
work_item.moved | Work item dipindah ke proyek lain | { "id", "title", "fromProject", "fromReference", "toProject", "toReference" } |
project.created | Proyek dibuat | { "project": ... } |
project.updated | Proyek diubah | { "project": ..., "fields": [...] } |
project.archived | Proyek diarsipkan | { "projectId", "name" } |
project.restored | Proyek dipulihkan dari arsip | { "projectId", "name" } |
project.deleted | Proyek dihapus | { "projectId", "name" } |
project.moved | Proyek dipindah ke workspace lain (dikirim ke kedua workspace) | { "projectId", "name", "details" } |
comment.created | Komentar ditambahkan (juga dari commit Git) | Objek komentar |
comment.updated | Komentar diedit | Objek komentar |
comment.deleted | Komentar dihapus | { "id", "taskId" } |
ping | Hanya saat Anda memilih Tes | { "message": "Webhook test from MyPlan" } |
Bentuk payload
Setiap pengiriman membungkus data event dalam amplop yang sama:
{
"id": "0193a6f2-7c1e-7b40-9d2a-5f1e8c3b2a10",
"event": "work_item.updated",
"workspaceId": "0193a6f2-0000-7000-8000-000000000001",
"createdAt": "2026-11-11T09:30:00Z",
"data": {
"id": "0193a6f2-1111-7000-8000-000000000002",
"reference": "WEB-42",
"title": "Perbaiki halaman login",
"statusId": "0193a6f2-2222-7000-8000-000000000003",
"statusCategory": "active",
"priority": 3,
"assigneeIds": ["0193a6f2-3333-7000-8000-000000000004"],
"dueOn": "2026-11-20"
}
}Objek work item di data berisi data lengkap work item (contoh di atas dipersingkat). Objek komentar berisi
id, taskId, authorId, bodyHtml, createdAt, dan editedAt.
Header
| Header | Isi |
|---|---|
Content-Type | application/json |
User-Agent | MyPlan-Webhooks/1 |
X-MyPlan-Event | Nama event, misalnya work_item.created |
X-MyPlan-Delivery | ID unik percobaan pengiriman ini. Setiap percobaan ulang dan kirim ulang mendapat ID baru. |
X-MyPlan-Signature | sha256= diikuti HMAC-SHA256 heksadesimal dari body mentah |
Memverifikasi tanda tangan
Rahasia webhook (diawali whsec_) ditampilkan sekali saat webhook dibuat atau saat Anda memilih Ganti rahasia.
Hitung HMAC-SHA256 dari body mentah (byte persis seperti yang diterima, sebelum diparse) dengan rahasia itu sebagai
kunci, lalu bandingkan dengan header dalam waktu konstan.
import { createHmac, timingSafeEqual } from "node:crypto";
import express from "express";
const app = express();
const SECRET = process.env.MYPLAN_WEBHOOK_SECRET; // whsec_...
app.post("/myplan", express.raw({ type: "application/json" }), (req, res) => {
const expected = "sha256=" + createHmac("sha256", SECRET).update(req.body).digest("hex");
const got = req.get("X-MyPlan-Signature") ?? "";
const ok = got.length === expected.length && timingSafeEqual(Buffer.from(got), Buffer.from(expected));
if (!ok) return res.status(401).end();
const event = JSON.parse(req.body.toString("utf8"));
console.log(event.event, event.data);
res.status(204).end();
});
app.listen(3000);Jangan menghitung tanda tangan dari JSON yang sudah diparse lalu diserialisasi ulang. Urutan field atau spasi bisa berbeda dan tanda tangan tidak akan cocok.
Mengelola webhook
Setiap webhook di daftar menampilkan URL, event yang dipilih, status pengiriman terakhir (Pengiriman terakhir berhasil atau Pengiriman terakhir gagal), dan Rahasia berakhiran … empat karakter terakhir rahasianya.
| Kontrol | Fungsi |
|---|---|
| Sakelar aktif | Menjeda atau mengaktifkan kembali webhook tanpa menghapusnya. |
| Tes | Mengirim event ping ke URL. |
| Pengiriman | Menampilkan hingga 100 pengiriman terbaru dengan kode status HTTP. Klik Tampilkan payload untuk melihat isi yang dikirim. |
| Kirim ulang | Mengirim ulang satu pengiriman dengan payload yang sama. |
| Edit | Mengubah URL payload dan event (Edit webhook). |
| Ganti rahasia | Menerbitkan rahasia baru. Rahasia lama langsung berhenti berfungsi, jadi perbarui layanan Anda. |
| Hapus | Menghapus webhook beserta riwayat pengirimannya. |
Menambah, mengubah, menghapus, dan mengganti rahasia webhook tercatat di log audit.
Tips
- Balas secepat mungkin dengan
2xx, lalu proses event di antrean Anda sendiri agar tidak terkena batas 10 detik. - Simpan
idevent dari payload dan abaikan duplikat, karena percobaan ulang dan Kirim ulang bisa mengirim event yang sama lebih dari sekali (header ID pengiriman berbeda di setiap percobaan). - Ganti rahasia secara berkala atau segera jika rahasia bocor.
- Webhook ini untuk event tugas, proyek, dan komentar. Untuk menautkan commit dan pull request, gunakan integrasi GitHub dan GitLab.
Izin
Mengelola webhook membutuhkan peran Admin atau Pemilik workspace (izin webhook.manage). Anggota lain melihat pesan Hanya admin workspace yang dapat melihat ini.
Ketersediaan paket
Webhook tersedia di paket Business ke atas. Lihat Paket dan tagihan.
Lewat MCP
Belum ada tool MCP untuk mengelola webhook.