API CRM
Membuat dan memperbarui kontak, deal, dan tugas dari aplikasi Anda sendiri.
Membuat dan memperbarui kontak, deal, dan tugas dari aplikasi Anda sendiri: formulir website, toko online, sistem ERP, atau AI agent.
Sebelum mulai
- Alamat dasar, autentikasi, dan bentuk balasan sama dengan Referensi API.
- API key wajib diberi scope CRM secara eksplisit. Scope Semua tidak mencakup CRM, supaya kunci integrasi lama tidak tiba-tiba bisa mengubah data penjualan.
| Scope | Membuka |
|---|---|
crm:read (CRM baca) |
Membaca pipeline dan kontak |
crm:write (CRM tulis) |
Semua endpoint di halaman ini, termasuk membaca |
Atur scope saat membuat kunci di menu API Keys. Lihat API Key & Keamanan.
- API CRM tidak membuat chat baru dan tidak mengirim pesan WhatsApp. Untuk mengirim pesan, pakai endpoint Pesan.
- Nomor telepon diterima dalam format
0812…,62812…, atau+62 812…. - Nilai uang dalam rupiah bulat, tanpa desimal.
Galat khusus CRM
| Status | error.code |
Artinya |
|---|---|---|
403 |
scope_missing |
Kunci tidak punya scope CRM yang dibutuhkan |
403 |
plan_feature_unavailable |
Paket workspace tidak menyertakan API CRM |
404 |
contact_not_found |
Kontak tidak ditemukan |
422 |
invalid_phone |
Nomor telepon tidak valid |
409 |
bervariasi | Bentrok dengan perubahan lain, misalnya deal sudah ditutup. Ambil ulang datanya, lalu putuskan apakah perlu diulang |
422 |
bervariasi | Data tidak valid. error.fields menunjukkan kolom yang bermasalah |
Pipeline
Daftar pipeline
GET /api/v1/pipelines · scope crm:read
Dipakai untuk mengetahui pipeline_id dan stage_id sebelum membuat atau memindahkan deal.
curl https://pesanvo.com/api/v1/pipelines -H "X-Api-Key: $KEY"
{
"success": true,
"data": [
{
"id": "01K2PIPE...",
"name": "Penjualan",
"is_default": true,
"archived": false,
"stages": [
{ "id": 11, "name": "Prospek", "type": "open", "position": 1, "probability": 10, "rot_days": 7 },
{ "id": 12, "name": "Penawaran", "type": "open", "position": 2, "probability": 40, "rot_days": 5 },
{ "id": 15, "name": "Berhasil", "type": "won", "position": 5, "probability": 100, "rot_days": null },
{ "id": 16, "name": "Gagal", "type": "lost", "position": 6, "probability": 0, "rot_days": null }
]
}
]
}
type bernilai open, won, atau lost.
Kontak
Buat atau perbarui kontak
POST /api/v1/contacts/upsert · scope crm:write
Kontak dicari berdasarkan nomor. Bila belum ada, kontak dibuat. Bila sudah ada, kolom yang Anda kirim diperbarui. Aman dipanggil berulang kali.
| Parameter | Tipe | Wajib | Keterangan |
|---|---|---|---|
phone |
string | ya | Nomor telepon |
name |
string, maks 120 | tidak | |
email |
string | tidak | |
labels |
array string, maks 20 | tidak | Ditambahkan ke label yang sudah ada. Label baru dibuat otomatis |
fields |
object | tidak | Nilai custom field kontak, dengan kunci field sebagai nama properti |
owner_email |
string | tidak | Email anggota workspace yang menjadi pemilik |
acquisition_source |
string | tidak | Hanya dipakai saat kontak baru dibuat. Salah satu dari organic, ctwa_ad, tracking_link, campaign, import, manual, api, referral |
curl -X POST https://pesanvo.com/api/v1/contacts/upsert \
-H "X-Api-Key: $KEY" \
-H "Content-Type: application/json" \
-d '{
"phone": "081234567890",
"name": "Budi Santoso",
"labels": ["Website"],
"fields": { "kota": "Bandung" },
"acquisition_source": "api"
}'
Balasan 201 bila kontak baru dibuat, 200 bila diperbarui. Isi data sama dengan Detail kontak, ditambah "created": true|false.
Detail kontak
GET /api/v1/contacts/{phone} · scope crm:read
curl https://pesanvo.com/api/v1/contacts/081234567890 -H "X-Api-Key: $KEY"
{
"success": true,
"data": {
"id": "01K2CONT...",
"name": "Budi Santoso",
"phone": "6281234567890",
"email": null,
"owner_id": 7,
"lifecycle_stage": "prospect",
"acquisition_source": "api",
"labels": ["Website"],
"fields": { "kota": "Bandung" },
"open_deals": [ ]
}
}
open_deals berisi hingga 20 deal terbuka milik kontak ini, dengan bentuk yang sama seperti deal.
Deal
Buat deal
POST /api/v1/deals · scope crm:write
| Parameter | Tipe | Wajib | Keterangan |
|---|---|---|---|
phone |
string | salah satu | Nomor kontak. Kontak dibuat otomatis bila belum ada |
contact_id |
string | salah satu | ID kontak yang sudah ada |
title |
string, maks 120 | ya | Judul deal |
value |
integer | tidak | Nilai dalam rupiah. Bawaan 0 |
pipeline_id |
string | tidak | Kosongkan untuk pipeline bawaan |
stage_id |
integer | tidak | Kosongkan untuk tahap pertama |
owner_email |
string | tidak | Email anggota workspace yang menjadi pemilik |
fields |
object | tidak | Nilai custom field deal |
external_id |
string, maks 100 | tidak | ID pesanan di sistem Anda. Lihat di bawah |
curl -X POST https://pesanvo.com/api/v1/deals \
-H "X-Api-Key: $KEY" \
-H "Content-Type: application/json" \
-d '{
"phone": "081234567890",
"title": "Order #INV-2041",
"value": 1250000,
"external_id": "INV-2041"
}'
Mencegah deal ganda dengan external_id
Bila external_id yang sama dikirim lagi, deal yang sudah ada dikembalikan dengan "created": false dan tidak ada deal baru yang dibuat. Kirim selalu external_id bila permintaan Anda bisa terulang, misalnya karena timeout atau antrean yang mengulang job.
Perbarui deal
PATCH /api/v1/deals/{id} · scope crm:write
| Parameter | Tipe | Keterangan |
|---|---|---|
title |
string | |
value |
integer | Ditolak 422 bila nilai deal dihitung dari produk |
owner_email |
string atau null |
null melepas pemilik |
fields |
object | Nilai custom field deal |
Kirim hanya kolom yang ingin diubah.
Pindah tahap
POST /api/v1/deals/{id}/stage · scope crm:write
| Parameter | Tipe | Wajib | Keterangan |
|---|---|---|---|
stage_id |
integer | ya | Tahap tujuan, dari Daftar pipeline |
lost_reason |
string | tidak | Dipakai bila tahap tujuan bertipe lost |
Tandai Berhasil
POST /api/v1/deals/{id}/won · scope crm:write
Tanpa parameter. Custom field wajib tidak menghalangi penutupan lewat API.
Tandai Gagal
POST /api/v1/deals/{id}/lost · scope crm:write
| Parameter | Tipe | Keterangan |
|---|---|---|
lost_reason |
string, maks 60 | Dicocokkan dengan nama alasan gagal di Pengaturan CRM. Bila tidak cocok, dipakai alasan "Lainnya" |
note |
string, maks 500 | Catatan tambahan |
Bentuk data deal
Semua endpoint deal mengembalikan bentuk yang sama:
{
"success": true,
"data": {
"id": "01K2DEAL...",
"title": "Order #INV-2041",
"value": 1250000,
"value_from_items": false,
"pipeline_id": "01K2PIPE...",
"stage_id": 11,
"stage": { "id": 11, "name": "Prospek", "type": "open" },
"status": "open",
"contact": { "id": "01K2CONT...", "name": "Budi Santoso", "phone": "6281234567890" },
"owner_id": 7,
"next_task": null,
"is_rotting": false,
"days_in_stage": 0,
"external_id": "INV-2041",
"fields": { },
"created": true
}
}
status bernilai open, won, atau lost. created hanya ada di balasan Buat deal.
Tugas
Buat tugas
POST /api/v1/tasks · scope crm:write
| Parameter | Tipe | Wajib | Keterangan |
|---|---|---|---|
deal_id |
string | salah satu | Tugas untuk deal ini |
phone |
string | salah satu | Tugas untuk kontak ini. Kontaknya harus sudah ada |
title |
string, maks 200 | ya | |
due_at |
tanggal ISO 8601 | ya | Jatuh tempo |
type |
string | tidak | follow_up (bawaan), call, meeting, send_quote, other |
owner_email |
string | tidak | Email anggota yang mengerjakan |
curl -X POST https://pesanvo.com/api/v1/tasks \
-H "X-Api-Key: $KEY" \
-H "Content-Type: application/json" \
-d '{
"phone": "081234567890",
"title": "Telepon konfirmasi alamat pengiriman",
"due_at": "2026-11-20T10:00:00+07:00",
"type": "call"
}'
Balasan 201 dengan data tugas.
Menerima perubahan
API CRM dipakai untuk mengirim data ke Pesanvo. Untuk mendengar perubahan yang dibuat tim Anda, misalnya deal berhasil atau tagihan lunas, daftarkan Webhook dan pilih kejadian CRM seperti deal.won atau invoice.paid.
Contoh alur: toko online
- Pembeli checkout di website →
POST /api/v1/contacts/upsertlaluPOST /api/v1/dealsdenganexternal_idnomor pesanan. - Sales menindaklanjuti di Inbox dan mengirim tagihan dari Kasir.
- Pembeli membayar → webhook
invoice.paiddandeal.wonsampai di server Anda → pesanan diproses gudang.
Pertanyaan seputar artikel ini?
Tim dukungan teknis kami siap menjawab pertanyaan implementasi Anda.