Halaman ini untuk kamu yang memegang kode website atau sistem CS sendiri. Ada dua jalur: widget yang kamu tempel di halaman toko, dan API server-to-server kalau sistemmu sudah punya tampilan chat sendiri. Keduanya memakai otak Nata yang sama dengan chat di app.nyataka.com.
API dibeli sebagai paketnya sendiri, terpisah dari langganan web/Telegram (Max). Beli Max tidak termasuk API-nya: langganan Max bukan syarat akses dan bukan pembeliannya. Sebaliknya, widget di situs tokomu tetap fitur paket Max — API yang tidak ikut paket mana pun.
Rp 199per pesan masuk, prabayar. Tanpa biaya bulanan, tanpa minimum bulanan.
1 pesan masuk = 1 balasan = Rp 199.
Volume mulai 50.000 pesan/bulan: Rp 175 per pesan; mulai 100.000: Rp 149 per pesan, perjanjian terpisah.
Saldo habis: API menjawab 402 quota_exhausted, pesannya tidak diproses sampai kredit ditambah.
Top up minimum Rp 250.000. Belum ada checkout sendiri di app: tim Nyataka mengaktifkan paket dan menambah kredit secara manual.
Harga ini keputusan pemilik 2026-10-03 (docs product-strategy-tiers-api §4). Penagihan masih manual: belum ada top up sendiri di app dan belum ada invoice otomatis. Rincian batas ada di bagian 7.
1. Dua jalur, pilih satu
Widget di situsmu
Satu baris <script> menampilkan Nata sebagai panel di sisi kanan situs. Pembeli bertanya dan dijawab dari katalog serta kebijakan tokomu. Kamu tidak menulis backend apa pun.
Kunci yang dipakai kunci publik toko (nata_pub_…) — aman ada di HTML karena hanya bisa menjawab dari katalog tokomu, dan hanya dari domain yang kamu izinkan.
API server-to-server
Sistem atau CS-mu sudah punya kotak chat sendiri? Kirim pesannya ke POST /webhook/nata dan tampilkan balasan Nata di UI-mu. Cocok untuk helpdesk, WhatsApp gateway, atau ERP internal.
Kunci rahasia (nata_whk_…) hanya boleh ada di server. Jangan pernah menaruhnya di kode browser.
Boleh dua-duanya: widget untuk pembeli di halaman toko, API untuk tim CS di dashboard internal.
2. Kunci API
Buka api.nyataka.com → Kunci lalu tekan Buat kunci. Kunci hanya ditampilkan sekali; di server kami yang tersimpan cuma hash-nya, jadi simpan di tempat aman waktu itu juga.
Formatnya:
nata_whk_<key_id>.<rahasia>
key_id adalah penanda publik (boleh kamu tulis di tiket dukungan); bagian rahasianya yang tidak boleh keluar dari server. Kirim di setiap permintaan:
Authorization: Bearer nata_whk_<key_id>.<rahasia>
Jangan tertukar dengan kunci widget
Widget resmi memakai kunci publik nata_pub_… yang boleh ditempel di HTML dan hanya bisa memanggil widget. API memakai nata_whk_… yang rahasia, hanya di server, dan memotong kredit API. Kunci widget tidak bisa memanggil /webhook/nata, dan kunci API tidak boleh dipakai di script widget.
Ganti kunci
Tekan Ganti kunci di halaman yang sama. Kunci lama langsung mati — tidak ada masa transisi — jadi perbarui environment variable di servermu segera setelah mengganti. Kalau kamu perlu memutar kunci tanpa downtime, hubungi kami: dua kunci aktif sekaligus belum didukung hari ini.
Kalau kunci bocor
Ganti kunci sekarang di halaman API (kunci lama mati seketika).
Perbarui NATA_API_KEY di server dan deploy ulang.
Cek pemakaian di halaman API (pesan hari ini) untuk melihat apakah ada pemakaian yang bukan dari kamu.
Email [email protected] dengan key_id (bukan kuncinya) supaya kami bisa menelusuri log.
Kunci bocor yang ditempel di kode frontend adalah penyebab paling umum. Kalau kunci itu terbaca browser, anggap sudah bocor.
3. Quickstart
Semua endpoint integrasi, sekilas:
Endpoint
Auth
Untuk apa
POST /webhook/nata
Bearer nata_whk_…
Kirim satu pesan, dapat balasan. Sinkron, atau 202 + callback.
GET /webhook/nata/usage
Bearer nata_whk_…
Meteran sendiri: pesan hari ini, token, sisa kredit.
PUT /webhook/nata/knowledge
Bearer nata_whk_…
Dorong katalog produk dan halaman kebijakan dari backend.
GET /api/embed/config
kunci publik + origin terdaftar
Konfigurasi widget (dipakai widget; berguna untuk cek cepat).
POST /api/embed/shop-chat
kunci publik + origin terdaftar
Pertanyaan pembeli ke widget.
Ganti kunci, atur URL callback, dan lihat meteran ada di halaman API-nya sendiri: api.nyataka.com → Kunci. Tidak ada endpoint untuk memutar kunci dari server — itu sengaja, supaya kunci tidak bisa diganti oleh kode yang mungkin sudah bocor.
curl
curl -X POST https://app.nyataka.com/webhook/nata \
-H "Authorization: Bearer $NATA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"text":"Stok gamis ukuran L masih ada?","thread_id":"cust-123"}'
JavaScript (Node 18+, fetch bawaan)
const res = await fetch("https://app.nyataka.com/webhook/nata", {
method: "POST",
headers: {
Authorization: "Bearer " + process.env.NATA_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({ text: "Stok gamis L masih ada?", thread_id: "cust-123" }),
});
const data = await res.json();
if (!res.ok) {
// data.error berisi kode mesin, lihat bagian 8
throw new Error(data.error);
}
console.log(data.reply); // balasan siap tampil
Isi permintaan
Field
Wajib
Arti
text
ya, kecuali ada lampiran
Pesan masuk. Dipotong di 8.000 karakter. message juga diterima sebagai nama lain.
thread_id
tidak
Penanda percakapan milikmu (mis. id tiket/pelanggan). Diteruskan apa adanya di balasan.
{
"ok": true,
"reply": "Masih ada 4 pcs ukuran L.",
"reply_html": "<p>Masih ada 4 pcs ukuran L.</p>",
"reply_text": "Masih ada 4 pcs ukuran L.",
"backend": "internal",
"thread_id": "cust-123",
"usage": { "messages_today": 12, "input_tokens": 812, "output_tokens": 233, "messages_this_month": 640 },
"credits": 488
}
reply adalah Markdown dari Nata. reply_html sudah dirender jadi HTML, dan reply_text versi tanpa Markdown — pakai salah satu yang cocok dengan UI-mu. usage.input_tokens/output_tokens hanya untuk rekonsiliasi biaya di sisimu, bukan satuan yang kami tagih; messages_this_month dipakai untuk memantau ambang volume. backend adalah label internal kami: jangan dipakai untuk logika.
Permintaan berat (analisis, laporan panjang) bisa lebih lama dari kesabaran pengguna. Kirim mode: "async": kami menjawab 202 langsung dan mengirim hasilnya ke URL callback yang tersimpan di halaman API.
Balasan callback adalah JSON yang sama dengan balasan sinkron (reply, reply_html, reply_text, thread_id), dikirim sebagai POST ke URL-mu.
Verifikasi tanda tangan callback
Setiap callback ditandatangani, jadi orang yang tahu URL callback-mu tetap tidak bisa menyuntikkan balasan palsu. Rahasianya adalah callback_signing_secret di halaman API (terbit bersama kunci dan tidak berubah saat kunci diganti; GET /api/web/webhook/status menampilkannya lagi kalau lupa), dikirim sebagai header:
Header
Isi
X-Nyataka-Timestamp
Unix detik saat kami menandatangani. Tolak kalau selisihnya lebih dari 5 menit.
X-Nyataka-Signature
sha256=<hex>, HMAC-SHA256 dari <timestamp>.<body mentah> dengan secret itu.
Contoh verifikasi di Node (pakai body mentah, sebelum JSON.parse):
URL callback harus https publik. http://, localhost, IP privat, dan host .local/.internal ditolak dengan callback_url_must_be_https atau invalid_callback_url.
Kami mencoba 2 kali dengan jeda 1,5 detik, lalu berhenti. Tidak ada antrean di sisi kami, jadi balas 2xx secepatnya — simpan ke antrean di sisimu kalau perlu.
Redirect tidak diikuti, dan alamatnya dicek ulang waktu pengiriman (anti DNS rebinding).
Kalau URL callback diisi, salinan balasan juga dikirim ke sana untuk permintaan sinkron. Kalau tidak mau, kosongkan URL callback.
5. Kirim katalog sendiri
Nata menjawab pembeli dari data tokomu. Dua cara mengisinya: biarkan Nata membaca sitemap situsmu dari tab Akun (Baca katalog dari website), atau dorong datanya dari backend — lebih akurat untuk stok dan harga yang berubah cepat.
Maks 500 produk dan 500 halaman per kiriman. Kirim bertahap kalau katalogmu lebih besar.
Balasan: { "ok": true, "counts": { "products": 128, "pages": 12 } } — jumlah yang tersimpan setelah kiriman.
Body kosong (tidak ada produk maupun halaman yang lolos) → 400 nothing_to_store.
Yang didapat seller: Nata menjawab dari harga, stok, dan kebijakan asli tokomu, bukan menebak. Kalau katalog belum pernah dikirim, Nata akan bilang datanya belum ada — itu perilaku yang benar, bukan bug.
Keduanya memakai kunci publik dan hanya melayani origin yang kamu izinkan — bukan pengganti API server-to-server, dan tidak menerima kunci nata_whk_.
CORS dan daftar origin
Permintaan pembeli hanya dilayani kalau header Origin browser sama persis dengan salah satu baris di daftar Website yang boleh memasang widget. Tulis skema + host saja, tanpa path dan tanpa garis miring di akhir:
https://tokumu.com
https://www.tokumu.com
Origin yang tidak terdaftar mendapat 403 origin_not_allowed dan header CORS tidak dikirim — jadi di browser gejalanya sering muncul sebagai error CORS di console, bukan sebagai pesan error dari widget. Itu penyebab tersamar nomor satu; cek daftar origin dulu sebelum menuduh yang lain.
Subdomain berbeda = origin berbeda. https://www.tokumu.com tidak otomatis diizinkan oleh baris https://tokumu.com. Tambahkan keduanya kalau pembeli bisa datang dari dua-duanya.
Batas widget
Per IP: 30 pesan per 10 menit; per situs: 40 pesan per menit. Lewat batas → 429 slow_down.
Kuota harian pembeli per situs (default 25, diatur di halaman widget). Habis → 429 store_daily_cap, dan pesannya menyarankan pembeli menghubungi kontak tokomu.
Pesan pembeli dipotong di 800 karakter; lebih dari 1.600 karakter ditolak 413 message_too_long.
Widget butuh paket yang mengizinkan integrasi web (Max). Akun tanpa itu → 403 widget_plan_required, dan widget tidak muncul.
6b. Copilot halaman (page agent)
Kalau halaman admin milikmu sendiri yang ingin dibantu Nata, kirim mode: "copilot" ke endpoint yang sama. Kamu mengirim apa yang terlihat di halaman; Nata membalas kalimat + daftar aksi yang boleh dijalankan halaman itu. Nata tidak punya browser di sini — halamanmu yang mengeksekusi.
Balasannya memuat reply, actions, requires_approval, dan session_id. Aksi yang diizinkan hanya set_field (nama field harus ada di page.fields) dan click (ref harus ada di page.elements). Server membuang aksi ke Simpan/Publikasi/Hapus/Bayar/Kirim; halaman tetap wajib menampilkan diff dan meminta persetujuan bila requires_approval.
access_mode: read_only (tanpa aksi), approval (default, aksi menunggu persetujuan), full_access (aksi boleh langsung dijalankan). Satu panggilan copilot = satu kredit API. Panduan lengkap dan contoh page agent ada di docs/copilot-api.md di repo; kontrak ini berlaku untuk semua customer API, bukan hanya satu toko.
Kalau halamanmu punya banyak route, deklarasikan manifest sekali. Contoh nyata Rumaisha: 20 route, 86 field, 11 flow; pack-nya ada di docs/rumaisha-page-agent-pack.json. Manifest menyimpan struktur, bukan nilai field, password, atau data pembeli.
7. Batas dan kuota API
Batas
Nilai
Kalau lewat
Panjang text
8.000 karakter
Dipotong, bukan ditolak.
Ukuran body JSON
8 MB
Permintaan ditolak sebelum sampai ke Nata (batas server).
Dua pagar, dua hitungan. Pesan API memakai kuota harian API sendiri, bukan jatah chat harian paketmu — chat web dan API tidak saling memotong. Dua pagar itu: batas harian API di atas (429 daily_chat_quota), dan saldo prabayar satu kredit per pesan (402 quota_exhausted). Kunci tanpa saldo prabayar — mis. kunci lama yang dibuat sebelum kredit ada — tidak memotong kredit, tetapi batas harian API tetap berlaku. Angka nyata untuk akunmu ada di halaman API.
Harga
Ringkasnya ada di Biaya & paket di atas: API adalah paket terpisah, prabayar Rp 199 per pesan, tanpa biaya bulanan.
Pemakaian
Harga
Catatan
Pesan teks masuk
Rp 199
1 pesan = 1 balasan. Top up minimum Rp 250.000.
Volume, mulai 50.000 pesan/bulan
Rp 175
Perjanjian terpisah untuk partner.
Volume, mulai 100.000 pesan/bulan
Rp 149
Perjanjian terpisah untuk partner.
Harga ini keputusan pemilik 2026-10-03 (docs product-strategy-tiers-api §4). Penagihan masih manual lewat tim: belum ada top up sendiri di app dan belum ada invoice otomatis. Untuk menambah kredit, email [email protected] dengan key_id-mu.
8. Error
Semua error berbentuk JSON { "error": "kode_mesin" }. error adalah kontrak yang stabil dan tidak berubah bahasa. Kalau ada teks untuk manusia, ia datang dua kali: message (Indonesia) dan message_en (Inggris). Kadang ada juga credits atau required. Kode di bawah ini yang benar-benar dikeluarkan hari ini.
API webhook
HTTP
Kode
Artinya & yang harus dilakukan
401
missing_api_key
Header Authorization kosong atau bukan format Bearer.
401
invalid_api_key
Kunci salah, sudah diganti, atau kunci lama. Buat kunci baru di halaman API.
400
invalid_text
Tidak ada text (dan tidak ada lampiran) di body.
402
quota_exhausted
Kredit prabayar habis. Balasan menyertakan credits. Minta top up ke tim.
400
callback_url_required_for_async
mode: "async" dipakai padahal belum ada URL callback tersimpan.
429
daily_chat_quota
Batas pesan harian API tersentuh (nama kode menyebut "chat"; di jalur API maksudnya batas API). Reset 07.00 WIB.
403
webhook_channel_scale_only
Akun ini belum punya langganan API. Nama kode ini menyebut paket karena sejarahnya; yang benar dibaca adalah required: "api_subscription" dan message/message_en di body.
403
account_disabled
Akun dinonaktifkan. Hubungi dukungan.
401
unknown_seller
Kunci menunjuk akun yang sudah tidak ada.
502
agent_failed
Backend Nata gagal menjawab. Kredit pesan itu dikembalikan; coba lagi.
504
agent_timeout
Nata kehabisan waktu. Kredit dikembalikan; coba lagi atau pakai mode: "async".
400
page_cannot_commit
Halaman belum punya simpan. Pilih mode Baca, atau tambahkan commit di page agent.
400
attachments_not_supported
Mode copilot tidak menerima lampiran; kirim hanya page dan message.
501
copilot_not_configured
Deployment ini belum mengaktifkan copilot. Hubungi tim.
PUT /webhook/nata/knowledge atau "Baca katalog dari website" di halaman widget
Balasan terpotong
Batas 8.000 karakter untuk pesan masuk
Kirim pesan lebih pendek, atau ringkas di sisimu
10. Dukungan
Email [email protected] — sertakan key_id (bukan kunci rahasianya), waktu kejadian (WIB), endpoint yang dipanggil, dan body respons mentahnya. Untuk permintaan top up kredit, tulis "Top up kredit API" di subjek.