Guide

API webhook Deskgram 2: metode, JSON, dan tanda tangan

Referensi REST API lokal: endpoint, peristiwa, pemetaan, riwayat, percobaan ulang, HMAC, dan perbedaan MCP.

settings14 menit2026-10-24

Key Takeaways

  • Buat endpoint nonaktif untuk memeriksa konfigurasi sebelum pengiriman otomatis:
  • Ambil endpoint.id dari respons. Untuk contoh ID 12, kirim pengujian:
  • Periksa success, delivery.response status code, delivery.response body, dan penerimaan sesungguhnya. Pengujian tidak memuat lead nyata sehingga bisa ditolak validasi bisnis CRM.
  • Aktifkan melalui antarmuka atau kirim pengaturan lengkap menggunakan PUT dengan enabled: true. PUT bukan pembaruan sebagian.

Ringkasan modul webhook

Kontrak diperiksa berdasarkan kode pada 24 Oktober 2026. Dokumen ini menjelaskan implementasi yang tersedia, bukan rencana. Untuk konfigurasi melalui antarmuka, lihat panduan pengguna.

Dua arah permintaan

ArahPemanggilAlamatTujuan
API pengelolaan lokalSkrip lokal → Deskgramhttp://127.0.0.1:5000/api/webhooksMengatur endpoint dan memeriksa pengiriman
Webhook keluarDeskgram → penerima AndaURL pada endpointMengirim peristiwa dengan POST JSON

Host dan port adalah contoh backend lokal; gunakan alamat instalasi Anda. Ini bukan API lisensi, server MCP, atau metode setWebhook/getUpdates Telegram Bot API.

Rute REST ini tidak melakukan pemeriksaan Bearer tersendiri. Gunakan lingkungan lokal tepercaya; jangan membuka port backend ke internet untuk webhook keluar. Pengiriman tidak membutuhkan koneksi masuk ke komputer Deskgram. Jika ada gateway autentikasi sendiri, atur secara terpisah.

Respons lokal menggunakan JSON. Sertakan Content-Type: application/json saat mengirim pengaturan melalui POST/PUT.

Mulai cepat API

Contoh curl memakai shell yang mendukung tanda kutip tunggal. Di PowerShell, gunakan curl.exe dan aturan versi shell untuk argumen JSON. Domain, ID, dan rahasia bersifat fiktif. Teks Rusia dalam contoh hanya nilai ilustrasi, bukan nilai wajib.

  1. Buat endpoint nonaktif untuk memeriksa konfigurasi sebelum pengiriman otomatis:
curl -X POST 'http://127.0.0.1:5000/api/webhooks/endpoints' \  -H 'Content-Type: application/json' \  --data '{"name":"CRM: рассылка","url":"https://receiver.example.com/deskgram","secret":"YOUR_SHARED_SECRET","events":["message.sent","message.failed","lead.reply_received"],"module_filter":["spam_pm"],"payload_template":"deskgram","enabled":false}'
  1. Ambil endpoint.id dari respons. Untuk contoh ID 12, kirim pengujian:
curl -X POST 'http://127.0.0.1:5000/api/webhooks/endpoints/12/test'
  1. Periksa success, delivery.responsestatuscode, delivery.response_body, dan penerimaan sesungguhnya. Pengujian tidak memuat lead nyata sehingga bisa ditolak validasi bisnis CRM.
  2. Aktifkan melalui antarmuka atau kirim pengaturan lengkap menggunakan PUT dengan enabled: true. PUT bukan pembaruan sebagian.
  3. Lakukan tindakan nyata yang sesuai dengan peristiwa, lalu periksa riwayat:
curl 'http://127.0.0.1:5000/api/webhooks/deliveries?endpoint_id=12&limit=20'

Objek endpoint

Bidang pembuatan dan pembaruan

POST dan PUT menggunakan model yang sama.

BidangTipeBawaanAturan
namestringWajib1–120 karakter sebelum spasi tepi dihapus; gunakan nama tidak kosong
urlstringWajib8–2000 karakter, diawali http:// atau https://; HTTPS disarankan
methodstringPOSTHanya POST
secretstring atau nullnull saat dibuatSpasi tepi dihapus; di PUT, tidak disertakan mempertahankan, null/kosong menghapus
headersobject bernilai string{}Header tambahan penerima, bukan kredensial Deskgram
eventsarray string["task.completed"]Enam peristiwa katalog atau "*"; daftar kosong menjadi task.completed
module_filterarray string[]Kosong berarti semua modul; contoh ["spam_pm"]
payload_templatestringdeskgramdeskgram, shortresult, crmlead, custom
payload_mappingobject{}Pengaturan bidang keluaran di bawah
enabledbooleantrueMengizinkan pengiriman otomatis peristiwa cocok
timeout_secondsnumber153–60 detik

Pada endpoint biasa, timeout berlaku untuk operasi jaringan klien HTTP, bukan batas total ketat panggilan lokal. Test dan retry menunggu pengiriman selesai, termasuk percobaan otomatis dan jeda.

Nama modul menjadi huruf kecil dan - diganti _. Entri peristiwa/modul duplikat dihapus. "*" mencakup peristiwa yang benar-benar masuk mekanisme ini, bukan menambahkan integrasi yang belum dimiliki modul lain.

Bidang respons

Selain pengaturan, tersedia id integer, hassecret boolean, createdat dan updated_at dalam UTC. secret selalu null, sekalipun rahasia tersimpan.

REST API lokal mengembalikan nilai headers tanpa penyamaran. Nilainya dapat memuat token penerima; jangan membagikan respons lengkap dalam log publik atau pesan dukungan.

Contoh respons pembuatan:

{  "success": true,  "endpoint": {    "id": 12,    "name": "CRM: рассылка",    "url": "https://receiver.example.com/deskgram",    "method": "POST",    "secret": null,    "has_secret": true,    "headers": {},    "events": ["message.sent", "message.failed", "lead.reply_received"],    "module_filter": ["spam_pm"],    "payload_template": "deskgram",    "payload_mapping": {},    "enabled": false,    "timeout_seconds": 15.0,    "created_at": "2026-10-15T10:00:00Z",    "updated_at": "2026-10-15T10:00:00Z"  }}

Metode API

Semua jalur menyertakan /api. Operasi selesai menggunakan HTTP 200, termasuk membuat dan menghapus. endpointid dan deliveryid adalah ID integer catatan.

GET /api/webhooks/endpoints

Daftar diurutkan berdasarkan waktu pembuatan, terbaru dahulu, tanpa parameter paginasi. Respons: {"endpoints": [...]} berisi objek endpoint. Daftar kosong: {"endpoints": []}.

POST /api/webhooks/endpoints

Membuat endpoint dengan model di atas. Respons: {"success": true, "endpoint": {...}}.

Tanpa enabled, endpoint langsung aktif. Kirim false secara eksplisit saat pengaturan awal.

PUT /api/webhooks/endpoints/{endpoint_id}

Memperbarui endpoint. Wajib menyertakan name, url, dan semua pengaturan yang hendak dipertahankan. Bidang yang tidak disertakan kembali ke bawaan, kecuali secret.

Jangan langsung mengirim ulang objek respons: secret: null akan menghapus rahasia tersimpan. Hilangkan seluruh kunci secret untuk mempertahankannya. Null atau string kosong eksplisit menghapusnya.

Contoh mengaktifkan sambil mempertahankan rahasia:

{  "name": "CRM: рассылка",  "url": "https://receiver.example.com/deskgram",  "method": "POST",  "headers": {},  "events": ["message.sent", "message.failed", "lead.reply_received"],  "module_filter": ["spam_pm"],  "payload_template": "deskgram",  "payload_mapping": {},  "enabled": true,  "timeout_seconds": 15}

Respons: {"success": true, "endpoint": {...}}. Endpoint tidak ditemukan: HTTP 404.

DELETE /api/webhooks/endpoints/{endpoint_id}

Menghapus endpoint tanpa badan permintaan. Respons: {"success": true, "endpoint_id": 12}. Jika tidak ada, HTTP 404.

Riwayat tetap ada. Penghapusan tidak membatalkan pengiriman yang sudah berjalan; catatan tidak dapat dicoba ulang setelah endpoint dihapus.

POST /api/webhooks/endpoints/{endpoint_id}/test

Mengirim pengujian hanya ke endpoint tersebut. Tidak memerlukan badan dan tidak menerima payload pengujian bebas.

Dapat digunakan saat endpoint nonaktif, tanpa batas langganan peristiwa atau filter modul. Mapping saat ini tetap diterapkan. Respons menunggu pengiriman dan percobaan otomatis selesai.

Contoh penerima menolak format standar dengan HTTP 403:

{  "success": false,  "delivered": 0,  "delivery_id": 45,  "status": "error",  "delivery": {    "id": 45,    "endpoint_id": 12,    "event_type": "webhook.test",    "task_id": null,    "status": "error",    "attempts": 3,    "response_status_code": 403,    "response_body": "Forbidden",    "error": "HTTP 403",    "created_at": "2026-10-15T10:01:00Z",    "updated_at": "2026-10-15T10:01:07Z",    "delivered_at": null,    "request_payload": {      "schema_version": "1.0",      "event": "webhook.test",      "occurred_at": "2026-10-15T10:01:00Z",      "source": "deskgram",      "test": true,      "endpoint": {"id": 12, "name": "CRM: рассылка"}    },    "source_payload": {      "schema_version": "1.0",      "event": "webhook.test",      "occurred_at": "2026-10-15T10:01:00Z",      "source": "deskgram",      "test": true,      "endpoint": {"id": 12, "name": "CRM: рассылка"}    }  }}

HTTP API lokal tetap 200. Angka 403 adalah status penerima di dalam delivery. Berhasil: success: true, delivered: 1, status: "success".

Jika catatan tidak dibuat, delivery_id dan delivery dapat null, success false. Endpoint hilang menghasilkan HTTP 404 lokal.

GET /api/webhooks/deliveries

Daftar pengiriman berdasarkan pembuatan, terbaru dahulu.

Parameter queryTipeBawaanArti
endpoint_idintegerTidak ditentukanID endpoint
event_typestringTidak ditentukanNama persis, misalnya message.failed
statusstringTidak ditentukanpending, retrying, success, error
limitinteger1001–500 catatan

Respons: {"deliveries": [...]}. Setiap objek tanpa requestpayload dan sourcepayload. Tidak ada offset, kursor, atau jumlah keseluruhan.

GET /api/webhooks/deliveries/{delivery_id}

Detail dengan requestpayload dan sourcepayload: {"delivery": {...}}. Tidak ditemukan: HTTP 404.

POST /api/webhooks/deliveries/{delivery_id}/retry

Mencoba ulang secara manual catatan berstatus error. Tidak membutuhkan badan. Membuat catatan baru dan menunggu percobaannya selesai. Diizinkan meskipun endpoint nonaktif.

Respons memuat success boolean, originaldeliveryid integer, status string, dan delivery baru lengkap. id serta X-Deskgram-Delivery-Id berbeda; catatan awal tetap. Kegagalan penerima tetap HTTP 200 lokal dengan success: false.

HTTP 400: sumber bukan error atau percobaan manualnya sedang berjalan dalam proses ini. HTTP 404: delivery atau endpoint tidak ditemukan.

GET /api/webhooks/events

Katalog enam peristiwa beserta label. Contoh mempertahankan label Rusia yang memang dikembalikan API; penerjemahan dokumen tidak mengubah nilai tersebut.

{  "events": [    {"event": "task.completed", "label": "Задача завершена"},    {"event": "task.failed", "label": "Задача завершилась ошибкой"},    {"event": "task.cancelled", "label": "Задача остановлена"},    {"event": "lead.reply_received", "label": "Получен ответ лида"},    {"event": "message.sent", "label": "Сообщение отправлено"},    {"event": "message.failed", "label": "Ошибка отправки сообщения"}  ]}

webhook.test dikirim lewat metode pengujian dan tidak ada dalam katalog langganan. "*" diterima di pengaturan tetapi juga tidak dicantumkan katalog.

Objek delivery

BidangTipeArti
idintegerID dalam basis data lokal
endpoint_idintegerID endpoint, termasuk yang kemudian dihapus
event_typestringNama peristiwa terlepas dari mapping keluaran
task_idstring atau nullID tugas jika tersedia
statusstringpending, retrying, success, error
attemptsintegerJumlah percobaan otomatis
responsestatuscodeinteger atau nullStatus HTTP terakhir; bisa null pada gangguan jaringan
response_bodystring atau nullRespons terakhir dipotong; bisa null pada gangguan jaringan
errorstring atau nullDiagnostik, bukan bidang kesalahan bisnis CRM
createdat, updatedatstringWaktu UTC ISO 8601 berakhiran Z
delivered_atstring atau nullWaktu pengiriman berhasil
request_payloadobjectJSON sesudah mapping; hanya detail/test/retry
source_payloadobjectPeristiwa asli; catatan lama mungkin {}; hanya detail/test/retry

Transport biasa menyimpan respons sampai 2000 karakter; transport MCP terlindungi juga membatasi byte yang dibaca. Riwayat bukan jejak HTTP lengkap: header terkirim dan semua respons percobaan perantara tidak disimpan.

Peristiwa dan JSON keluar

Contoh menggunakan payload_template: "deskgram". Mapping mengubah struktur luar, tetapi X-Deskgram-Event tetap nama peristiwa.

Peristiwa akhir tugas

PeristiwaArti
task.completedEksekusi selesai, tidak menjamin setiap tindakan berhasil
task.failedStatus akhir gagal
task.cancelledTugas dihentikan/dibatalkan
{  "schema_version": "1.0",  "event": "task.completed",  "occurred_at": "2026-10-15T10:05:00Z",  "source": "deskgram",  "task": {    "task_id": "12345",    "task_name": "Тестовая рассылка",    "module_name": "spam_pm",    "status": "completed",    "created_at": "2026-10-15T10:04:00Z",    "completed_at": "2026-10-15T10:05:00Z",    "accounts_count": 1,    "params": {},    "statistics": {},    "result": {}  }}

params, statistics, result bergantung pada modul; tidak ada skema penghitung universal. taskname, modulename, created_at bisa null. Failed/cancelled memakai keluarga struktur sama dengan peristiwa, status, hasil yang sesuai.

Peristiwa pesan langsung

Saat ini message.sent, message.failed, lead.replyreceived terhubung ke spampm. Filter modul lain tidak menciptakan sumber baru.

Contoh pesan terkirim:

{  "schema_version": "1.0",  "event": "message.sent",  "occurred_at": "2026-10-15T10:04:20Z",  "source": "deskgram",  "module": "spam_pm",  "task": {    "task_id": "12345",    "campaign_id": "spam_pm:12345",    "module_name": "spam_pm"  },  "account": {"id": "987654321"},  "lead": {    "telegram_user_id": "123456789",    "username": "example_client",    "raw_identifier": "@example_client"  },  "message": {    "message_id": 1001,    "message_text": "Здравствуйте!",    "raw_identifier": "@example_client",    "text": "Здравствуйте!",    "status": "sent"  }}

lead dan message bergantung data yang tersedia. Telepon, username, nama, ID, atau teks bisa tidak ada. Gunakan message.text untuk mapping teks. message_text adalah tambahan jalur tertentu, bukan bidang universal.

message.failed memuat error dan status yang tersedia di message; ID pesan terkirim mungkin tidak ada. Melewati penerima atau gagal mengenalinya tidak selalu menghasilkan peristiwa.

lead.replyreceived dapat memuat messageid, text, media_type, datetime, timestamp, status: "received". Hanya muncul jika penangan aktif benar-benar menerima balasan. Webhook tidak menyalakan pemantauan terus-menerus atau menjamin balasan setelah tugas selesai.

message.sent bukan bukti dibaca. Perlakukan ID sebagai nilai buram: ID tugas, akun, pengguna Telegram berupa string; message_id tertentu dapat berupa angka.

Peristiwa pengujian

Memuat schemaversion, event: "webhook.test", occurredat, source, test: true, endpoint: {id, name}. Struktur lengkap terdapat pada contoh metode test.

Tidak ada task, lead, account, atau message. Mapping hanya dari lead menghasilkan {}.

Pemetaan bidang

deskgram mengirim seluruh peristiwa asli dan mengabaikan payload_mapping. Pilih format lain untuk membatasi data.

Untuk shortresult, crmlead, custom, format eksplisit yang disarankan:

{  "fields": [    {"target": "event", "source": "event", "enabled": true},    {"target": "contact.telegram_id", "source": "lead.telegram_user_id", "enabled": true},    {"target": "contact.username", "source": "lead.username", "enabled": true},    {"target": "comment", "source": "message.text", "enabled": true},    {"target": "status", "source": ["message.status", "task.status"], "enabled": true}  ]}

Masukkan seluruh objek ke payload_mapping. target adalah jalur penerima; source adalah jalur dalam peristiwa asli, bukan konstanta atau ekspresi.

Hasil contoh message.sent:

{  "event": "message.sent",  "contact": {"telegram_id": "123456789", "username": "example_client"},  "comment": "Здравствуйте!",  "status": "sent"}

Aturan:

  • Titik pada target membuat objek bertingkat. Hindari jalur bertabrakan seperti contact dan contact.username sekaligus.
  • source membaca kunci objek dengan titik; tidak mendukung indeks array atau templat {{...}}.
  • Nilai tidak tersedia/null dihilangkan. Sumber tunggal mempertahankan 0, false, string kosong dengan tipe JSON asli.
  • Daftar sumber memilih nilai pertama selain null, string kosong, daftar kosong, objek kosong. Bentuk "message.status|task.status" juga didukung.
  • enabled: false meniadakan bidang; tidak ada enabled berarti aktif.
  • {"fields": []} atau semua dinonaktifkan menghasilkan {}, tanpa menggantinya dengan payload lengkap.
  • payloadmapping: {} memakai bidang bawaan pada shortresult/crm_lead; custom menghasilkan {}. fields eksplisit menetapkan kontrak pasti.

shortresult bawaan menggunakan event, occurredat, taskid, module, status, lead, message, error yang tersedia. crmlead bawaan menggunakan event, occurredat, taskid, accountid, telegramuserid, username, phone, firstname, lastname, rawidentifier, messageid, messagetext, messagestatus, messageerror.

Antarmuka dapat menyimpan daftar fields tersendiri yang bisa diedit untuk preset. Pengaturan tersimpan menentukan keluaran aktual, bukan hanya nama preset.

Header keluar

HeaderNilai
Content-Typeapplication/json
User-AgentDeskgram-Webhooks/1.0
X-Deskgram-Delivery-IdID catatan berupa string
X-Deskgram-EventNama peristiwa
x-secretRahasia bersama jika diatur
X-Deskgram-Webhook-SecretRahasia yang sama
X-Deskgram-SignatureTanda tangan sha256= jika ada rahasia

Rahasia dipakai untuk HMAC sekaligus dikirim melalui dua header. Gunakan HTTPS dan jangan mencatat nilainya dalam log publik.

headers tidak dapat mengganti Content-Type, User-Agent, Delivery-Id, Event serta tiga header rahasia saat dikonfigurasi, tanpa memandang kapitalisasi. Header lain, misalnya Authorization penerima, ditambahkan terpisah.

Verifikasi tanda tangan

Algoritme: HMAC-SHA256(secretutf8, rawrequest_body). Header berisi sha256= diikuti digest heksadesimal huruf kecil.

Yang ditandatangani adalah byte persis yang dikirim. JSON UTF-8, tanpa escape ASCII teks non-ASCII, kunci diurutkan, pemisah ringkas. Gunakan badan HTTP mentah, bukan JSON yang diparse lalu diserialkan ulang.

Contoh Python hanya memakai pustaka standar:

import hashlibimport hmacdef verify_deskgram_signature(raw_body: bytes, signature: str, secret: str) -> bool:    if not secret or not signature:        return False    expected = "sha256=" + hmac.new(        secret.encode("utf-8"), raw_body, hashlib.sha256    ).hexdigest()    try:        return hmac.compare_digest(expected, signature)    except TypeError:        return False

Berikan byte mentah, X-Deskgram-Signature, dan rahasia tersimpan di penerima. Jangan menjalankan tindakan bisnis jika verifikasi gagal. Ambil rahasia dari konfigurasi terlindungi, bukan x-secret masuk.

Tanda tangan saja tidak mencegah pengulangan badan bertanda tangan. Penerima memerlukan pemeriksaan umur dan deduplikasi. Delivery-Id tidak masuk badan bertanda tangan. Rahasia dipangkas; gunakan ASCII tidak kosong tanpa spasi tepi, sampai 1000 karakter.

Percobaan ulang dan jaminan

  • Hanya HTTP 200–299 berhasil; 3xx tidak diikuti. HTTP 200 dengan kesalahan bisnis JSON tetap keberhasilan transport.
  • Maksimal tiga percobaan, jeda sekitar 2 dan 4 detik sebelum kedua/ketiga. Gangguan jaringan dan HTTP termasuk 4xx diulang. Retry-After tidak ditangani khusus.
  • Percobaan otomatis mempertahankan badan dan Delivery-Id. Penerima harus menghindari tindakan ganda setelah berhasil.
  • Retry manual memakai URL, rahasia, headers saat ini. Dengan sourcepayload, mapping saat ini diterapkan pada peristiwa asli; catatan lama tanpa sumber mengirim requestpayload tersimpan tanpa mapping kedua.
  • Retry manual membuat Delivery-Id baru. Deduplikasi bisnis juga perlu identitas tugas/akun/pesan dan jenis peristiwa sesuai alur.
  • Delivery-Id unik dalam satu basis data lokal, bukan semua instalasi. Bedakan pengirim jika ada beberapa.
  • Tidak menjamin exactly-once, urutan antarperistiwa, atau pemulihan antrean otomatis setelah proses berhenti. Catatan pending/retrying terputus tidak berarti dilanjutkan saat mulai lagi.
  • Menonaktifkan menghentikan pemilihan otomatis baru, bukan pengiriman berjalan. Test/retry eksplisit bisa mengirim ke endpoint nonaktif.

Alur penerima yang disarankan: verifikasi, simpan atau antrekan dengan andal, balas 2xx, lakukan pemrosesan lama secara terpisah.

Kesalahan API

HTTP lokalKondisi
200Operasi selesai; periksa success/delivery pada test/retry
400Metode/format/peristiwa tidak didukung, URL tanpa http(s), retry tidak valid
404Endpoint/delivery hilang atau endpoint asal dihapus
422Validasi badan, tipe, atau rentang limit/timeout gagal

Contoh; teks server sebenarnya bisa tetap Rusia:

{"detail": "Webhook endpoint не найден"}

Pada validasi, detail bisa array diagnostik FastAPI, bukan string. Gangguan basis data/backend bisa menghasilkan kesalahan server; itu berbeda dari respons CRM luar.

Perbedaan MCP

MCP adalah antarmuka pengelolaan agen AI tersendiri, bukan nama lain REST API ini. Lihat koneksi MCP.

SifatREST lokalAlat MCP
Endpoint baruenabled=true bawaanNonaktif
PratinjauPermintaan dijalankanPembuatan/perubahan default dry-run sesuai pengaturan MCP
PembaruanPUT penuh, pengecualian secretSebagian
URLhttp(s); jangan publikasikan API lokalHanya HTTPS publik dengan perlindungan jaringan
Timeout3–60 detik3–30 detik
PembacaanURL, nilai headers, detail payload lengkapTanpa rahasia, nilai headers, badan lengkap

Endpoint yang dibuat atau diambil alih lewat tindakan MCP nyata yang sesuai mempertahankan perlindungan untuk pengiriman berikutnya, termasuk dari antarmuka. PUT biasa tidak menghapusnya. Membaca, dry-run, menonaktifkan, menghapus tidak dengan sendirinya memasukkan endpoint lama ke kebijakan baru.

Sumber kontrak

Untuk pemeliharaan: model/rute web/routes/api/webhooks.py; peristiwa, tanda tangan, retry web/webhookdispatcher.py; data langsung functions/functions/spampm/crmintegration.py; transport terlindungi web/webhooknetwork.py; MCP web/mcp/webhooks.py. Jalur repositori ini untuk pengelola; konfigurasi tidak membutuhkan akses kode.

Lanjutkan

Unduh Deskgram 2

Langkah berikutnya

Helpful Links