Your AI Connector Docs

API Kontak

Kontak adalah satu orang yang Anda kirimi pesan — nama, nomor telepon, email, saluran, tag, kolom kustom, serta daftar dan kampanye tempat mereka berada. API Kontak memungkinkan Anda membuat kontak, mencarinya, memperbaruinya, memberi tag, mengimpornya secara massal, dan menghapusnya, semuanya tanpa menggunakan dasbor.

Semua jalur di halaman ini bersifat relatif terhadap URL dasar:

https://api.youraiconnector.com/v1

Jadi /contacts berarti https://api.youraiconnector.com/v1/contacts.

Baru menggunakan API? Baca Akses API terlebih dahulu — bagian ini mencakup cara membuat kunci API Anda, tiga cara untuk melakukan autentikasi, batas kecepatan, dan format kesalahan. Semua yang ada di halaman ini mengasumsikan Anda sudah memiliki kunci API yang berfungsi.


Tentang ID kontak

Setiap kontak memiliki ID unik. ID yang Anda dapatkan saat membuat kontak (di data.contactId) adalah ID yang sama yang Anda gunakan di tempat lain — untuk mengambil, memperbarui, memberi tag, mengirim pesan, atau menghapus kontak tersebut. Simpan sekali dan gunakan kembali.

Anda tidak perlu membuat kontak untuk mendapatkan ID-nya. Anda juga dapat mencarinya berdasarkan nomor telepon atau email (lihat Mendapatkan kontak), atau menelusuri semua kontak Anda (lihat Daftar kontak). Masing-masing metode tersebut mengembalikan ID yang sama.


Membuat kontak

POST /contacts

Menambahkan kontak baru ke akun Anda. Nomor telepon dengan kode negara wajib diisi — email saja tidak cukup. Semua kolom lainnya bersifat opsional.

Anda dapat secara opsional memasukkan kontak baru langsung ke dalam satu atau beberapa daftar dengan listId (satu daftar) atau listIds (sebuah array). Jika keduanya dikirim, listIds yang akan digunakan.

Setiap kolom yang Anda kirimkan yang bukan merupakan salah satu kolom pembuatan standar yang tercantum dalam tabel kolom Buat kontak di bawah (phoneNumber, firstName, lastName, email, channel, is_bot_active, is_private, lead_profile, listId, listIds, custom_fields) akan disimpan secara otomatis sebagai kolom kustom — sehingga payload datar dari alat seperti Make atau Zapier dapat berfungsi tanpa perlu melakukan nesting. Anda juga dapat meneruskan objek custom_fields secara eksplisit.

Bidang Wajib Deskripsi
phoneNumber Ya Nomor telepon kontak, dengan kode negara (contoh: +15551234567).
firstName Tidak Nama depan.
lastName Tidak Nama belakang.
email Tidak Alamat email.
channel Tidak Saluran pesan. Salah satu dari whatsapp, sms, whatsapp_web. Default ke whatsapp.
is_bot_active Tidak Apakah asisten AI membalas kontak ini. Default ke true.
is_private Tidak Tandai kontak sebagai pribadi. Saat true, asisten AI dimatikan untuk mereka. Default ke false.
lead_profile Tidak Catatan teks bebas tentang prospek.
listId Tidak ID daftar tunggal untuk menambahkan kontak.
listIds Tidak Larik ID daftar untuk menambahkan kontak (lebih diutamakan daripada listId).
custom_fields Tidak Objek bidang kunci/nilai Anda sendiri. Anda juga dapat meneruskannya sebagai kunci tingkat atas. Bidang dengan tipe (tanggal, angka, dropdown, kotak centang) divalidasi — lihat Tipe bidang kustom.

Nama alternatif umum diterima jika nama standar tidak ada: phone atau phone_number untuk nomor, first_name dan last_name untuk nama, serta full_name atau name, yang dipisah menjadi nama depan dan nama belakang. Oleh karena itu, kesalahan Missing required fields: phoneNumber berarti tidak ada nilai telepon yang diterima sama sekali, bukan karena kuncinya dieja secara berbeda.

cURL

curl -X POST "https://api.youraiconnector.com/v1/contacts?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "phoneNumber": "+15551234567",
    "firstName": "Jane",
    "lastName": "Smith",
    "email": "jane@example.com",
    "is_bot_active": true,
    "listIds": ["list123", "list456"]
  }'

JavaScript

const res = await fetch("https://api.youraiconnector.com/v1/contacts", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    phoneNumber: "+15551234567",
    firstName: "Jane",
    lastName: "Smith",
    email: "jane@example.com",
    is_bot_active: true,
    listIds: ["list123", "list456"],
  }),
});
const data = await res.json();
console.log(data.data.contactId);

Python

import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/contacts",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "phoneNumber": "+15551234567",
        "firstName": "Jane",
        "lastName": "Smith",
        "email": "jane@example.com",
        "is_bot_active": True,
        "listIds": ["list123", "list456"],
    },
)
print(res.json()["data"]["contactId"])

Respons

{
  "success": true,
  "data": {
    "message": "Successfully created new contact",
    "contactId": "contact_abc123",
    "listsAdded": ["list123", "list456"]
  }
}

ID kontak baru ada di data.contactId. Daftar tempat kontak tersebut ditambahkan akan dikembalikan dalam data.listsAdded.

Duplikat tidak dibuat. Jika kontak dengan nomor telepon yang sama sudah ada di saluran yang Anda buat, panggilan buat (create call) tidak membuat kontak kedua. Respons yang dikembalikan memiliki status HTTP 200 dan error_code bernilai 409 di dalam body, jadi lakukan percabangan pada error_code alih-alih pada status HTTP. ID kontak yang sudah ada dikembalikan sebagai contactId (dan data.contactId), sehingga Anda dapat langsung melanjutkannya:

{ "success": false, "error_code": 409, "error": "A contact with this phone number already exists for the current user.", "contactId": "abc123", "data": { "contactId": "abc123" } }

Hal yang sama berlaku untuk alamat email duplikat di saluran Email. Jika seat tim Anda hanya dapat melihat kontaknya sendiri dan kontak yang ada bukan salah satunya, ID tersebut tidak disertakan; cari kontak tersebut dengan Dapatkan kontak berdasarkan telepon atau email sebagai gantinya.

Ejaan WhatsApp yang setara dihitung sebagai nomor yang sama. Beberapa negara memiliki dua ejaan yang valid untuk saluran seluler yang sama dan WhatsApp mungkin melaporkan salah satunya: Meksiko (+52… dan +521… lama), Brasil (dengan atau tanpa digit kesembilan), dan Argentina (dengan atau tanpa 9 setelah +54). Pemeriksaan duplikat saat pembuatan dan pencocokan GET /contacts?phoneNumber= berlaku untuk kedua ejaan tersebut, sehingga Anda akan mendapatkan kembali kontak yang sudah ada, apa pun bentuk yang Anda kirimkan. phone_number yang tersimpan pada kontak tidak akan pernah ditulis ulang.


Mendapatkan kontak berdasarkan telepon atau email

GET /contacts?phoneNumber=... atau GET /contacts?email=...

Mencari satu kontak dan mengembalikan objek kontak lengkap yang diperkaya — termasuk daftar, tag, dan kampanye yang diselesaikan menjadi pasangan { id, name }, ditambah pesan terakhir yang dipertukarkan.

Berikan salah satu phoneNumber (dalam format internasional) atau email. Jika Anda tidak memberikan keduanya, endpoint yang sama ini akan beralih ke mode Daftar kontak.

cURL

curl "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts?phoneNumber=%2B15551234567&apiKey=YOUR_API_KEY"

JavaScript

const phone = encodeURIComponent("+15551234567");
const res = await fetch(`https://api.youraiconnector.com/v1/contacts?phoneNumber=${phone}`, {
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
console.log(data.contact);

Python

import requests

res = requests.get(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts",
    headers={"X-API-Key": "YOUR_API_KEY"},
    params={"phoneNumber": "+15551234567"},
)
print(res.json()["contact"])

Respons

{
  "success": true,
  "contactId": "contact_abc123",
  "contact": {
    "id": "contact_abc123",
    "firstName": "Jane",
    "lastName": "Smith",
    "email": "jane@example.com",
    "phoneNumber": "+15551234567",
    "channel": "whatsapp",
    "isBotActive": true,
    "isPrivate": false,
    "doNotDisturb": false,
    "lead_profile": null,
    "avatarUrl": "https://example.com/photo.jpg",
    "customFields": {},
    "lists": [{ "id": "list123", "name": "VIP customers" }],
    "tags": [{ "id": "tagHotLead", "name": "Hot lead" }],
    "campaigns": [{ "id": "campaign789", "name": "Spring promo" }],
    "currentCampaign": { "id": "campaign789", "name": "Spring promo" },
    "lastMessage": {
      "direction": "inbound",
      "body": "Sounds good, thanks!",
      "status": "received",
      "timestamp": "2026-06-09T10:21:00.000Z"
    },
    "adAttribution": {
      "visit_at": "2026-06-09T10:14:02.000Z",
      "matched_at": "2026-06-09T10:14:20.000Z",
      "match_method": "reference",
      "reference": "4827",
      "fbc": "fb.1.1749463000000.IwAR...",
      "fbp": "fb.1.1749000000000.123456789",
      "fbclid": "IwAR...",
      "gclid": null,
      "gbraid": null,
      "wbraid": null,
      "utm_source": "facebook",
      "utm_medium": "paid",
      "utm_campaign": "spring-promo",
      "utm_content": null,
      "utm_term": null,
      "landing_url": "https://yoursite.com/quiz?utm_source=facebook&utm_campaign=spring-promo",
      "referrer": "https://l.facebook.com/",
      "client_ip": "203.0.113.7",
      "user_agent": "Mozilla/5.0 (iPhone; ...)",
      "site_key": "YOUR_SITE_KEY",
      "visit_id": "visit_abc123"
    }
  }
}

adAttribution adalah klik pada iklan yang mengarahkan ke situs web Anda, yang dicocokkan dengan kontak ini oleh skrip klik iklan, atau null jika tidak ada. Bidang-bidang tersebut dijelaskan dalam Atribusi klik iklan untuk WhatsApp.

ID kontak dikembalikan baik di tingkat atas (contactId) maupun di dalam objek (contact.id). Jika tidak ada yang cocok, Anda akan mendapatkan 404 dengan { "success": false, "message": "Contact not found" }.

avatarUrl adalah foto profil kontak, yang diambil dari WhatsApp atau Meta saat mereka mengirim pesan kepada Anda. Ini bersifat baca-saja: Anda tidak dapat mengaturnya, dan ini adalah null untuk kontak yang tidak memiliki foto atau yang menghubungi Anda melalui saluran yang tidak membagikannya. Perlakukan tautan tersebut sebagai sementara alih-alih menyimpannya, karena beberapa tautan foto ini kedaluwarsa dan diperbarui secara otomatis. (Dalam endpoint daftar di bawah, nilai yang sama disebut avatar_url.)

Nomor telepon di URL. Tanda + dalam string kueri harus di-encode URL sebagai %2B, jika tidak, tanda tersebut akan dibaca sebagai spasi. Contoh di atas sudah melakukannya untuk Anda.


Kontak yang nomornya disembunyikan

Kontak WhatsApp Web dapat muncul tanpa nomor telepon jika WhatsApp menyembunyikannya dari perangkat yang ditautkan (lihat Kontak yang Nomornya Disembunyikan). Setiap kontak yang Anda baca memiliki dua kolom tambahan untuk hal ini: number_hidden (numberHidden pada bentuk kontak tunggal) dan whatsapp_lid (whatsappLid).

  • Untuk kontak dengan nomor tersembunyi, phone_number adalah null, number_hidden adalah true, dan whatsapp_lid berisi ID internal WhatsApp, dalam format 153055538446346@lid. Ini bukan nomor yang dapat dihubungi. Cocokkan kontak tersebut berdasarkan ID itu dari sistem Anda sendiri, dan teruskan sebagai phoneNumber ke pencarian ini untuk menemukan kembali kontak tersebut.
  • Untuk setiap kontak lainnya, number_hidden adalah false dan whatsapp_lid adalah ID yang dilaporkan WhatsApp untuk kontak tersebut, atau null.

Webhook keluar dan payload otomatisasi yang menyertakan kontak membawa tiga kolom yang sama, dan ekspor CSV kontak memiliki kolom Number Hidden dan WhatsApp LID di samping Phone Number. Setelah WhatsApp membagikan nomor aslinya, kontak akan diperbarui secara otomatis dan phone_number akan terisi.

Mendapatkan kontak berdasarkan ID

GET /contacts/{contactId}

Jika Anda sudah memiliki ID kontak, ambil datanya secara langsung. Bentuk responsnya identik dengan pencarian di atas.

cURL

curl "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123?apiKey=YOUR_API_KEY"

JavaScript

const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123", {
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
console.log(data.contact);

Python

import requests

res = requests.get(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
print(res.json()["contact"])

ID kontak yang tidak ada di akun Anda akan mengembalikan 404.


Mendapatkan statistik kontak

GET /contacts/{contactId}/stats

Mengembalikan statistik pesan gabungan untuk satu kontak: total, balasan AI vs manusia, kredit yang digunakan, serta stempel waktu pesan pertama/terakhir.

cURL

curl "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/stats?apiKey=YOUR_API_KEY"

JavaScript

const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/stats", {
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
console.log(data.totalMessages, data.creditsUsed);

Python

import requests

res = requests.get(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/stats",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
print(data["totalMessages"], data["creditsUsed"])

Respons

{
  "success": true,
  "totalMessages": 48,
  "sent": 21,
  "received": 27,
  "aiReplies": 18,
  "humanReplies": 3,
  "creditsUsed": 34,
  "botMessageCount": 18,
  "firstMessageAt": "2026-05-01T09:00:00.000Z",
  "lastMessageAt": "2026-06-09T10:21:00.000Z"
}

botMessageCount adalah penghitung pesan AI yang sama dengan yang diatur ulang oleh tombol “reset” dalam aplikasi pada sebuah kontak. creditsUsed adalah total kredit berjalan untuk kontak ini, bukan hanya angka untuk respons ini saja. ID kontak yang tidak ada di akun Anda akan mengembalikan 404.


Mendapatkan biaya kontak

GET /contacts/{contactId}/cost

Mengembalikan kredit yang telah digunakan oleh satu kontak, dibagi per percakapan (sesi obrolan), per jenis tindakan, dan biaya rata-rata percakapan yang ditangani AI sendiri dibandingkan dengan percakapan yang melibatkan tim Anda. Gunakan ini untuk menunjukkan kepada klien berapa biaya sebuah percakapan.

cURL

curl "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/cost?apiKey=YOUR_API_KEY"

JavaScript

const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/cost", {
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
console.log(data.total_credits, data.by_session.length);

Python

import requests

res = requests.get(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/cost",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
print(data["total_credits"], data["summary"]["contained"]["avg_credits"])

Respons

{
  "success": true,
  "contact_id": "contact_abc123",
  "total_credits": 23,
  "refunded_credits": 0,
  "unattributed_credits": 0,
  "by_session": [
    {
      "session_id": "hpWKxuTSXIKlylze5Ulx",
      "start": "2026-09-21T00:00:00.000Z",
      "end": "2026-09-24T17:41:52.052Z",
      "status": "ChatSessionClosed",
      "tag": null,
      "credits": 7,
      "actions": 7,
      "outcome": "handed_off"
    },
    {
      "session_id": "5kKnkI3DD4THIh2YVjey",
      "start": "2026-09-09T00:00:00.000Z",
      "end": "2026-09-11T22:42:34.056Z",
      "status": "ChatSessionClosed",
      "tag": null,
      "credits": 13,
      "actions": 14,
      "outcome": "contained"
    }
  ],
  "by_type": [
    { "type": "AI Chat Conclude Evaluation", "credits": 8, "actions": 8 },
    { "type": "AI Tool Use", "credits": 4, "actions": 4 },
    { "type": "AI Message", "credits": 2, "actions": 2 }
  ],
  "summary": {
    "contained": { "sessions": 1, "credits": 13, "avg_credits": 13 },
    "handed_off": { "sessions": 1, "credits": 7, "avg_credits": 7 },
    "no_ai": { "sessions": 0, "credits": 0, "avg_credits": 0 }
  },
  "sessions_truncated": false
}

Catatan kolom:

  • total_credits menghitung setiap biaya pada kontak (balasan AI, panggilan alat, tag, tindak lanjut, ringkasan, langkah evaluasi latar belakang, biaya templat dan pengiriman) dengan pengurangan pengembalian dana pada kontak. Pemberian kredit, isi ulang, dan pembaruan tidak pernah menjadi milik kontak. Uji coba di Playground tidak disertakan.
  • Biaya masuk ke dalam percakapan yang jendelanya mencakup biaya tersebut. Jendela berjalan dari awal percakapan hingga ditutup atau percakapan berikutnya dimulai, sehingga tidak ada biaya yang dihitung dua kali. Biaya di luar setiap jendela berada di unattributed_credits (dan dalam total).
  • outcome: contained berarti AI membalas dan tidak ada seorang pun dari tim Anda yang perlu turun tangan; handed_off berarti seseorang mengirim pesan setelah AI membalas, atau AI memberi tahu manusia; no_ai berarti AI tidak pernah membalas dalam percakapan tersebut.
  • Hingga 200 percakapan dicantumkan, yang terbaru terlebih dahulu; sessions_truncated adalah true jika ada lebih banyak.
  • Untuk klien agensi, berikan sub_account_id; angka-angka tersebut dalam kredit klien itu sendiri.
  • creditsUsed pada Dapatkan statistik kontak adalah penghitung berjalan yang disimpan pada kontak. Titik akhir ini membangun kembali angka dari buku besar kredit, sehingga keduanya bisa sedikit berbeda, terutama pada kontak yang lebih lama.
  • Anggota tim memerlukan izin penagihan. Kontak yang tidak ada di akun Anda akan mengembalikan 404; 503 berarti angka tidak dapat dihitung saat ini, coba lagi sebentar lagi.

Mencantumkan kontak

GET /contacts

Panggil GET /contacts tanpa phoneNumber maupun email untuk menelusuri semua kontak Anda, dimulai dari yang terbaru. Setiap halaman mengembalikan ringkasan kontak yang ringkas (daftar, tag, dan kampanye dikembalikan sebagai array ID, bukan objek lengkap) dan sebuah next_cursor.

Parameter kueri Deskripsi
limit Ukuran halaman. Default-nya 50, maksimum 100.
cursor Nilai next_cursor dari halaman sebelumnya. Hilangkan pada halaman pertama.
listId Opsional. Hanya mengembalikan kontak yang termasuk dalam daftar ini.

Untuk menelusuri setiap halaman: lakukan panggilan pertama tanpa kursor, lalu terus berikan next_cursor yang dikembalikan sebagai cursor. Berhenti saat next_cursor bernilai null — itu berarti tidak ada lagi hasil yang tersisa.

cURL

curl "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts?limit=50&apiKey=YOUR_API_KEY"

# next page:
curl "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts?limit=50&cursor=contact_abc123&apiKey=YOUR_API_KEY"

JavaScript

async function listAllContacts() {
  const all = [];
  let cursor = null;
  do {
    const url = new URL("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts");
    url.searchParams.set("limit", "100");
    if (cursor) url.searchParams.set("cursor", cursor);
    const res = await fetch(url, { headers: { "X-API-Key": "YOUR_API_KEY" } });
    const data = await res.json();
    all.push(...data.contacts);
    cursor = data.next_cursor;
  } while (cursor);
  return all;
}

Python

import requests

def list_all_contacts():
    all_contacts = []
    cursor = None
    while True:
        params = {"limit": 100}
        if cursor:
            params["cursor"] = cursor
        res = requests.get(
            "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts",
            headers={"X-API-Key": "YOUR_API_KEY"},
            params=params,
        )
        data = res.json()
        all_contacts.extend(data["contacts"])
        cursor = data["next_cursor"]
        if not cursor:
            break
    return all_contacts

Respons

{
  "success": true,
  "contacts": [
    {
      "id": "contact_abc123",
      "first_name": "Jane",
      "last_name": "Smith",
      "email": "jane@example.com",
      "phone_number": "+15551234567",
      "number_hidden": false,
      "whatsapp_lid": null,
      "channel": "whatsapp",
      "is_bot_active": true,
      "is_private": false,
      "do_not_disturb": false,
      "avatar_url": "https://example.com/photo.jpg",
      "custom_fields": {},
      "created_at": "2026-06-01T09:00:00.000Z",
      "list_ids": ["list123"],
      "tag_ids": ["tagHotLead"],
      "campaign_ids": ["campaign789"],
      "current_campaign_id": "campaign789",
      "ad_attribution": null
    }
  ],
  "next_cursor": "contact_abc123"
}

Setiap kontak membawa ad_attribution: klik pada iklan yang mengarahkan ke situs web Anda, yang dicocokkan dengan kontak tersebut, dengan bidang yang sama seperti adAttribution pada Mendapatkan kontak berdasarkan ID, atau null jika tidak ada.

Catatan: Memfilter berdasarkan listId yang tidak ada di akun Anda akan mengembalikan 404. cursor yang tidak valid akan mengembalikan 400.


Menghitung kontak

GET /contacts/count

Mengembalikan berapa banyak kontak yang cocok dengan filter, ditambah pembagian per saluran, tanpa perlu melakukan paging. Ini adalah panggilan yang tepat untuk pertanyaan “berapa banyak” — ubin dasbor, otomatisasi, atau bertanya kepada Champ. Semua filter bersifat opsional, dan menggabungkan beberapa filter akan mempersempit jumlahnya (kontak harus cocok dengan setiap filter yang Anda kirim).

Parameter kueri Deskripsi
agentId Hanya kontak yang ditetapkan ke agen AI ini. Berikan none untuk kontak tanpa agen yang ditetapkan (kontak tersebut dijawab oleh agen default saluran).
channel Hanya kontak di saluran ini, contohnya whatsapp, messenger, instagram, sms, email, chat_widget.
tag Hanya kontak yang memiliki tag ini, berdasarkan nama tag (huruf besar/kecil tidak berpengaruh). Nama tag yang tidak Anda miliki akan mengembalikan 404.
listId Hanya kontak di daftar ini.
botActive true atau false — hanya kontak yang asisten AI-nya aktif atau nonaktif.
status Hanya kontak dengan status ini, contohnya Lead.
rules Objek aturan JSON yang di-encode URL, menggunakan bentuk yang sama dengan daftar cerdas (lihat Bentuk smart_rules di bawah). Tidak dapat digabungkan dengan filter lainnya.

Jangan kirim filter apa pun dan Anda akan mendapatkan jumlah total kontak di akun Anda.

cURL

# everything
curl "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/count?apiKey=YOUR_API_KEY"

# only the contacts one agent handles on Messenger
curl "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/count?agentId=agent_xyz789&channel=messenger&apiKey=YOUR_API_KEY"

JavaScript

const url = new URL("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/count");
url.searchParams.set("agentId", "agent_xyz789");
url.searchParams.set("channel", "messenger");

const res = await fetch(url, { headers: { "X-API-Key": "YOUR_API_KEY" } });
const data = await res.json();
console.log(data.total);

Python

import requests

res = requests.get(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/count",
    headers={"X-API-Key": "YOUR_API_KEY"},
    params={"agentId": "agent_xyz789", "channel": "messenger"},
)
data = res.json()
print(data["total"])

Respons

{
  "success": true,
  "total": 3423,
  "by_channel": { "messenger": 2744, "instagram": 667, "none": 12 },
  "filters": { "agentId": "agent_xyz789" }
}

by_channel membagi total yang sama per saluran; kontak yang tidak ada di saluran mana pun dihitung di bawah none. filters menggemakan kembali filter yang diterapkan, sehingga Anda dapat memeriksa apakah panggilan tersebut melakukan apa yang Anda maksudkan.

Catatan: Mengirim rules bersama dengan filter lain, atau nilai rules yang bukan JSON valid, akan mengembalikan 400. Nama tag atau ID daftar yang tidak ada di akun Anda akan mengembalikan 404.


Memperbarui kontak

PUT /contacts/{contactId}

Memperbarui kontak yang sudah ada. Hanya kolom yang Anda sertakan yang akan diubah — abaikan kolom yang tidak ingin Anda ubah. Anda harus mengirim setidaknya satu kolom, atau Anda akan mendapatkan 400 (“Tidak ada kolom untuk diperbarui”).

Bidang Deskripsi
firstName Nama depan.
lastName Nama belakang.
email Alamat email.
is_bot_active Apakah asisten AI membalas kontak ini.
is_private Tandai pribadi. Mengaturnya ke true juga mematikan asisten AI.
do_not_disturb Jeda penjangkauan otomatis ke kontak ini. Juga menghentikan AI dari membalas.
follow_ups_disabled Hentikan semua tindak lanjut otomatis untuk kontak ini (cepat, siklus, dan prospek dingin) sementara AI terus membalas pesan yang mereka kirim. Berguna setelah seseorang membeli. Tetap mati sampai Anda mengaturnya kembali ke false.
lead_profile Catatan prospek teks bebas.
custom_fields Objek bidang kustom. Digabungkan per kunci — hanya kunci yang Anda kirim yang ditulis, sisa bidang kustom yang ada tetap disimpan. Anda juga dapat meneruskan kunci bidang kustom di tingkat atas. Bidang bertipe divalidasi dan nilai yang buruk akan menolak permintaan dengan field_errors — lihat Tipe bidang kustom.

cURL

curl -X PUT "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "firstName": "Jane", "do_not_disturb": true }'

JavaScript

const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123", {
  method: "PUT",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ firstName: "Jane", do_not_disturb: true }),
});
const data = await res.json();
console.log(data.message);

Python

import requests

res = requests.put(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"firstName": "Jane", "do_not_disturb": True},
)
print(res.json()["message"])

Respons

{
  "success": true,
  "message": "Contact updated successfully"
}

Kolom kustom digabungkan, bukan diganti. Mengirim { "custom_fields": { "tier": "gold" } } hanya akan mengatur tier — kolom kustom lainnya pada kontak akan tetap seperti semula. Untuk menghapus kolom kustom sepenuhnya di semua kontak, gunakan Hapus kolom kustom.


Menambah atau menghapus tag

POST /contacts/{contactId}/tags

Menambah dan/atau menghapus tag pada satu kontak dalam satu panggilan. Teruskan ID tag di addTagIds dan removeTagIds. Setidaknya salah satu dari keduanya harus tidak kosong.

Tag tersebut harus sudah ada di akun Anda — buat tag terlebih dahulu melalui endpoint tag. Jika kontak atau tag yang dirujuk tidak ada, Anda akan mendapatkan 404.

Bidang Deskripsi
addTagIds Larik ID tag untuk ditambahkan ke kontak.
removeTagIds Larik ID tag untuk dihapus dari kontak.

cURL

curl -X POST "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/tags?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "addTagIds": ["tagHotLead"], "removeTagIds": ["tagColdLead"] }'

JavaScript

const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/tags", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    addTagIds: ["tagHotLead"],
    removeTagIds: ["tagColdLead"],
  }),
});
const data = await res.json();
console.log(data.added, data.removed);

Python

import requests

res = requests.post(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/tags",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"addTagIds": ["tagHotLead"], "removeTagIds": ["tagColdLead"]},
)
data = res.json()
print(data["added"], data["removed"])

Respons

{
  "success": true,
  "contact_id": "contact_abc123",
  "added": 1,
  "removed": 1
}

Mengelola pustaka tag Anda

Endpoint ini mengelola tag itu sendiri — mengganti nama atau menghapusnya di akun Anda — berbeda dengan menerapkan atau menghapus tag pada satu kontak (lihat Menambah atau menghapus tag di atas). Setiap tag di akun Anda memiliki ID (tagId): ID yang ditampilkan di pengelola tag dasbor Anda, dan ID yang dikembalikan sebagai tag_id di tingkat atas respons saat Anda membuat tag dengan POST /tags dan isi JSON { "name": "..." } (tanpa phoneNumber, email, atau contactId).

Memperbarui tag

PUT /tags/{tagId}

Kirim hanya kolom yang ingin Anda ubah.

Kolom Deskripsi
name Nama tag.
curl -X PUT "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/tags/tagHotLead?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Hot lead (Q3)" }'

Respons

{ "success": true, "tag_id": "tagHotLead" }

tagId yang tidak ada di akun Anda akan mengembalikan 404.

Menghapus tag

DELETE /tags/{tagId}

Menghapus satu tag berdasarkan ID. Tindakan ini tidak dapat dibatalkan — kontak yang memiliki tag tersebut akan kehilangan tag tersebut. Menghapus tag yang sudah tidak ada (atau tidak pernah ada) akan mengembalikan 200 dengan deleted: 0 alih-alih 404, karena tidak ada yang perlu dihitung.

curl -X DELETE "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/tags/tagColdLead?apiKey=YOUR_API_KEY"

Respons

{ "success": true, "deleted": 1 }

Menghapus beberapa tag sekaligus

DELETE /tags

Field Description
tagIds Array ID tag untuk dihapus (maks 1000).
curl -X DELETE "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/tags?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "tagIds": ["tagColdLead", "tagUnsubscribed"] }'

Respons

{ "success": true, "deleted": 2 }

ID yang tidak ada, atau milik akun lain, akan dilewati secara diam-diam dan tidak dihitung dalam deleted.


Mengatur flag secara massal

POST /contacts/bulk-flag

Mengatur satu flag boolean pada banyak kontak sekaligus. Hingga 500 ID kontak per permintaan. ID yang tidak ada di akun Anda akan dilewati dan dihitung dalam skipped.

Bidang Deskripsi
contactIds Larik ID kontak untuk diperbarui (maks 500).
field Flag mana yang akan diatur. Salah satu dari bot_active (asisten AI aktif/nonaktif), dnd (jeda jangkauan otomatis), spam, private.
value Nilai boolean untuk mengatur flag tersebut.

cURL

curl -X POST "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/bulk-flag?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "contactIds": ["contactId1", "contactId2"],
    "field": "bot_active",
    "value": false
  }'

JavaScript

const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/bulk-flag", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    contactIds: ["contactId1", "contactId2"],
    field: "bot_active",
    value: false,
  }),
});
const data = await res.json();
console.log(data.updated, data.skipped);

Python

import requests

res = requests.post(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/bulk-flag",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "contactIds": ["contactId1", "contactId2"],
        "field": "bot_active",
        "value": False,
    },
)
data = res.json()
print(data["updated"], data["skipped"])

Respons

{
  "success": true,
  "updated": 2,
  "skipped": 0
}

Impor kontak massal

POST /contacts/import

Membuat hingga 500 kontak dalam satu panggilan dari array JSON. Setiap catatan memerlukan phone_number dalam format internasional; sisanya bersifat opsional. Catatan dengan nomor telepon yang tidak valid atau saluran yang tidak didukung akan dilewati (tidak dibuat), dan setiap catatan yang dilewati akan dilaporkan beserta indeks dan alasannya — sehingga Anda dapat memperbaiki kegagalan tersebut dan mencoba lagi.

Nomor telepon yang sudah ada di akun Anda akan dilewati sebagai duplicate secara default — namun saat Anda mengirim listId, kontak yang sudah Anda miliki tetap ditambahkan ke daftar tersebut dan dihitung di bawah added_to_list, sehingga impor ulang akan mengisi daftar tanpa mengubah apa pun pada kontak tersebut. Kirim updateExisting: true untuk memperbarui kontak tersebut sebagai gantinya: bidang yang ada dalam catatan akan menimpa (first_name, last_name, email, lead_profile, dan custom_fields digabungkan kunci demi kunci), tags akan ditambahkan, dan kontak akan ditambahkan ke listId. Saluran, nomor telepon, dan flag bot tidak pernah diubah pada kontak yang sudah ada.

Anda dapat menambahkan setiap kontak yang diimpor (atau diperbarui) ke daftar dengan listId secara opsional, menetapkan defaultChannel untuk catatan yang tidak menentukannya, dan menandai catatan dengan tags (nama tag — tag yang tidak ada akan dibuat, tag yang sudah ada dicocokkan tanpa mempedulikan huruf besar/kecil).

Bidang tingkat atas

Bidang Wajib Deskripsi
contacts Ya Larik catatan kontak (maks 500).
listId Tidak Daftar untuk menambahkan setiap kontak dalam permintaan ini — baik yang dibuat, diperbarui, maupun yang dilewati sebagai duplikat. Harus berupa daftar di akun Anda.
defaultChannel Tidak Saluran yang diterapkan ke catatan yang menghilangkan channel. Salah satu dari whatsapp, sms, whatsapp_web. Default ke whatsapp.
updateExisting Tidak true untuk memperbarui kontak yang nomor teleponnya sudah ada alih-alih melewatinya sebagai duplicate. Default ke false.

Bidang per catatan

Bidang Wajib Deskripsi
phone_number Ya Nomor telepon dalam format internasional (+ di depan akan ditambahkan jika tidak ada).
first_name Tidak Nama depan.
last_name Tidak Nama belakang.
email Tidak Alamat email.
channel Tidak Salah satu dari whatsapp, sms, whatsapp_web. Kembali ke defaultChannel.
is_bot_active Tidak Apakah asisten AI membalas. Default ke true.
is_private Tidak Tandai pribadi. Default ke false.
lead_profile Tidak Catatan prospek teks bebas.
custom_fields Tidak Objek kunci dan nilai bidang kustom.
tags Tidak Array nama tag (satu string "a; b" juga berfungsi). Tag yang tidak ada akan dibuat; tag yang sudah ada dicocokkan dengan mengabaikan huruf besar/kecil. Maks 25 per catatan.

cURL

curl -X POST "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/import?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "contacts": [
      { "phone_number": "+12025551234", "first_name": "Ann", "last_name": "Lee", "tags": ["vip", "newsletter"] },
      { "phone_number": "+12025551235", "first_name": "Bob" }
    ],
    "listId": "list123",
    "defaultChannel": "whatsapp_web",
    "updateExisting": true
  }'

JavaScript

const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/import", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    contacts: [
      { phone_number: "+12025551234", first_name: "Ann", last_name: "Lee", tags: ["vip", "newsletter"] },
      { phone_number: "+12025551235", first_name: "Bob" },
    ],
    listId: "list123",
    defaultChannel: "whatsapp_web",
    updateExisting: true,
  }),
});
const data = await res.json();
console.log(`Imported ${data.imported}, updated ${data.updated}, skipped ${data.skipped.length}`);

Python

import requests

res = requests.post(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/import",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "contacts": [
            {"phone_number": "+12025551234", "first_name": "Ann", "last_name": "Lee", "tags": ["vip", "newsletter"]},
            {"phone_number": "+12025551235", "first_name": "Bob"},
        ],
        "listId": "list123",
        "defaultChannel": "whatsapp_web",
        "updateExisting": True,
    },
)
data = res.json()
print(f"Imported {data['imported']}, updated {data['updated']}, skipped {len(data['skipped'])}")

Respons

{
  "success": true,
  "imported": 2,
  "contact_ids": ["contact_abc123", "contact_def456"],
  "updated": 0,
  "updated_contact_ids": [],
  "added_to_list": 0,
  "added_to_list_contact_ids": [],
  "skipped": []
}

Jika beberapa catatan tidak dapat dibuat, catatan tersebut akan muncul di skipped beserta alasannya (di sini tanpa updateExisting, sehingga nomor yang sudah ada dilewati):

{
  "success": true,
  "imported": 1,
  "contact_ids": ["contact_abc123"],
  "updated": 0,
  "updated_contact_ids": [],
  "added_to_list": 1,
  "added_to_list_contact_ids": ["contact_def456"],
  "skipped": [
    { "index": 1, "phone_number": "+12025551235", "reason": "duplicate" }
  ]
}

Baris yang dilewati tetap bergabung dengan listId, yang merupakan apa yang dihitung oleh added_to_list — tidak ada hal lain pada kontak tersebut yang disentuh. Dengan updateExisting: true, permintaan yang sama melaporkan kontak yang ada di bawah updated / updated_contact_ids sebagai gantinya.

Kemungkinan alasan dilewati: invalid_record, missing_phone_number, invalid_phone_number, invalid_channel, duplicate_in_request, duplicate, contact_limit_reached, create_failed.

Batas paket. Jika batas kontak paket Anda tidak memungkinkan penambahan kontak sebanyak ini, seluruh permintaan akan ditolak di awal dengan 403. Jika batas tercapai di tengah proses, catatan yang tersisa akan dikembalikan sebagai dilewati dengan alasan contact_limit_reached.


Impor kontak dari file CSV

Untuk impor yang lebih besar dari yang didukung oleh impor massal (hingga sekitar 50.000 baris), antrekan pekerjaan impor asinkron terhadap file CSV yang sudah ada di penyimpanan akun Anda, lalu lakukan polling hingga selesai.

Memulai impor

POST /contacts/import-csv

Field Wajib Deskripsi
csvStoragePath Ya Jalur penyimpanan file CSV, di bawah users/{your account id}/imports/, diakhiri dengan .csv.
listName Ya Membuat (atau menggunakan kembali) daftar dengan nama ini dan menambahkan setiap kontak yang diimpor ke dalamnya.
existingListRefs Tidak Array ID daftar yang ada untuk juga menambahkan setiap kontak yang diimpor ke dalamnya.
defaultChannel Tidak Saluran yang diterapkan ke baris yang tidak menentukannya.
curl -X POST "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/import-csv?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "csvStoragePath": "users/abc123/imports/leads.csv",
    "listName": "Webinar signups"
  }'

JavaScript

const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/import-csv", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    csvStoragePath: "users/abc123/imports/leads.csv",
    listName: "Webinar signups",
  }),
});
const data = await res.json();
console.log(data.job_id);

Python

import requests

res = requests.post(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/import-csv",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "csvStoragePath": "users/abc123/imports/leads.csv",
        "listName": "Webinar signups",
    },
)
job_id = res.json()["job_id"]

Respons (202 — impor sedang diantrekan, belum selesai)

{
  "success": true,
  "job_id": "csvimp_abc123",
  "status": "queued"
}

Memasukkan file ke penyimpanan. Endpoint ini memulai dan melacak pekerjaan impor; endpoint ini tidak menerima unggahan secara langsung. File CSV harus sudah berada di csvStoragePath sebelum Anda memanggilnya — pengimpor CSV dasbor itu sendiri melakukan ini sebagai langkah pertamanya.

Polling pekerjaan impor

GET /contacts/import-csv/{jobId}

curl "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/import-csv/csvimp_abc123?apiKey=YOUR_API_KEY"

Respons

{
  "success": true,
  "job_id": "csvimp_abc123",
  "status": "completed",
  "imported": 812,
  "updated": 0,
  "skipped": 14,
  "errors": [],
  "error_message": null
}

status bergerak melalui queued → processing → completed, atau failed dengan alasan di error_message. jobId yang tidak ada di akun Anda akan mengembalikan 404.


Ekspor kontak

Memulai ekspor CSV asinkron dari kontak Anda dan mengembalikan pekerjaan yang dapat Anda polling untuk penyelesaiannya.

Memulai ekspor

POST /contacts/export

Bidang Wajib Deskripsi
listId Tidak Hanya ekspor kontak yang termasuk dalam daftar ini.
contactIds Tidak Hanya ekspor ID kontak spesifik ini.

Jika keduanya dikosongkan, semua kontak di akun Anda akan diekspor.

curl -X POST "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/export?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "listId": "list123" }'

JavaScript

const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/export", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ listId: "list123" }),
});
const data = await res.json();
console.log(data.job_id);

Python

import requests

res = requests.post(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/export",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"listId": "list123"},
)
job_id = res.json()["job_id"]

Respons (202 — ekspor sedang dalam antrean)

{
  "success": true,
  "job_id": "export_abc123",
  "status": "queued"
}

Memeriksa status pekerjaan ekspor

GET /contacts/export/{jobId}

curl "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/export/export_abc123?apiKey=YOUR_API_KEY"

Respons

{
  "success": true,
  "job_id": "export_abc123",
  "status": "completed",
  "export_id": "exp_xyz789",
  "contact_count": 812,
  "error_message": null
}

Setelah status berstatus "completed", Anda akan mendapatkan export_id dan contact_count. Pengunduhan file CSV yang dihasilkan dilakukan melalui halaman Ekspor di dasbor Anda.


Kirim pesan ke kontak

POST /contacts/{contactId}/send-message

Mengirim pesan ke kontak yang sudah ada di saluran mana pun yang sedang mereka gunakan. Pesan akan diantrekan dan dikirim di latar belakang — respons mengonfirmasi bahwa pesan telah diterima, bukan bahwa pesan tersebut sudah terkirim.

Bidang Wajib Deskripsi
body Ya Teks pesan yang akan dikirim.
mediaUrl Tidak URL file media untuk dilampirkan.
mediaContentType Tidak Tipe MIME dari media yang dilampirkan (contoh: image/jpeg).

cURL

curl -X POST "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/send-message?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "body": "Hi! Your appointment is confirmed." }'

JavaScript

const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/send-message", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ body: "Hi! Your appointment is confirmed." }),
});
const data = await res.json();
console.log(data.messageId);

Python

import requests

res = requests.post(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/send-message",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"body": "Hi! Your appointment is confirmed."},
)
print(res.json()["messageId"])

Respons

{
  "success": true,
  "messageId": "aB3dE5fG7hI9jK1lM2nO",
  "contactId": "contact_abc123",
  "channel": "whatsapp",
  "message": "Message created successfully. Delivery is being processed."
}

Tidak dapat mengirim sekarang? Jika kontak mengaktifkan mode jangan ganggu atau mode pribadi, atau tidak berada di saluran yang dapat menerima pesan keluar, permintaan akan ditolak dengan 422 dan error yang menjelaskan alasannya.

Untuk mengirim melalui nomor telepon, ID Instagram, atau identitas saluran lainnya alih-alih ID kontak — dan untuk informasi lebih lanjut tentang pengiriman pesan secara umum — lihat Messages API.


Kirim tindak lanjut AI ke kontak

POST /contacts/{contactId}/ai-follow-up

Meminta agen AI menulis satu pesan dengan suaranya sendiri, berdasarkan percakapan yang telah berlangsung dan instruksi yang Anda berikan, lalu mengirimkannya melalui saluran kontak tersebut. Ini sama dengan langkah otomatisasi Kirim tindak lanjut AI, dan biayanya sama dengan tindak lanjut AI.

Bidang Wajib Deskripsi
instruction Ya Apa yang harus dilakukan pesan tersebut, dalam kata-kata sederhana, hingga 2.000 karakter. Contoh: “Ingatkan mereka bahwa tautan reservasi mereka akan kedaluwarsa malam ini dan tanyakan apakah mereka ingin menguncinya”.
agentId Tidak Agen yang menulis pesan. Kosongkan untuk menggunakan agen yang sudah menangani kontak tersebut.
mustContain Tidak Daftar hingga 5 frasa atau tautan (masing-masing hingga 500 karakter) yang harus disertakan dalam pesan kata demi kata. Jika AI melewatkan salah satunya, tidak ada pesan yang dikirim dan skipReason adalah text_check_failed.
respectMessagingWindow Tidak Default true. Pada WhatsApp Business API, Instagram, dan Messenger, lewati jika pesan terakhir kontak sudah lebih dari 24 jam.
skipWhenAiPaused Tidak Default true. Lewati jika AI dimatikan untuk kontak ini.

cURL

curl -X POST "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/ai-follow-up" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "instruction": "Remind them their reserved link expires tonight and ask if they want to lock it in",
    "mustContain": ["https://example.com/r/abc123"]
  }'

JavaScript

const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/ai-follow-up", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    instruction: "Remind them their reserved link expires tonight and ask if they want to lock it in",
    mustContain: ["https://example.com/r/abc123"],
  }),
});
const data = await res.json();
if (!data.sent) console.log("Skipped:", data.skipReason);

Respons saat pesan berhasil dikirim:

{
  "sent": true,
  "messageId": "ai-follow-up-aB3dE5fG7hI9jK1l",
  "text": "Hi Ada, quick reminder: your reserved spot is held until 20:00 tonight. Want to lock it in? https://example.com/r/abc123",
  "agentId": "agent_abc123"
}

Respons saat pesan dilewati:

{
  "sent": false,
  "skipReason": "window_closed"
}

Keduanya kembali dengan status 200. skipReason adalah salah satu dari no_agent (tidak ada agen yang menangani kontak dan tidak ada yang diberikan), dnd (jangan ganggu), ai_paused, window_closed (di luar jendela 24 jam, atau kontak tidak pernah menulis kepada Anda di saluran tersebut), no_credits, text_check_failed (item mustContain tidak ditemukan), no_text (AI tidak menulis apa pun yang dapat digunakan) atau linkedin_gap (prospek LinkedIn mendapatkan pesan otomatis kurang dari 24 jam yang lalu; jawaban tersebut kemudian juga membawa nextAllowedAt, waktu kapan pesan berikutnya dapat dikirim). Lewati (skip) adalah jawaban normal, bukan kesalahan, jadi periksa sent sebelum berasumsi bahwa pesan telah terkirim. Panggilan yang dilewati tidak menggunakan kredit.

Isi yang kehilangan instruction atau memiliki bidang dengan tipe yang salah akan mendapatkan 400. Kontak atau agen yang tidak ada di akun Anda akan mendapatkan 404. Kesalahan dikembalikan sebagai { "success": false, "error": "..." }. Kunci anggota tim memerlukan akses edit ke kontak.


Menetapkan agen AI ke kontak

POST /contacts/{contactId}/assign-agent

Memindahkan percakapan yang ada ke agen AI yang berbeda, mulai dari pesan berikutnya dan seterusnya. Ini sama dengan Tetapkan Agen AI di menu obrolan, dan langkah yang sama yang digunakan oleh tindakan Tetapkan agen AI dalam Otomatisasi.

Bidang Wajib Deskripsi
agentId Ya ID agen AI yang harus mengambil alih, atau null untuk menghapus penugasan agar percakapan kembali ke kotak masuk tim Anda.
triggerAIResponse Tidak true membuat agen yang baru ditugaskan langsung membalas pesan kontak terbaru yang belum terjawab. Default-nya adalah false. Jika kontak sudah berada di agen ini dan pesan terakhirnya sudah terjawab, tidak ada balasan yang dimulai: respons membawa aiResponseTriggered: false dan aiTriggerError yang menjelaskan alasannya.

Berhati-hatilah dengan triggerAIResponse: true — ini mengirim pesan ke kontak saat itu juga, jadi gunakan hanya jika Anda ingin mereka dikirimi pesan sekarang. Di Messenger dan Instagram, pesan tersebut gagal jika kontak terakhir menulis kepada Anda lebih dari 24 jam yang lalu.

cURL

curl -X POST "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/assign-agent?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "agentId": "agent_xyz789" }'

JavaScript

const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/assign-agent", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ agentId: "agent_xyz789" }),
});
const data = await res.json();
console.log(data.data.agentId);

Python

import requests

res = requests.post(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/assign-agent",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"agentId": "agent_xyz789"},
)
print(res.json()["data"]["agentId"])

Respons

{
  "success": true,
  "data": {
    "contactId": "contact_abc123",
    "agentId": "agent_xyz789",
    "aiResponseTriggered": false
  }
}

Agen harus berasal dari akun yang sama dengan kontak; jika tidak, permintaan akan ditolak dengan 404 atau 403. Temukan ID agen di halaman Agen AI (URL setiap agen diakhiri dengan ID-nya).


Menetapkan agen AI ke banyak kontak

POST /contacts/bulk-assign-agent

Memindahkan banyak percakapan ke agen AI yang berbeda dalam satu panggilan — atau menghapus penetapan untuk semuanya dengan null. Ini murni perubahan perutean: tidak ada pesan yang dikirim dan agen tidak membalas siapa pun. Setiap kontak cukup mendapatkan agen baru saat mereka menulis pesan berikutnya. (Itulah sebabnya tidak ada triggerAIResponse di sini.)

Bidang Wajib Deskripsi
agentId Ya Agen AI yang harus mengambil alih, atau null untuk menghapus penetapan.
contactIds Salah satu dari tiga Hingga 500 ID kontak untuk dipindahkan.
filter Salah satu dari tiga Pilih kontak di server alih-alih mencantumkannya, yang terbaru terlebih dahulu. Menggunakan kunci yang sama dengan filter endpoint hitung: agentId (atau none), channel, tag, listId, botActive, status.
rules Salah satu dari tiga Objek aturan daftar cerdas — lihat Bentuk smart_rules.
limit Tidak Berapa banyak kontak yang akan dipindahkan dalam panggilan ini saat Anda memilih dengan filter atau rules. 1 hingga 500, defaultnya 500.

Kirim tepat satu dari contactIds, filter, atau rules.

cURL

curl -X POST "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/bulk-assign-agent?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agentId": "agent_xyz789",
    "filter": { "agentId": "agent_abc123", "channel": "messenger" }
  }'

JavaScript

const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/bulk-assign-agent", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    agentId: "agent_xyz789",
    filter: { agentId: "agent_abc123", channel: "messenger" },
  }),
});
const data = await res.json();
console.log(data.updated, data.remaining);

Python

import requests

res = requests.post(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/bulk-assign-agent",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "agentId": "agent_xyz789",
        "filter": {"agentId": "agent_abc123", "channel": "messenger"},
    },
)
data = res.json()
print(data["updated"], data["remaining"])

Respons

{
  "success": true,
  "agentId": "agent_xyz789",
  "matched": 3415,
  "updated": 500,
  "skipped": 0,
  "remaining": 2915,
  "filters": { "agentId": "agent_abc123" }
}

matched adalah berapa banyak kontak yang ditemukan oleh pilihan tersebut secara total, updated berapa banyak yang dipindahkan oleh panggilan ini, skipped berapa banyak ID yang Anda kirim tidak ditemukan di akun Anda, dan remaining berapa banyak yang masih cocok sekarang setelah panggilan ini selesai.

Memindahkan semua orang. Karena satu panggilan memindahkan paling banyak 500 kontak, grup besar memerlukan beberapa panggilan. Gunakan filter yang berhenti mencocokkan kontak setelah dipindahkan — misalnya filter: { "agentId": "agent_abc123" } saat menetapkan ke agent_xyz789 — dan ulangi panggilan yang sama persis hingga remaining kembali sebagai 0. Saat Anda memberikan contactIds sebagai gantinya, remaining selalu 0.


Menetapkan kontak ke departemen

POST /contacts/{contactId}/department

“Tetapkan prospek ini ke Penjualan” — mengarsipkan kontak di bawah departemen tertentu dan, secara default, menyerahkannya kepada siapa pun di departemen tersebut yang saat ini memiliki kontak paling sedikit. Ini terpisah dari menetapkan agen AI: departemen menjawab “tim mana yang memiliki ini,” agen menjawab “AI mana yang menjawab ini,” dan menetapkan salah satunya tidak akan pernah menghapus yang lain.

Bidang Wajib Deskripsi
department_id Ya Departemen tempat kontak akan diarsipkan. Berikan null untuk menghapusnya.
hand_to_member Tidak Juga serahkan kontak kepada orang dengan beban kerja paling sedikit di departemen tersebut. Default-nya adalah true. Tidak akan pernah menetapkan ulang kontak yang sudah dimiliki seseorang.

cURL

curl -X POST "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/department?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "department_id": "dept_sales" }'

JavaScript

const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/department", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ department_id: "dept_sales" }),
});
const data = await res.json();
console.log(data.assigned_to);

Python

import requests

res = requests.post(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/department",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"department_id": "dept_sales"},
)
print(res.json()["assigned_to"])

Respons

{
  "success": true,
  "department_id": "dept_sales",
  "assigned_to": "member_uid_123"
}

assigned_to bernilai null jika kontak tersebut sudah dimiliki oleh seseorang, atau Anda memberikan hand_to_member: false.


Menautkan kontak lintas saluran

“Lanjutkan di WhatsApp” (atau SMS) akan mencari atau membuat kontak orang ini di saluran berbasis telepon lain dan menautkan keduanya, sehingga aplikasi mengenali mereka sebagai orang yang sama.

Tautkan ke saluran lain

POST /contacts/{contactId}/link-channel

Bidang Wajib Deskripsi
channel Ya Saluran untuk ditautkan. Salah satu dari whatsapp, whatsapp_web, sms.
phoneNumber Tidak Nomor telepon yang digunakan pada saluran baru. Default-nya adalah nomor kontak sumber itu sendiri.
curl -X POST "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/link-channel?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "channel": "sms" }'

Respons

{
  "success": true,
  "data": {
    "contact_id": "contact_def456",
    "person_id": "person_xyz789",
    "created": true
  }
}

created memberi tahu Anda apakah kontak baru dibuat untuk saluran target atau kontak yang sudah ada ditemukan dan ditautkan. Memanggil ini untuk kedua kalinya aman — fungsi ini mengembalikan contact_id yang sama dengan created: false alih-alih membuat duplikat.

422 berarti akun tidak dapat melakukan penautan ini saat ini: kontak sudah berada di keluarga saluran tersebut, tidak memiliki nomor telepon untuk digunakan, atau tidak ada pengirim yang terhubung untuk saluran target. 409 berarti kedua kontak sudah ditautkan ke dua orang yang berbeda — batalkan tautan salah satunya terlebih dahulu.

Mencantumkan percakapan yang ditautkan dari kontak

GET /contacts/{contactId}/linked

Mengembalikan percakapan lain yang merupakan orang yang sama dengan kontak ini. Kontak yang tidak ditautkan akan mengembalikan array kosong, bukan 404 — “orang ini tidak memiliki saluran lain” adalah status yang normal.

curl "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/linked?apiKey=YOUR_API_KEY"

Respons

{
  "success": true,
  "data": [
    {
      "contact_id": "contact_def456",
      "channel": "sms",
      "custom_channel": null,
      "first_name": "Jane",
      "last_name": "Smith",
      "phone_number": "+15551234567",
      "last_message": "Sounds good, thanks!",
      "last_message_timestamp": "2026-06-09T10:21:00.000Z",
      "linked_from": {
        "contact_id": "contact_abc123",
        "channel": "whatsapp",
        "linked_at": "2026-06-01T09:00:00.000Z",
        "reason": "continue_on_channel"
      }
    }
  ]
}

Batalkan tautan kontak

DELETE /contacts/{contactId}/link

Menghapus kontak ini dari orangnya, secara sepihak — kontak lain yang masih ditautkan ke orang tersebut tetap mempertahankan tautannya, jadi membatalkan tautan satu dari tiga kontak tidak akan membubarkan grup tersebut.

curl -X DELETE "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/link?apiKey=YOUR_API_KEY"

Respons

{ "success": true }

Mengambil foto profil kontak

POST /contacts/{contactId}/profile-pic

Mengambil (dan menyimpan dalam cache) foto profil WhatsApp atau Meta kontak sesuai permintaan — foto yang sama dikembalikan sebagai avatarUrl pada Dapatkan kontak, yang diperbarui.

curl -X POST "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/profile-pic?apiKey=YOUR_API_KEY"

Respons

{
  "success": true,
  "avatar_url": "https://example.com/photo.jpg",
  "cached": false
}

cached: true berarti URL berasal dari pengambilan terbaru, bukan pencarian penyedia yang baru — foto disimpan dalam cache selama 7 hari, dan kontak yang menurut penyedia tidak memiliki foto yang dapat dijangkau akan disimpan dalam cache sebagai tidak tersedia selama 24 jam. Jika tidak ada foto untuk diambil, avatar_url dihilangkan dan message menjelaskan alasannya.


Menandai kontak secara otomatis dengan AI

Menjalankan aturan tag akun Anda pada riwayat percakapan lengkap satu atau beberapa kontak dan menerapkan (atau menghapus) tag persis seperti penandaan waktu nyata yang berjalan selama obrolan langsung — aturan yang sama, biaya kredit per tag yang sama.

Memulai proses

POST /contacts/auto-tag

Bidang Wajib Deskripsi
scope Ya "contacts" untuk menandai kontak tertentu, atau "agent" untuk menandai setiap percakapan yang saat ini ditangani oleh satu agen AI.
contact_ids Wajib jika scope adalah "contacts" Larik ID kontak, 1 hingga 500.
agent_id Wajib jika scope adalah "agent" Agen AI yang percakapannya akan ditandai. Jika scope adalah "contacts", bidang ini bersifat opsional dan hanya mempersempit aturan tag agen mana yang dijalankan.
curl -X POST "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/auto-tag?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "scope": "contacts", "contact_ids": ["contact_abc123", "contact_def456"] }'

Satu kontak dijalankan secara inline dan langsung mengembalikan hasilnya:

{ "success": true, "result": { "tags_applied": 2, "tags_removed": 0 } }

Dua atau lebih kontak (atau scope: "agent") dijalankan sebagai tugas latar belakang dan langsung mengembalikan 202:

{ "success": true, "run_id": "m1x2y3-a1b2c3d4", "total": 214 }

Melakukan polling proses

GET /contacts/auto-tag/run

Mengembalikan proses akun saat ini (atau yang terbaru), sehingga Anda dapat melakukan polling kemajuan tanpa harus melacak run_id sendiri.

curl "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/auto-tag/run?apiKey=YOUR_API_KEY"

Respons

{
  "success": true,
  "run": {
    "run_id": "m1x2y3-a1b2c3d4",
    "status": "running",
    "total": 214,
    "processed": 58,
    "tagged_contacts": 12,
    "tags_applied": 15,
    "tags_removed": 2,
    "credits_charged": 15
  }
}

run adalah null jika akun belum pernah memulai satu proses pun. status berpindah dari "running" ke "completed" atau "failed".

Hanya satu proses massal yang dapat berjalan per akun dalam satu waktu — memulai proses kedua saat proses lain sedang berjalan akan mengembalikan 409 dengan error_code: "auto_tag_run_in_progress". Kehabisan kredit pada proses satu kontak akan mengembalikan 402 dengan error_code: "insufficient_credits"; proses massal justru akan berhenti lebih awal dan melaporkan sejauh mana proses tersebut berjalan di run.


Menghapus kontak

DELETE /contacts/{contactId}

Menghapus satu kontak secara permanen berdasarkan ID, beserta riwayat pesannya. Tindakan ini tidak dapat dibatalkan. Untuk menghapus beberapa kontak dalam satu panggilan, gunakan Hapus kontak di bawah ini.

cURL

curl -X DELETE "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123?apiKey=YOUR_API_KEY"

JavaScript

const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123", {
  method: "DELETE",
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
console.log(data.success);

Python

import requests

res = requests.delete(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
print(res.json()["success"])

Respons

{
  "success": true
}

ID kontak yang tidak ada di akun Anda, atau milik akun yang berbeda, akan mengembalikan 404.


Menghapus kontak

DELETE /contacts

Menghapus satu atau beberapa kontak secara permanen berdasarkan ID dalam satu panggilan (hingga 500 ID). ID yang tidak ada di akun Anda akan dilewati dan dihitung dalam skipped. Tindakan ini tidak dapat dibatalkan.

Bidang Deskripsi
contactIds Larik ID kontak yang akan dihapus (maks 500).

cURL

curl -X DELETE "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "contactIds": ["contactId1", "contactId2"] }'

JavaScript

const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts", {
  method: "DELETE",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ contactIds: ["contactId1", "contactId2"] }),
});
const data = await res.json();
console.log(`Deleted ${data.deleted}, skipped ${data.skipped}`);

Python

import requests

res = requests.delete(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"contactIds": ["contactId1", "contactId2"]},
)
data = res.json()
print(f"Deleted {data['deleted']}, skipped {data['skipped']}")

Respons

{
  "success": true,
  "deleted": 2,
  "skipped": 0
}

Daftar kolom kustom

GET /users/me/custom-fields — mengembalikan kunci kolom kustom yang terdaftar di akun Anda (yang ditampilkan sebagai kolom dan di formulir kontak), sehingga integrasi dapat menawarkannya sebagai pemilih alih-alih menebaknya.

curl "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/users/me/custom-fields?apiKey=YOUR_API_KEY"

Respons (200)

{ "success": true, "custom_fields": ["tier", "company", "birthday"] }

Tetapkan daftar dengan PUT /users/me/custom-fields dan bentuk array yang sama.


Menghapus bidang kustom

DELETE /contacts/custom-fields/{fieldKey}

Menghapus satu kunci bidang kustom dari setiap kontak di akun Anda. Gunakan ini untuk membersihkan data setelah mengganti nama atau menonaktifkan bidang kustom. Kunci hanya boleh berisi huruf, angka, garis bawah, dan tanda hubung. Mengembalikan jumlah kontak yang diperbarui. Tindakan ini tidak dapat dibatalkan.

cURL

curl -X DELETE "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/custom-fields/webinar_date_nh?apiKey=YOUR_API_KEY"

JavaScript

const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/custom-fields/webinar_date_nh", {
  method: "DELETE",
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
console.log(`Removed from ${data.updated} contacts`);

Python

import requests

res = requests.delete(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/custom-fields/webinar_date_nh",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
print(f"Removed from {res.json()['updated']} contacts")

Respons

{
  "success": true,
  "updated": 42
}

Catatan: Kunci kolom dengan karakter yang tidak didukung akan mengembalikan 400.


Tipe bidang kustom

Setiap bidang kustom pada akun memiliki tipe: text (default), number, date, select (dropdown dengan opsi tetap), atau boolean (kotak centang). Bidang bertipe divalidasi pada setiap penulisan — buat, perbarui, impor, mesin otomatisasi, dan pengumpulan bidang AI itu sendiri — dan nilainya disimpan dalam satu bentuk kanonik, sehingga filter dan kondisi otomatisasi membandingkan hal yang sama dengan yang sama:

Tipe Disimpan sebagai Diterima pada input
text Apa pun yang Anda kirim Apa pun (perilaku tidak berubah)
number Angka JSON 42, "42", "19,99"
date "YYYY-MM-DD" 2026-02-01, tanggal-waktu ISO (bagian tanggal disimpan), 01/02/2026 (hari-pertama atau bulan-pertama sesuai format tanggal akun; nilai yang tidak ambigu seperti 13/02/2026 selalu menang), February 1, 2026, 1 de febrero de 2026
select Salah satu opsi bidang, dalam ejaan opsi itu sendiri Kecocokan apa pun yang tidak peka huruf besar-kecil dari sebuah opsi
boolean true / false true/false, yes/no, 1/0, si/no, ja/nein …

Mengirim null atau string kosong akan menghapus bidang bertipe. Kunci yang tidak terdaftar di akun, dan bidang text, disimpan persis seperti yang dikirim.

Baca definisi bidang

GET /users/me/custom-fields

{
  "success": true,
  "custom_fields": ["company", "birthday", "plan", "vip"],
  "definitions": [
    { "key": "company", "type": "text" },
    { "key": "birthday", "type": "date" },
    { "key": "plan", "type": "select", "options": ["Free", "Pro", "Enterprise"] },
    { "key": "vip", "type": "boolean" }
  ]
}

custom_fields adalah daftar kunci biasa (tidak berubah untuk klien lama); definitions membawa tipe per kunci.

Tetapkan definisi bidang

PUT /users/me/custom-fields

Menggantikan seluruh daftar. Setiap entri adalah kunci kosong (mempertahankan tipe yang sudah dimiliki bidang, text untuk yang baru) atau objek dengan key, type dan, untuk select, options (1 hingga 100 opsi unik, masing-masing hingga 64 karakter). Hingga 50 bidang; kunci menggunakan huruf kecil, angka, dan garis bawah serta dimulai dengan huruf atau garis bawah.

curl -X PUT "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/users/me/custom-fields?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "customFields": [
      "company",
      { "key": "birthday", "type": "date" },
      { "key": "plan", "type": "select", "options": ["Free", "Pro", "Enterprise"] },
      { "key": "vip", "type": "boolean" }
    ]
  }'

Mengubah tipe bidang tidak menulis ulang nilai yang sudah disimpan pada kontak; nilai tersebut divalidasi saat berikutnya ditulis.

Kesalahan validasi

Pembuatan atau pembaruan kontak yang nilai bidang kustomnya tidak sesuai dengan tipenya akan ditolak secara keseluruhan dengan 400:

{
  "success": false,
  "error": "Invalid custom field value(s): birthday: \"birthday\" must be a date in YYYY-MM-DD format (for example 1990-02-01).",
  "field_errors": [
    { "key": "birthday", "message": "\"birthday\" must be a date in YYYY-MM-DD format (for example 1990-02-01)." }
  ]
}

Pada impor massal, data dengan nilai yang salah akan dilaporkan gagal dengan pesan yang sama dan sisa batch lainnya akan tetap diproses.


Daftar

Daftar mengelompokkan kontak. Daftar bisa berupa statis (Anda yang menentukan siapa yang ada di dalamnya) atau cerdas (keanggotaan dihitung berdasarkan aturan dan diperbarui secara otomatis — lihat Mengatur Daftar & Kontak).

Bidang Deskripsi
name Wajib diisi saat pembuatan. Maksimal 100 karakter.
status live (default) atau draft. Huruf kecil.
contact_ids Larik ID kontak untuk dimasukkan ke dalam daftar. Hanya untuk daftar statis.
type static (default) atau smart.
smart_rules Kumpulan aturan — wajib diisi saat type adalah smart. Lihat di bawah.

Membuat daftar

POST /lists

curl -X POST "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/lists?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
        "name": "Hot leads (active)",
        "type": "smart",
        "smart_rules": {
          "match": "all",
          "conditions": [
            { "field": "tags", "op": "has_any", "value": ["tagHotLead"] },
            { "field": "last_activity_at", "op": "within_last", "value": { "amount": 90, "unit": "days" } }
          ]
        }
      }'

Respons

{
  "success": true,
  "list_id": "list_abc123",
  "evaluation": { "added": 3, "removed": 0, "total": 3 }
}

Daftar cerdas dievaluasi secara inline, dalam permintaan yang sama, sehingga evaluation memberi tahu Anda dengan tepat siapa saja yang masuk ke dalamnya. Pada daftar statis, evaluation adalah null.

Memperbarui daftar

PUT /lists/{listId}

Kirim hanya bidang yang ingin Anda ubah. Mengubah smart_rules akan mengevaluasi ulang daftar secara langsung dan mengembalikan objek evaluation yang sama.

curl -X PUT "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/lists/list_abc123?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "smart_rules": { "match": "any", "conditions": [ { "field": "tags", "op": "has_any", "value": ["tagHotLead", "tagWebinar"] } ] } }'

Anda dapat mengubah jenis daftar di antara keduanya:

  • Statis → cerdas: kirim { "type": "smart", "smart_rules": { … } }. Aturan akan langsung diterapkan.
  • Cerdas → statis: kirim { "type": "static" }. Aturan akan dihapus dan siapa pun yang ada di dalam daftar akan tetap berada di sana.

Bentuk smart_rules

{
  "match": "all",
  "conditions": [
    { "field": "tags", "op": "has_any", "value": ["tagHotLead"] },
    { "field": "channel", "op": "is_any", "value": ["whatsapp", "sms"] },
    { "field": "last_incoming_message_at", "op": "not_within_last", "value": { "amount": 7, "unit": "days" } },
    { "field": "created_at", "op": "after", "value": "2026-01-01" },
    { "field": "is_bot_active", "op": "is", "value": true },
    { "field": "email", "op": "is_set" },
    { "field": "custom_field", "key": "Plan", "op": "eq", "value": "pro" }
  ]
}
  • match — all (setiap kondisi harus benar) atau any (setidaknya satu).
  • conditions — 1 hingga 20 kondisi, masing-masing maksimal 100 nilai, string hingga 200 karakter.
field op value
tags has_any, has_all, has_none larik ID tag
lists in_any, not_in_any larik ID daftar (hanya daftar statis — daftar cerdas tidak dapat dibuat dari daftar cerdas lainnya)
channel is_any, is_none larik saluran
status is_any, is_none larik status kontak
created_at, last_activity_at, last_incoming_message_at, last_outgoing_message_at, first_ai_interaction_at, last_ai_interaction_at within_last, not_within_last { "amount": 1–3650, "unit": "hours" | "days" }
kolom tanggal yang sama before, after tanggal ISO ("2026-01-01", dibandingkan sebagai hari penuh) atau tanggal-waktu ISO lengkap ("2026-01-01T14:30:00Z", dibandingkan hingga momen yang tepat)
kolom tanggal yang sama is_set, not_set —
has_interacted_with_ai is true / false — true mencocokkan kontak yang pernah dikirimi pesan oleh AI setidaknya sekali (kapan pun)
is_bot_active, do_not_disturb, is_private, has_ever_responded is true / false
email, phone_number, first_name, last_name is_set, not_set, contains, not_contains string untuk formulir contains
current_campaign_id, assigned_agent is_any, is_none, is_set, not_set larik ID untuk formulir is_any / is_none
custom_field (ditambah key) eq, neq, contains, not_contains, is_set, not_set string untuk formulir nilai

not_within_last juga mencocokkan kontak yang tanggalnya tidak pernah ditetapkan (“lebih dari N yang lalu, atau tidak pernah”), dan perbandingan teks mengabaikan huruf besar/kecil.

Keterlibatan AI. has_interacted_with_ai adalah penanda seumur hidup: true untuk setiap kontak yang telah dikirimi setidaknya satu pesan oleh AI Anda, false untuk yang lainnya (termasuk kontak yang hanya pernah dijawab oleh tim Anda). Penanda ini dibubuhkan pada pesan pertama AI ke kontak dan tidak pernah dihapus, jadi mematikan balasan AI untuk kontak tersebut atau memindahkan mereka ke kampanye lain tidak akan meresetnya. Untuk periode — “kontak yang ditangani AI saya bulan ini”, pertanyaan penagihan yang umum — gunakan rentang last_ai_interaction_at sebagai gantinya:

{ "field": "last_ai_interaction_at", "op": "within_last", "value": { "amount": 30, "unit": "days" } }

Jangan tertukar dengan is_bot_active (AI diizinkan untuk membalas, bukan berarti sudah membalas) atau has_ever_responded (kontak membalas, kepada siapa pun). Kedua penanda yang sama dikembalikan pada setiap kontak sebagai first_ai_interaction_at / last_ai_interaction_at, dan seluruh rangkaian aturan juga berfungsi pada GET /contacts?rules=, sehingga Anda dapat menghitung kecocokan tanpa membuat daftar.

Pratinjau kumpulan aturan

POST /lists/preview

Menghitung dan mengambil sampel kontak yang akan dicocokkan oleh kumpulan aturan, tanpa membuat atau mengubah apa pun. Gunakan ini untuk memeriksa kewajaran aturan sebelum Anda menyimpannya.

curl -X POST "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/lists/preview?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "smart_rules": { "match": "all", "conditions": [ { "field": "tags", "op": "has_any", "value": ["tagHotLead"] } ] } }'

Respons

{
  "success": true,
  "count": 3,
  "sample": [
    {
      "id": "contact_abc123",
      "first_name": "Sofia",
      "last_name": "Martinez",
      "phone_number": "+31600000000",
      "email": "sofia@example.com",
      "channel": "whatsapp"
    }
  ]
}

sample menampung hingga 10 kontak, dengan yang paling baru aktif di urutan pertama.

Jalankan ulang daftar cerdas sekarang

POST /lists/{listId}/evaluate

Memaksa evaluasi ulang segera (sama dengan fungsi Segarkan sekarang di dasbor). Daftar cerdas sudah diperbarui saat kontak berubah, dan setiap 15 menit untuk aturan berbasis waktu, jadi ini hanya diperlukan saat Anda menginginkan hasilnya saat ini juga.

Respons

{
  "success": true,
  "list_id": "list_abc123",
  "evaluation": { "added": 2, "removed": 1, "total": 4 }
}

evaluation.skipped: true berarti evaluasi lain dari daftar yang sama sudah berjalan dan panggilan ini tidak melakukan apa pun.

Daftar cerdas menolak anggota yang dipilih secara manual

Endpoint keanggotaan mengembalikan 409 dengan "This is a smart list — its members are computed from its rules. Edit the rules instead." saat daftar target adalah daftar cerdas. Ini mencakup POST /contacts/lists, DELETE /contacts/lists, POST /contacts/lists/batch, contact_ids pada POST /lists dan PUT /lists/{listId}, serta memilih daftar cerdas sebagai target impor CSV. Ubah aturannya sebagai gantinya.

Memanggil POST /lists/{listId}/evaluate pada daftar statis juga merupakan 409 — daftar tersebut tidak memiliki aturan untuk dijalankan.


Kesalahan API Kontak

Endpoint kontak mengembalikan amplop error standar:

{
  "success": false,
  "error": "Contact not found"
}

Beberapa endpoint juga menyertakan error_code, yang biasanya cocok dengan status HTTP — satu-satunya pengecualian adalah kasus kontak duplikat di bawah, di mana status HTTP adalah 200 dan hanya error_code yang membawa 409. Kode yang spesifik untuk endpoint kontak:

Kode Kapan ini terjadi pada endpoint kontak
400 Permintaan buruk — kolom yang hilang/tidak valid, isi kosong, kursor buruk, atau lebih dari 500 ID dalam satu batch.
402 Kredit tidak cukup untuk menyelesaikan proses penandaan AI pada satu kontak (error_code: "insufficient_credits").
404 Kontak, daftar, atau tag tidak ditemukan di akun Anda.
409 Kontak dengan nomor telepon tersebut sudah ada (saat pembuatan). Dikembalikan sebagai error_code di dalam isi dengan status HTTP 200, jadi buat percabangan pada error_code di sini. Juga dikembalikan saat proses penandaan otomatis massal sedang berlangsung (error_code: "auto_tag_run_in_progress"), atau saat menautkan kontak ke saluran lain yang akan menggabungkan dua kontak yang sudah ditautkan ke dua orang berbeda.
422 Kontak tidak dapat menerima pesan saat ini (jangan ganggu, pribadi, atau saluran yang tidak didukung). Pada endpoint penautan saluran, ini juga mencakup tidak ada nomor telepon, pemasangan saluran yang tidak didukung, atau tidak ada pengirim yang terhubung untuk saluran target.

403 pada endpoint kontak juga dapat berarti masalah batas kontak atau izin daftar, bukan akses paket. Kode bersama yang dapat dikembalikan oleh setiap endpoint — 401, 403 (paket Anda tidak menyertakan akses API), 429 (batas kecepatan), dan 500 — tercantum beserta panduan percobaan ulang di Kesalahan & Penomoran Halaman.


Langkah berikutnya

  • API Pesan — mengirim pesan berdasarkan identitas saluran dan mengelola percakapan.
  • Referensi API — daftar endpoint lengkap, termasuk tag dan daftar.
  • Akses API — autentikasi, batas kecepatan, dan penanganan error.