Data API (sebelumnya didokumentasikan di sini sebagai Server API) memungkinkan backend Anda membaca data identifikasi yang sudah dikumpulkan TRACIO untuk workspace Anda: riwayat seorang pengunjung, sesi satu per satu, dan penghitung velocity pada jendela pendek. Beberapa route juga menulis — catatan akun, field kustom, dan entri daftar — sehingga backend Anda dapat memperkaya apa yang diketahui TRACIO.
Ia melengkapi Webhook, bukan menggantikannya:
| Webhooks | Data API | |
|---|---|---|
| Arah | TRACIO mendorong ke endpoint Anda | Backend Anda menarik saat dibutuhkan |
| Waktu | Saat setiap identifikasi terjadi | Kapan saja, dalam jendela retensi Anda |
| Paling cocok untuk | Bereaksi terhadap sebuah peristiwa | Mencari data saat mengambil keputusan, pengisian ulang, investigasi |
Kedua permukaan tersedia mulai paket Pro ke atas.
https://api.tracio.ai/v2Ini adalah host yang berbeda dari endpoint peramban (edge.tracio.ai) dan dari dashboard
(app.tracio.ai). Ketiganya terpisah: peramban berbicara dengan edge memakai kunci
public Anda, sedangkan backend Anda berbicara dengan Data API memakai kunci
secret Anda.
Route /v1 telah dihapus. Gunakan /v2: route-nya sama, dan setiap kunci JSON serta
parameter query memakai snake_case (visitor_id, risk_score, min_risk_score).
Kunci di dalam kamus fields dan labels milik Anda sendiri adalah data Anda dan
mempertahankan ejaan aslinya. SDK JavaScript tetap memakai antarmuka camelCase.
Setiap permintaan membawa secret key Anda sebagai bearer token:
curl -H "Authorization: Bearer tracio_sk_XXXX...XXXX" \ "https://api.tracio.ai/v2/visitors/X7fh2Hg9LkMn3pQr5tBvQw3xZa9mK2pL4nR8dT6y"Data API hanya untuk komunikasi server ke server. Header CORS sengaja tidak dikembalikan, sehingga peramban tidak dapat memanggilnya — itulah yang menjaga secret key Anda tetap di luar kode sisi klien. Jangan pernah mengirimkan secret key ke peramban.
Buat di dashboard pada bagian API Keys, dengan memilih tipe secret.
tracio_sk_ diikuti 43 karakter, total 53. Dashboard
menampilkannya berdasarkan beberapa karakter pertama sehingga Anda bisa membedakan
antar kunci.404, persis seperti untuk data yang tidak ada.Rotasi menerbitkan kunci baru dan membiarkan kunci lama tetap bekerja selama 7 hari, sehingga Anda bisa menggulirkannya tanpa waktu henti. Terapkan kunci baru, pastikan trafiknya sudah berpindah, lalu biarkan kunci lama kedaluwarsa. Public key tidak dapat dirotasi — kunci itu bukan rahasia dan memang terlihat di sumber halaman Anda.
| Metode | Path | Mengembalikan |
|---|---|---|
GET | /v2/visitors/{visitor_id} | Riwayat teragregasi satu pengunjung, plus sesi terbarunya |
GET | /v2/visitors/{visitor_id}/sessions | Daftar terpaginasi sesi-sesi pengunjung tersebut |
GET | /v2/visitors/{visitor_id}/sessions/latest | Satu sesi paling baru saja |
GET | /v2/visitors/{visitor_id}/velocity | Penghitung aktivitas pada jendela pendek |
GET | /v2/sessions/{request_id} | Satu sesi berdasarkan pengidentifikasi permintaannya |
POST | /v2/accounts/metadata | Lampirkan nama tampilan dan email ke ID akun Anda |
POST | /v2/events/fields | Lampirkan field kustom ke kunjungan setelah halaman dimuat |
POST | /v2/events/fields/delete | Hapus field kustom dari kunjungan — kunjungannya sendiri tidak disentuh |
GET | /v2/lists | Daftar workspace Anda: id, nama, tipe (tindakannya), mode, jumlah entri |
POST | /v2/lists/{list_id}/entries | Tambahkan nilai ke daftar, opsional dengan TTL |
POST | /v2/lists/{list_id}/entries/delete | Hapus nilai dari daftar |
GET | /.well-known/webhook-keys | Kunci publik untuk tanda tangan platform webhook (tanpa autentikasi) |
Kunci dan host yang sama juga melayani API keputusan, semuanya dalam snake_case:
| Metode | Path | Tujuan |
|---|---|---|
POST | /v2/transactions | Keputusan sinkron APPROVE / REVIEW / DECLINE atas peristiwa bisnis — Business ke atas, kecuali konversi afiliasi (account_register atau deposit dengan affiliate_id), yang tersedia di setiap paket dengan akses API |
GET | /v2/transactions/{transaction_id} | Baca ulang keputusan beserta label dan keadaan efektifnya — Business ke atas, kecuali transaksi yang diatribusikan ke afiliasi |
PUT, DELETE | /v2/transaction-labels | Atur atau hapus label hasil hingga 50 transaksi — Business ke atas |
GET | /v2/transaction-labels/value-set | Nilai label yang diterima beserta polaritasnya — Business ke atas |
POST | /v2/logins/assess | Menilai login: allow / challenge / review / deny beserta alasannya |
POST, GET | /v2/accounts/{user_id}/trusted-devices | Jadikan perangkat suatu kunjungan tepercaya untuk sebuah akun setelah step-up Anda, atau tampilkan daftar perangkat tepercaya akun |
DELETE | /v2/accounts/{user_id}/trusted-devices/{device_ref} | Cabut kepercayaan sebuah perangkat |
GET | /v2/affiliates/{affiliate_id} | Laporan kualitas afiliasi selama 90 hari, dengan rekomendasi hold / review |
POST, GET | /v2/self-exclusions | Atur atau perpanjang pengecualian diri pada sebuah akun, atau tampilkan daftarnya |
DELETE | /v2/self-exclusions/{user_id} | Cabut pengecualian diri lebih awal |
Hasilnya juga sampai kepada Anda sebagai peristiwa webhook:
transaction_state_changed, login_risk, trusted_device_enrolled,
trusted_device_revoked, dan affiliate_threshold_crossed.
Garis miring di akhir diterima dan diabaikan. Path yang tidak dikenal atau metode yang salah mengembalikan amplop error JSON yang sama seperti segala hal lainnya, tidak pernah berupa halaman HTML atau teks biasa.
Setiap pembacaan dibatasi oleh sebuah jendela waktu, yang dikendalikan dua parameter query opsional:
| Parameter | Menerima |
|---|---|
from | YYYY-MM-DD atau timestamp RFC 3339 lengkap |
to | YYYY-MM-DD atau timestamp RFC 3339 lengkap |
to mencakup seluruh hari itu.400 invalid_request dan pesan
time must be YYYY-MM-DD or RFC3339.meta, jadi periksalah meta.from dan meta.to alih-alih
menganggap permintaan Anda dipenuhi apa adanya.curl -H "Authorization: Bearer tracio_sk_XXXX...XXXX" \ "https://api.tracio.ai/v2/visitors/X7fh2Hg9LkMn3pQr5tBvQw3xZa9mK2pL4nR8dT6y"Responsnya membawa riwayat agregat dan menyertakan sesi terbaru, sehingga kasus umum cukup dengan satu permintaan alih-alih dua:
{ "visitor_id": "X7fh2Hg9LkMn3pQr5tBvQw3xZa9mK2pL4nR8dT6y", "first_seen_at": "2026-05-02T10:11:12Z", "last_seen_at": "2026-07-25T08:00:00Z", "visits": 42, "incognito_visits": 3, "unique_ips": 5, "unique_countries": 2, "browsers": ["Chrome"], "os": ["macOS"], "devices": ["desktop"], "risk": { "max_risk_score": 63, "avg_bot_score": 12.5, "bot_sessions": 7, "last_decision": "real" }, "network": { "vpn_seen": false, "proxy_seen": false, "tor_seen": false, "datacenter_seen": true, "proxy_detected_seen": true, "last_isp": "Deutsche Telekom", "last_real_ip": { "address": "203.0.113.7", "country": "NL", "isp": "KPN" } }, "last_session": { "request_id": "9c1f6a2e-3b7d-4c58-a1e2-6f0d8b4a7c31", "visitor_id": "X7fh2Hg9LkMn3pQr5tBvQw3xZa9mK2pL4nR8dT6y", "account_id": "user_8842", "account": { "id": "user_8842", "email": "ann@example.com", "display_name": "Ann Lee" }, "timestamp": "2026-07-25T08:00:00Z", "tag": "checkout", "fields": { "order_ref": "A-1029" }, "url": "https://shop.example.com/checkout", "ip": "203.0.113.42", "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36", "browser": { "name": "Chrome", "version": "126.0" }, "os": { "name": "macOS", "version": "14.5" }, "device": "desktop", "gpu": "Apple M2", "geo": { "country": "DE", "city": "Berlin", "timezone": "Europe/Berlin", "isp": "Deutsche Telekom" }, "network": { "vpn": false, "proxy": false, "tor": false, "datacenter": false, "connection_type": "residential", "proxy_detected": true, "real_ip": { "address": "203.0.113.7", "country": "NL", "isp": "KPN" }, "asn": 3320 }, "screen": { "width": 2560, "height": 1600, "color_depth": 30, "pixel_ratio": 2 }, "locale": { "languages": ["en-US", "de"], "timezone": "Europe/Berlin" }, "client_hints": { "architecture": "arm", "bitness": "64", "platform_version": "14.5.0" }, "extensions": [ { "slug": "ublock-origin", "name": "uBlock Origin", "category": "adblock", "risky": false, "store_url": "https://chromewebstore.google.com/detail/cjpalhdlnbpafiamejdnhcphjbkeiagm" } ], "bot": { "result": "human", "score": 4.5, "antidetect_score": 2.1 }, "identification": { "confidence": 0.97, "incognito": false, "match_type": "exact", "match_confidence": 0.99 }, "device_info": { "device_id": "d_4f9c2e", "cross_browser": true, "confidence": 0.88, "linked_browsers": 2 }, "decision": { "action": "real", "risk_score": 12, "suspect_score": 3 } }, "meta": { "plan": "business", "retention_days": 90, "from": "2026-04-26T00:00:00Z", "to": "2026-07-25T12:00:00Z" }}| Field | Arti |
|---|---|
visits, incognito_visits | Total kunjungan dalam jendela, dan berapa yang terjadi di jendela pribadi |
unique_ips, unique_countries | Alamat dan negara berbeda yang terlihat dalam jendela |
browsers, os, devices | Lingkungan berbeda tempat pengunjung ini pernah muncul |
risk.max_risk_score | Skor risiko tertinggi yang tercatat dalam jendela, 0..100 |
risk.last_decision | Keputusan yang tercatat untuk kunjungan paling baru |
risk.avg_bot_score, risk.bot_sessions | Rata-rata skor bot dan jumlah sesi bot — Business ke atas |
network.*_seen | Apakah VPN, proxy, node keluar Tor, atau alamat datacenter pernah terlihat pada pengunjung ini |
network.proxy_detected_seen | Apakah setidaknya satu kunjungan dalam jendela keluar lewat proxy atau VPN di depan peramban — lihat network.proxy_detected pada bagian Fakta perangkat |
network.last_isp | ISP paling baru — Business ke atas |
network.last_real_ip | Alamat paling baru yang teramati di balik proxy atau VPN (address, country, isp) — Business ke atas; tidak ada bila tidak ada kunjungan yang membawanya |
last_session | Objek sesi lengkap untuk kunjungan paling baru |
meta | Paket, retensinya dalam hari, dan jendela yang benar-benar diterapkan |
Pengunjung tanpa data di dalam jendela retensi mengembalikan 404 not_found dengan pesan
visitor not found in the retention window — itu bukan error pada integrasi Anda,
melainkan berarti pengunjungnya baru atau datanya sudah melewati masa retensi.
Sesi membawa dua verdict, dan keduanya menjawab pertanyaan berbeda — apakah kliennya otomatis, dan apa kesimpulan keseluruhan dari mesin risiko:
| Field | Nilai |
|---|---|
bot.result | human, bot, uncertain |
bot.type | Hadir ketika bot.result bernilai bot: bisa berupa alat tertentu (playwright, puppeteer, selenium, jsdom, claude_computer_use…), agen AI terverifikasi (ai_agent:<vendor>), atau sebuah keluarga bila alatnya tidak disebutkan — automation, headless, antidetect, extension, privacy_browser, impersonation, other |
decision.action | real, fake, suspicious |
bot.score dan decision.risk_score sama-sama berjalan pada 0..100. Pada Business ke
atas, guidance mengubahnya menjadi saran per skenario pada tangga
allow → challenge → review → deny — lihat
Guidance untuk arti setiap anak tangganya.
Nilai dan skalanya sama dengan body webhook v3 untuk kunjungan yang sama, dan
guidance dihitung dengan aturan yang sama.
curl -H "Authorization: Bearer tracio_sk_XXXX...XXXX" \ "https://api.tracio.ai/v2/visitors/X7fh2Hg9LkMn3pQr5tBvQw3xZa9mK2pL4nR8dT6y/sessions?limit=100&min_risk_score=50"| Parameter | Default | Catatan |
|---|---|---|
limit | 50 | Dibatasi di 500; nilai lebih besar dipangkas, bukan ditolak |
from, to | Retensi paket | Jendela waktu bersama yang dijelaskan di atas |
cursor | — | Kursor paginasi buram dari halaman sebelumnya |
bot_result | — | Hanya simpan sesi dengan verdict bot ini |
min_risk_score | — | Hanya simpan sesi pada skor risiko ini atau di atasnya, 0..100 |
Sesi dikembalikan dari yang terbaru lebih dulu:
{ "items": [ { "request_id": "9c1f6a2e-3b7d-4c58-a1e2-6f0d8b4a7c31", "visitor_id": "X7fh2Hg9LkMn3pQr5tBvQw3xZa9mK2pL4nR8dT6y", "timestamp": "2026-07-25T08:00:00Z" } ], "next_cursor": "MTcyMTg5NDQwMDAwMDphYmMxMjM", "has_more": true, "meta": { "plan": "business", "retention_days": 90, "from": "2026-04-26T00:00:00Z", "to": "2026-07-25T12:00:00Z" }}Paginasi berbasis kursor. Tidak ada parameter page atau offset: kirimkan kembali
next_cursor yang Anda terima sebagai cursor, dan teruskan selama has_more
bernilai benar. Halaman terakhir mungkin sama sekali tidak menyertakan next_cursor,
jadi jangan jadikan field itu wajib.
async function allSessions(visitorId: string, secretKey: string) { const sessions = [] let cursor: string | undefined
do { const url = new URL(`https://api.tracio.ai/v2/visitors/${visitorId}/sessions`) url.searchParams.set("limit", "500") if (cursor) url.searchParams.set("cursor", cursor)
const res = await fetch(url, { headers: { Authorization: `Bearer ${secretKey}` } }) if (!res.ok) throw new Error(`Data API: ${res.status}`)
const page = await res.json() sessions.push(...page.items) cursor = page.has_more ? page.next_cursor : undefined } while (cursor)
return sessions}Perlakukan kursor sebagai buram — isinya adalah detail implementasi dan bisa berubah.
Kursor yang telah disunting ditolak dengan 400 invalid_request dan pesan
malformed cursor.
Selain peramban dan OS yang diambil dari User-Agent, sebuah sesi membawa apa yang dilaporkan peramban pengunjung tentang mesinnya, sudah dibersihkan di sisi kami. Setiap field tidak ada bila kunjungan tidak membawa data semacam itu, jadi perlakukan masing-masing sebagai opsional.
| Field | Arti |
|---|---|
gpu | Model adaptor video seperti yang dilaporkan peramban (WebGL), dinormalisasi menjadi nama yang terbaca — Intel Iris Xe Graphics, Apple M1 Pro, Qualcomm Adreno 830; Software renderer berarti tidak ada GPU nyata (mesin virtual atau lingkungan headless); Safari melaporkan Apple GPU |
network.proxy_detected | Lalu lintas HTTP kunjungan dan jalur jaringan mentahnya keluar lewat jaringan yang berbeda — ada proxy atau VPN di depan peramban; dua alamat dari penyedia yang sama (NAT operator, keluaran kedua dari VPN yang sama) tidak dihitung; tidak dimunculkan bila alamatnya tidak dapat dibandingkan (iCloud Private Relay, IPv4 di samping IPv6) |
network.real_ip.address, .country, .isp | Alamat publik yang teramati pada jalur jaringan mentah, yaitu alamat di balik proxy atau VPN, beserta negara dan ISP-nya — Business ke atas; tidak ada bila alamat semacam itu tidak teramati (country dan isp tidak ada bila tidak dapat ditentukan) |
device_info.device_id, .cross_browser, .confidence, .linked_browsers | Hadir ketika identitas perangkat berhasil ditentukan: id stabil dari perangkat fisik yang menembus semua peramban di atasnya, apakah kunjungan ini datang lewat peramban yang berbeda dari sebelumnya, keyakinan atas kecocokan itu, dan berapa banyak pengunjung (peramban) berbeda yang berbagi perangkat tersebut — lebih dari satu berarti satu mesin di bawah beberapa identitas peramban — Business ke atas |
os_environment | Lingkungan desktop yang diukur pada mesin Linux (Mint 22+, Ubuntu 25.04+, Ubuntu, GNOME, KDE) — Business ke atas; tidak ada bila tidak dapat ditentukan |
spoofing | Apa yang diklaim kunjungan dibandingkan dengan apa yang diukur pemeriksaan independen (claimed, real, spoofed_axes dari os, gpu, screen, network, browser; anonymous_browser dengan nama produk) — Business ke atas; hadir hanya bila pemalsuan terdeteksi |
screen.width, .height, .color_depth, .pixel_ratio | Resolusi layar, kedalaman warna, dan device pixel ratio seperti yang dilaporkan peramban — Business ke atas |
locale.languages, locale.timezone | Bahasa pilihan dan zona waktu peramban itu sendiri — berbeda dengan geo.timezone yang diturunkan dari alamat IP; ketidakcocokan di antara keduanya adalah tanda umum lokasi yang dipalsukan — Business ke atas |
client_hints.architecture, .bitness, .model, .device_name, .platform_version | User-Agent Client Hints: arsitektur dan bitness CPU, kode model perangkat (Android, mis. SM-A556B) beserta nama pemasarannya dari daftar perangkat Google Play (device_name, mis. Samsung Galaxy A55 5G), dan versi platform yang persis; hanya peramban berbasis Chromium — Business ke atas |
environment.virtual_machine, environment.hypervisor | Hadir hanya bila adaptor video menyatakan dirinya sebagai adaptor virtual; hypervisor adalah kamus tertutup (vmware, virtualbox, parallels, qemu, hyperv, bochs, intel-gvt, vgpu). Blok yang tidak ada berarti tidak ada bukti semacam itu — Business ke atas |
extensions mencantumkan ekstensi peramban yang terdeteksi selama kunjungan — Pro ke
atas. Setiap entri berupa sebuah objek:
| Field | Arti |
|---|---|
slug | Pengidentifikasi mesin yang stabil untuk ekstensi, nilai yang sama dengan yang dikirim webhook |
name | Nama yang mudah dibaca manusia |
category | Kelas kasar — adblock, privacy, automation, wallet, vpn, devtools, other, dan seterusnya |
risky | true untuk ekstensi yang terkait dengan otomasi, pemalsuan, atau pencurian kredensial |
store_url | Tautan ke halaman ekstensi di toko, bila diketahui |
Sebuah temuan baru dilaporkan setelah lolos pemeriksaan kepercayaan kami — lingkungan yang menjawab "terpasang" pada setiap pemeriksaan, atau kumpulan yang lebih panjang dari 12 nama, dibuang karena tidak dapat diandalkan. Karena itu daftar yang kosong atau tidak ada berarti "tidak ada yang bisa kami konfirmasi", bukan "tidak ada ekstensi yang terpasang". Bacalah itu sebagai bukti, bukan sebagai daftar inventaris.
fields berisi pasangan kunci-nilai kustom yang dilampirkan integrasi Anda ke kunjungan — referensi pesanan, nama paket, hasil pembayaran. Kunci dan nilai selalu berupa string: angka atau boolean yang Anda lampirkan dikembalikan dalam bentuk teks. Seperti bagian sesi lainnya, kolom ini tersedia di setiap paket dengan akses API (Pro ke atas) dan tidak ada jika kunjungan tidak memiliki kolom.
fields dibaca langsung pada setiap permintaan, bukan disalin saat kunjungan terjadi.
Kolom yang dilampirkan setelah kunjungan (lihat
Melampirkan field setelah kunjungan) juga muncul
di sini, sehingga untuk kunjungan yang sama fields bisa berisi lebih banyak daripada
yang dikirim webhook.
Jangan masukkan data pribadi seperti nama, alamat email, atau nomor telepon ke kolom kustom — lampirkan referensi yang dapat diselesaikan oleh sistem Anda sendiri sebagai gantinya, dan kirim siapa pemilik akun itu sebagai catatan akun (di bawah).
account adalah catatan Anda untuk akun di balik kunjungan — apa yang terakhir Anda
kirim untuk account_id tersebut melalui
POST /v2/accounts/metadata:
{ "account": { "id": "user-42", "email": "ann@example.com", "display_name": "Ann Lee" }}| Field | Deskripsi |
|---|---|
id | ID akun Anda — nilai yang sama dengan account_id |
email | Alamat email yang Anda kirim untuk akun; tidak ada bila kosong |
display_name | Nama tampilan yang Anda kirim untuk akun; tidak ada bila kosong |
Catatan ini dibaca langsung pada setiap permintaan, jadi penggantian nama juga muncul pada kunjungan lama: blok ini menggambarkan akun sebagaimana adanya sekarang, bukan sebagaimana saat kunjungan terjadi. Tersedia di setiap paket dengan akses API (Pro ke atas). Label yang Anda kirim bersama catatan tidak dikembalikan.
Blok ini tidak ada bila kunjungan tidak memiliki akun tertaut, bila tidak ada catatan untuknya (atau Anda mengosongkannya dengan mengirim nilai kosong), dan — jarang — bila catatan tidak dapat dibaca: sesi tetap dikembalikan secara lengkap alih-alih menggagalkan permintaan, jadi perlakukan blok yang tidak ada sebagai "tidak diketahui", bukan "akun ini tidak punya email". Webhook tidak membawa blok ini.
Yang paling baru:
curl -H "Authorization: Bearer tracio_sk_XXXX...XXXX" \ "https://api.tracio.ai/v2/visitors/X7fh2Hg9LkMn3pQr5tBvQw3xZa9mK2pL4nR8dT6y/sessions/latest"Ini mengembalikan objek sesi telanjang — bukan array, dan tidak dibungkus dalam amplop.
Pengunjung tanpa sesi apa pun dalam jendela mengembalikan 404 not_found dengan
no sessions for this visitor in the retention window.
Atau berdasarkan request_id, pengidentifikasi yang juga muncul pada payload webhook:
curl -H "Authorization: Bearer tracio_sk_XXXX...XXXX" \ "https://api.tracio.ai/v2/sessions/9c1f6a2e-3b7d-4c58-a1e2-6f0d8b4a7c31?visitor_id=X7fh2Hg9LkMn3pQr5tBvQw3xZa9mK2pL4nR8dT6y"visitor_id bersifat opsional di sini, tetapi mengirimkannya ketika Anda mengetahuinya
membuat pencariannya jauh lebih cepat.
identification.drift_score — skor perilaku yang dihaluskan yang menjadi dasar verdict
pengambilalihan akun, Business ke atas — hanya dikembalikan oleh pembacaan satu sesi
ini. Penyimpangan perilaku diukur selama kunjungan, setelah identifikasi awal, sehingga
route daftar dan sesi terbaru tidak menyertakannya. Kunjungan yang perilakunya tidak
pernah dinilai tidak memiliki drift_score. Nilai yang sama sampai kepada Anda melalui
webhook account_takeover.
Sebuah kunjungan dapat dikirim lebih dari sekali lewat webhook: primary lebih dulu,
lalu late atau correction seiring datangnya sinyal yang lebih lambat dan bukti
perilaku — dan fase yang lebih akhir dapat membalik verdict sebelumnya. Data API
menjawab dari catatan primary. Fase yang lebih akhir tidak digabungkan kembali ke
dalamnya, jadi untuk kunjungan yang dikoreksi, webhook terakhir adalah jawaban yang
lebih baru. Jika Anda bertindak beberapa menit setelah kunjungan, utamakan fase yang
terakhir Anda terima ketimbang pembacaan baru di sini.
Satu hal berjalan ke arah sebaliknya: begitu detektor pengambilalihan akun terpicu
untuk sebuah kunjungan, guidance di sini mencerminkannya, sedangkan body webhook
identification dari kunjungan yang sama tidak membawa sumbu itu — sumbu itu ikut
dalam pengiriman account_takeover tersendiri.
Velocity menjawab pertanyaan "seberapa banyak yang dilakukan pengunjung ini belakangan ini" — bentuk khas dari credential stuffing, uji coba kartu, dan pendaftaran massal.
curl -H "Authorization: Bearer tracio_sk_XXXX...XXXX" \ "https://api.tracio.ai/v2/visitors/X7fh2Hg9LkMn3pQr5tBvQw3xZa9mK2pL4nR8dT6y/velocity?window=1h"window menerima 1h, 24h, atau 7d dan secara default 24h. Nilai lain apa pun
ditolak dengan 400 invalid_request dan window must be one of: 1h, 24h, 7d.
{ "window": "1h", "events": 37, "unique_ips": 9, "unique_countries": 3, "unique_accounts": 12, "bot_events": 4, "meta": { "plan": "business", "retention_days": 90, "from": "2026-07-25T11:00:00Z", "to": "2026-07-25T12:00:00Z" }}unique_accounts menghitung nilai linkedId berbeda yang Anda kirim untuk perangkat
ini — lihat Penautan akun. bot_events tersedia mulai
Business ke atas; pada Pro kuncinya tidak ada.
TRACIO mengenal akun Anda hanya melalui ID yang dikirim situs Anda sebagai linkedId —
string buram seperti usr_8412. Kirim label yang mudah dibaca manusia sekali saja, dan
setiap layar dashboard yang menampilkan akun itu akan menampilkan nama atau email
alih-alih ID mentah, dan objek sesi mengembalikannya dalam blok
account-nya. Tidak ada di sini yang memengaruhi deteksi atau
penilaian skor; ini lapisan tampilan.
curl -s -X POST "https://api.tracio.ai/v2/accounts/metadata" \ -H "Authorization: Bearer tracio_sk_XXXX...XXXX" \ -H "Content-Type: application/json" \ -d '{"accounts":[ {"account_id":"usr_8412","email":"ann@example.com","display_name":"Ann Lee","labels":{"tier":"vip"}}, {"account_id":"usr_9130","display_name":"Bob Ray"} ]}'{ "updated": 2 }fields. Email atau
nama yang dikirim ke sini hanya tinggal di catatan akun workspace Anda: tidak disimpan
per kunjungan, tidak ditulis ke halaman, dan satu kali pengiriman memperbarui setiap
kunjungan akun itu.400 invalid_request, dan satu entri
yang salah menolak seluruh batch — error-nya menyebut posisinya. ID akun duplikat
dalam satu batch tidak masalah: yang terakhir menang.Batas: 1000 akun per permintaan, body 1 MiB, account_id ≤ 256 karakter,
email ≤ 320, display_name ≤ 256, paling banyak 16 label dengan kunci ≤ 64 dan nilai
≤ 256 karakter.
Peramban hanya dapat mengirim apa yang diketahui halaman saat dirender — ID pesanan, tidak pernah hasil pemeriksaan pembayaran atau hal lain yang baru pasti kemudian. Route ini mengisi celah itu: temukan kunjungan berdasarkan field yang sudah dibawanya, lalu lampirkan field tambahan dari sisi server.
curl -s -X POST "https://api.tracio.ai/v2/events/fields" \ -H "Authorization: Bearer tracio_sk_XXXX...XXXX" \ -H "Content-Type: application/json" \ -d '{"match":{"key":"order_ref","value":"A-1029"},"fields":{"amount":"120.00"}}'{ "updated": 1 }match menemukan kunjungan berdasarkan field yang sudah dimilikinya, bukan
berdasarkan request_id, di dalam workspace dan lingkungan kunci Anda.404 not_found — tulis field-nya segera setelah hasilnya pasti.updated menghitung kunjungan yang berbeda. Nilainya melebihi 1 hanya bila
match Anda mengenai lebih dari satu kunjungan — pasangan kunci/nilai yang tidak unik
untuk satu pesanan atau keranjang. match yang mengenai lebih dari 100 peristiwa
ditolak dengan 400 invalid_request alih-alih diterapkan pada subset sembarang.server, dan lebih
diutamakan daripada nilai dengan kunci yang sama yang ditulis peramban.404 not_found, bukan 200 kosong.Batasnya sama dengan kanal peramban: 50 field per panggilan, kunci ≤ 40 byte, nilai
≤ 500 byte — byte, bukan karakter — set karakter kunci A-Za-z0-9_.:-, body 1 MiB.
Menghapus field kustom — tidak pernah kunjungannya sendiri. Gunakan untuk nilai yang tidak lagi perlu Anda lampirkan pada kunjungan, misalnya total pesanan. Webhook yang sudah terkirim dan ekspor yang sudah diambil tidak berubah.
# by request_id — clears every field on this one visitcurl -s -X POST "https://api.tracio.ai/v2/events/fields/delete" \ -H "Authorization: Bearer tracio_sk_XXXX...XXXX" \ -H "Content-Type: application/json" \ -d '{"request_id":"9c1f6a2e-3b7d-4c58-a1e2-6f0d8b4a7c31"}'
# by match — clears "order_ref" from every visit currently holding "A-1029"curl -s -X POST "https://api.tracio.ai/v2/events/fields/delete" \ -H "Authorization: Bearer tracio_sk_XXXX...XXXX" \ -H "Content-Type: application/json" \ -d '{"match":{"key":"order_ref","value":"A-1029"}}'{ "deleted": 1 }request_id dan match saling eksklusif — mengirim keduanya, atau tidak keduanya,
menghasilkan 400 invalid_request. match memakai jendela 24 jam yang sama dan batas
atas 100 peristiwa yang sama seperti saat melampirkan.deleted menghitung field yang dihapus dari kunjungan (berdasarkan request_id)
atau kunjungan tempat field itu dihapus (berdasarkan match).404 not_found.Daftar yang sama yang dikelola operator Anda di dashboard, dapat dijangkau dari back
office Anda sendiri. Tipe sebuah daftar adalah tindakannya pada kunjungan yang
cocok — block, manual_review, challenge, allow — dan mode-nya menentukan
apakah tindakan itu diterapkan: observe hanya menghitung kecocokan, enforce
menerapkannya ke guidance (sumbu list). Daftar dan modenya dibuat di dashboard;
Data API membaca daftar serta menambah dan menghapus entri.
curl -s "https://api.tracio.ai/v2/lists" \ -H "Authorization: Bearer tracio_sk_XXXX...XXXX"[ { "id": "7f3a9d2e-4c1b-4e8f-9a6d-1b2c3d4e5f60", "name": "Chargeback accounts", "type": "block", "mode": "enforce", "entries_count": 128 }]# ban an account for 30 dayscurl -s -X POST "https://api.tracio.ai/v2/lists/7f3a9d2e-4c1b-4e8f-9a6d-1b2c3d4e5f60/entries" \ -H "Authorization: Bearer tracio_sk_XXXX...XXXX" \ -H "Content-Type: application/json" \ -d '{"value":"usr_8412","value_type":"linked_id","ttl_minutes":43200}'{ "id": "02b4c8d1-6e7f-4a90-b1c2-d3e4f5a6b7c8", "value": "usr_8412", "value_type": "linked_id", "expires_at": "2026-10-19T12:00:00Z", "propagation": "immediate"}Hapus entri dengan body yang sama di POST /v2/lists/{list_id}/entries/delete;
jawabannya { "removed": true, "propagation": "immediate" }.
value_type adalah apa yang dicocokkan dengan nilai: linked_id, visitor_id,
device_id, ip, cidr, atau country. Nilai yang tidak dapat di-parse untuk
tipenya menghasilkan 400 invalid_request.linked_id → visitor_id → device_id → ip → cidr → country — dan di
dalamnya tindakan terketat yang menang.ttl_minutes bersifat opsional. Bila dihilangkan, TTL default daftar berlaku;
bila tidak ada, entri tidak pernah kedaluwarsa (expires_at bernilai null).
Menambahkan ulang entri akan memperpanjangnya.propagation menyatakan kapan perubahan aktif: immediate, atau ttl — dalam
sekitar lima menit.200 dengan removed: false; 404
disediakan untuk daftar yang tidak dikenal.Field yang tidak ada berarti "tidak ada data", tidak pernah berarti nol. Field tanpa
nilai dihilangkan sepenuhnya alih-alih dikirim sebagai 0, "", atau null: pengunjung
yang benar-benar baru tidak punya match_confidence, kunjungan yang bersih tidak punya
antidetect_score atau suspect_score. Satu-satunya pengecualian yang disengaja
adalah bot.score, yang selalu ada bahkan ketika nilainya nol. Bacalah field secara
defensif.
Payload bergantung pada paket Anda. Akses API dimulai dari Pro, dan Pro mendapatkan
sesi dasar — pengidentifikasi, timestamp, URL, IP, user agent, peramban, OS, perangkat,
geo, network, bot, identification, dan decision — bersama dengan
identification.match_type, identification.match_confidence, bot.score,
bot.type, bot.antidetect_score, gpu, network.proxy_detected, extensions,
fields, dan account. Business dan Enterprise menambahkan geo.isp, network.asn, network.real_ip, decision.suspect_score,
identification.drift_score, reasons, behavior, guidance, device_info,
spoofing, os_environment, screen, locale, client_hints, dan environment.
Field tingkat orang (person_id, reputation, linked_accounts_count,
linked_visitors_count) disediakan untuk Business dan Enterprise dan akan muncul
begitu lapisan orang diaktifkan — saat ini lapisan itu berjalan dalam mode pengamatan
dan field-field ini tidak dikirimkan. Tidak adanya field Business pada paket Pro
bukanlah sebuah error.
Bagian internal pada tingkat sinyal tidak pernah dikembalikan, pada paket mana pun: nama masing-masing sinyal, bobotnya, ambang batas di balik sebuah verdict, nilai sinyal mentah, dan rincian skor tetap berada di sisi kami. Skor yang bisa direkayasa balik menjadi masukannya berhenti berguna sebagai pertahanan.
Setiap kegagalan memakai satu amplop:
{ "error": { "code": "unauthorized", "message": "missing Authorization: Bearer <secret key>", "request_id": "8f14e45fceea167a5a36dedd" }}request_id ini bukan pengidentifikasi kunjungan. Dua nilai berbeda berbagi nama
yang sama: di dalam payload sesi, request_id adalah UUID kunjungan, sama dengan yang
dikirim webhook; di dalam amplop error, ia adalah pengidentifikasi jejak sepanjang 24
karakter yang dibuat untuk setiap panggilan HTTP. Pengidentifikasi jejak itu juga
kembali di header X-Request-Id pada setiap respons, berhasil maupun tidak. Sertakan
nilainya saat Anda menghubungi dukungan — dari situlah kami menemukan panggilan Anda
yang persis.
| HTTP | code | Arti |
|---|---|---|
| 400 | invalid_request | Sebuah parameter hilang atau salah bentuk |
| 401 | unauthorized | Kuncinya tidak ada, tidak valid, dicabut, atau kedaluwarsa |
| 402 | upgrade_required | Paket Anda tidak mencakup akses API |
| 404 | not_found | Tidak ada yang cocok di dalam jendela retensi, atau datanya milik lingkungan lain |
| 405 | method_not_allowed | Route-nya ada, tetapi tidak untuk metode itu |
| 429 | rate_limited | Permintaan per detik, atau kuota harian, terlampaui |
| 500 | internal | Ada yang gagal di sisi kami |
| 503 | unavailable | Sebuah penyimpanan pendukung sementara tidak terjangkau |
Pemeriksaan berjalan dalam urutan tetap — kunci, lalu paket, lalu batas — sehingga
permintaan dengan kunci yang salah selalu melaporkan soal kunci lebih dulu, tidak pernah
soal kuota. Data dari workspace lain tidak dapat dibedakan dari data yang tidak ada:
hasilnya 404, bukan 403.
Dua kasus 401 sengaja dibaca berbeda: missing Authorization: Bearer <secret key>
berarti header-nya tidak pernah tiba, sedangkan invalid or revoked API key berarti ia
tiba dan tidak cocok. 402 membawa Data API requires the Pro plan or higher.
Coba ulang 429 dan 503 dengan jeda yang makin panjang; mencoba ulang 4xx lainnya
tidak ada gunanya — itu berarti permintaannya sendiri perlu diperbaiki.
Respons yang kuncinya sudah dikenali membawa posisi Anda saat ini (respons 401 dan
402 tidak, dan Enterprise, yang tanpa kuota harian, tidak mendapat header kuota):
| Header | Arti |
|---|---|
X-RateLimit-Limit | Kuota harian Anda; pada penolakan per detik, batas per detik |
X-RateLimit-Remaining | Panggilan yang tersisa hari ini |
X-RateLimit-Reset | Waktu Unix saat reset — tengah malam UTC |
Retry-After | Detik yang harus ditunggu, hanya dikirim dengan 429 — ikuti nilainya: benar untuk kedua batas |
| Paket | Permintaan per detik | Permintaan per hari | Kedalaman riwayat |
|---|---|---|---|
| Free | Tanpa akses API | — | 7 hari |
| Pro | 10 | 10.000 | 30 hari |
| Business | 50 | 100.000 | 90 hari |
| Enterprise | 200 | Tanpa penghitungan | 365 hari |