Appearance
POST /apiv2/screening
Pesan penapisan AML untuk alamat blockchain: satu bentuk respons untuk setiap penyedia dan setiap status pesanan, angka desimal sebagai string, dan satu format kesalahan tunggal.
URL Endpoint
POST https://netts.io/apiv2/screeningHeader Permintaan
| Header | Wajib | Deskripsi |
|---|---|---|
| Content-Type | Ya | application/json |
| X-API-KEY | Ya | Kunci API Anda dari dasbor Netts |
| X-Idempotency-Key | Tidak | Kunci Anda sendiri untuk percobaan ulang yang aman. Lihat Idempotensi |
Isi Permintaan
json
{
"address": "YOUR_ADDRESS_HERE",
"network": "trx",
"provider": "elliptic",
"wait_for_result": true
}Parameter Permintaan
| Parameter | Tipe | Wajib | Deskripsi |
|---|---|---|---|
| address | string | Ya | Alamat yang akan ditapis, 10–128 karakter |
| network | string | Ya | Ticker jaringan. Ticker yang dicakup oleh setiap penyedia tercantum di GET /apiv2/screening/providers |
| provider | string | Ya | elliptic atau bitok. Tidak ada nilai bawaan |
| wait_for_result | boolean | Tidak | true menunggu hasil hingga 15 detik. Bawaan false |
| language | string | Tidak | Bahasa laporan. Hanya en |
Bidang yang tidak dikenal akan ditolak. Body yang memuat bidang yang tidak tercantum dalam tabel di atas mengembalikan 400 dengan kode 4001.
provider wajib diisi dan tidak memiliki nilai bawaan. Anda selalu memilih penyedia yang Anda bayar.
provider adalah string bebas dalam skema, bukan sebuah enumerasi. Saat ini dua nilai diterima; penyedia ketiga tidak boleh menjadi perubahan yang merusak (breaking change) bagi siapa pun yang memvalidasi respons terhadap skema. Daftar saat ini, jaringan yang dicakup oleh setiap penyedia, dan skala penilaian masing-masing berasal dari GET /apiv2/screening/providers.
Contoh
cURL — tunggu hasilnya
bash
curl -X POST https://netts.io/apiv2/screening \
-H "Content-Type: application/json" \
-H "X-API-KEY: your_api_key" \
-d '{
"address": "YOUR_ADDRESS_HERE",
"network": "trx",
"provider": "elliptic",
"wait_for_result": true
}'cURL — terima dan lakukan polling
bash
curl -X POST https://netts.io/apiv2/screening \
-H "Content-Type: application/json" \
-H "X-API-KEY: your_api_key" \
-d '{
"address": "YOUR_ADDRESS_HERE",
"network": "trx",
"provider": "bitok"
}'Responsnya adalah 202 Accepted dengan header Location yang mengarah ke pesanan tersebut.
Python
python
import requests
from decimal import Decimal
url = "https://netts.io/apiv2/screening"
headers = {
"Content-Type": "application/json",
"X-API-KEY": "your_api_key",
}
payload = {
"address": "YOUR_ADDRESS_HERE",
"network": "trx",
"provider": "elliptic",
"wait_for_result": True,
}
response = requests.post(url, headers=headers, json=payload)
if response.status_code in (200, 202):
body = response.json()
print("Order:", body["order"]["client_order_id"])
print("Status:", body["order"]["status"])
if body["risk"]["score"] is not None:
# Parse provider numbers as Decimal, never as float
print("Score:", Decimal(body["risk"]["score"]), "of", body["risk"]["scale"]["max"])
print("Level:", body["risk"]["level"], "-", body["risk"]["level_source"])
print("Charged:", body["billing"]["charged_amount"], body["billing"]["charged_currency"])
else:
problem = response.json()
print(problem["code"], problem["title"], "-", problem["detail"])Kode Respons
| Situasi | Kode | Header |
|---|---|---|
| Pesanan dibuat, penapisan berjalan di latar belakang | 202 Accepted | Location: /apiv2/screening/{client_order_id} |
Hasil ada di dalam respons (wait_for_result) | 200 OK | — |
| Hasil digunakan kembali dari pemeriksaan terbaru, tidak ada biaya | 200 OK | — |
| Alamat tidak memiliki aktivitas blockchain, tidak ada biaya | 200 OK | — |
| Kesalahan | lihat Error Responses | Content-Type: application/problem+json |
Respons yang membawa hasil penapisan dikirimkan dengan Cache-Control: private, no-store.
Respons
json
{
"schema_version": 2,
"order": {
"client_order_id": "A90D21F68C9AEA2",
"status": "completed",
"api_version": "v2",
"cache_hit": false,
"created_at": "2026-09-13T08:14:29.614988Z",
"started_at": "2026-09-13T08:14:30.288251Z",
"completed_at": "2026-09-13T08:14:34.993174Z"
},
"request": {
"address": "YOUR_ADDRESS_HERE",
"network": "trx",
"provider": "elliptic"
},
"billing": {
"charged": true,
"price_usdt": "0.98",
"base_amount": "2.882421",
"markup_amount": "0",
"charged_amount": "2.882421",
"charged_currency": "TRX",
"exchange_rate": "0.33999200",
"payment_status": "pending"
},
"precheck": {
"activity_checked": true,
"activity_status": "active",
"source": "tron-address-checker"
},
"check": {
"provider": "elliptic",
"provider_check_id": "b4903a5d-9f22-4075-b51b-beb40b419b97",
"checked_at": "2026-09-13T08:14:32.144000Z",
"status": "completed",
"provider_status": "complete"
},
"risk": {
"score": "0.9634087310611608",
"scale": { "min": 0, "max": 10 },
"level": "low",
"level_source": "computed",
"provider_level": null,
"policy": "netts-risk-v1",
"by_direction": {
"source": "0.12332156899576921",
"destination": "0.9634087310611608"
}
},
"sanctions": {
"self": false,
"self_entities": null,
"exposure": {
"entity": "HTX (formerly Huobi) - Post-Sanctions - UK Sanctions List - 26 May 2026",
"category": "Exchange",
"share_fraction": "0.004409451392423414",
"proximity": "indirect",
"hops": 3,
"direction": "source",
"rule_name": "Sanctioned, TF & CSAM"
},
"items": []
},
"exposure": [
{
"category": "Exchange",
"share_fraction": "0.1888065152442461",
"direction": "source",
"hops": 2,
"is_screened_address": false,
"entities": [
{ "name": "Binance", "category": "Exchange", "is_vasp": true,
"is_primary": true, "is_after_sanction_date": null }
]
}
],
"rules": [
{ "name": "Sanctioned, TF & CSAM", "type": "exposure", "level": null,
"score": "0.061426483114820525", "share_fraction": null, "category": null,
"proximity": null, "direction": "source", "detected_at": null }
],
"entities": [
{ "name": "Unknown", "category": "Unknown", "is_vasp": null,
"is_primary": true, "is_after_sanction_date": false }
],
"primary_entity": {
"name": "Unknown", "category": "Unknown", "is_vasp": null,
"is_primary": true, "is_after_sanction_date": false
},
"sanctioned_entities": [],
"wallet": {
"inflow_usd": "354663.6116669158",
"outflow_usd": "80248.63081808022"
},
"provider_data": { }
}Kumpulan bidang tidak pernah berubah
Setiap blok yang tercantum di atas selalu ada dalam setiap respons, apa pun penyedianya dan apa pun status pesanannya. Apa yang tidak disediakan oleh penyedia bernilai null; sebuah daftar yang tidak memiliki isi bernilai [], bukan null; sebuah blok yang belum memiliki data diisi dengan null daripada dihilangkan. Satu parser menangani pemeriksaan yang baru saja diterima dan pemeriksaan yang sama setelah selesai.
Dua konsekuensi untuk kode Anda:
- abaikan bidang yang tidak Anda ketahui. Bidang baru ditambahkan ke blok-blok ini tanpa versi baru. Menolak bidang yang tidak dikenal adalah bug Anda, bukan bug kami;
provider_databukan bagian dari kontrak. Bentuknya mengikuti penyedia, dan berubah ketika penyedia berubah. Segala hal yang dijamin oleh kontrak berada di blok-blok di atas.
order
| Bidang | Tipe | Deskripsi |
|---|---|---|
| client_order_id | string | Pengidentifikasi pesanan, digunakan untuk membaca hasil nanti |
| status | string | pending, processing, completed, skipped, failed |
| api_version | string | Kontrak yang membuat pesanan |
| cache_hit | boolean | true ketika hasil terbaru digunakan kembali dan tidak ada biaya yang dikenakan |
| created_at | string | RFC 3339, UTC, mikrodetik |
| started_at | string | null | Kapan panggilan penyedia dimulai. null untuk skipped |
| completed_at | string | null | Kapan hasil tiba |
| error | string | Hanya untuk failed: alasan kegagalan |
| reason | string | Hanya untuk skipped: address_inactive |
Semua stempel waktu menggunakan UTC, RFC 3339, dengan akhiran Z dan presisi mikrodetik.
billing
| Bidang | Tipe | Deskripsi |
|---|---|---|
| charged | boolean | Apakah uang ditarik |
| price_usdt | string | Harga daftar penyedia dalam USDT |
| base_amount | string | Harga pesanan dalam mata uang yang ditagihkan, tanpa markup sub-pengguna |
| markup_amount | string | Markup sub-pengguna. "0" untuk akun langsung |
| charged_amount | string | Jumlah yang benar-benar ditarik dari saldo |
| charged_currency | string | TRX |
| exchange_rate | string | null | Kurs yang digunakan untuk konversi |
| payment_status | string | paid, pending, failed, not_charged, postpaid |
payment_status bernilai pending untuk waktu yang singkat setelah pemeriksaan berhasil: penagihan ditahan terlebih dahulu dan diselesaikan dalam waktu satu jam. failed berarti uang dikembalikan. not_charged berarti tidak ada tagihan yang pernah dibuat — hasil yang digunakan kembali atau alamat yang dilewati. postpaid — lihat Akun Pascabayar.
precheck
Sebelum penapisan berbayar, alamat diperiksa untuk aktivitas blockchain. Alamat tanpa aktivitas tidak dikirim ke penyedia dan tidak dikenakan biaya.
| Bidang | Tipe | Deskripsi |
|---|---|---|
| activity_checked | boolean | Apakah pemeriksaan dijalankan. false pada jaringan yang tidak menyediakannya |
| activity_status | string | active, inactive, unknown |
| source | string | null | Nama mekanisme |
unknown tidak menghentikan penapisan berbayar: jika layanan aktivitas tidak tersedia, alamat akan diperlakukan sebagai aktif.
check
| Bidang | Tipe | Deskripsi |
|---|---|---|
| provider | string | Penyedia yang melakukan pemeriksaan |
| provider_check_id | string | null | Pengidentifikasi milik penyedia itu sendiri — kutip ini saat mengajukan sengketa hasil dengan mereka |
| checked_at | string | null | Kapan penyedia menghasilkan hasil |
| status | string | Lihat tabel di bawah |
| provider_status | string | null | Kata-kata dari penyedia itu sendiri, tanpa diubah |
order.status | check.status | Arti |
|---|---|---|
pending | pending | Pesanan diterima, belum dimulai |
processing | running | Penyedia sedang mengerjakannya |
completed | completed | Hasil diterima |
failed | failed | Ditolak sebelum atau selama panggilan penyedia |
skipped | not_performed | Alamat tidak memiliki aktivitas; penyedia tidak pernah dipanggil dan tidak ada biaya yang dikenakan |
risk
| Bidang | Tipe | Deskripsi |
|---|---|---|
| score | string | null | Skor dari penyedia itu sendiri, sebagai string desimal |
| scale | object | min dan max dari skala penyedia tersebut |
| level | string | none, low, medium, high, severe |
| level_source | string | computed — kami mendapatkan level dari skor; provider — penyedia yang menyatakannya |
| provider_level | string | null | Kata dari penyedia itu sendiri, jika mereka mengembalikannya |
| policy | string | Nama kebijakan ambang batas, netts-risk-v1 |
| by_direction | object | Skor dipecah menjadi source dan destination, jika penyedia memecahnya |
Skor tidak pernah diskalakan ulang. Elliptic menggunakan skala 0–10 dan BitOK menggunakan 0–1, dan nilai 7 pada satu skala bukanlah 0.7 pada skala lainnya dalam arti apa pun yang bermakna. Skala disertakan dalam respons sehingga integrasi yang ditulis untuk satu penyedia tidak salah membaca penyedia lain setelah satu perubahan konfigurasi.
Level adalah satu kosakata di seluruh API. Jika penyedia menyatakan levelnya sendiri, kami meneruskannya dan menyatakannya di level_source; jika tidak, kami menurunkan level dari skor dengan ambang batas netts-risk-v1 dan menyatakan hal tersebut. Kata yang sama muncul di respons API, dasbor, dan laporan PDF untuk pemeriksaan yang sama.
exposure[], rules[], entities[]
exposure[] merinci dana berdasarkan kategori pihak lawan (counterparty). rules[] mencantumkan aturan penyedia yang terpicu. entities[] mencantumkan entitas tempat alamat itu sendiri berada; primary_entity memilih salah satunya berdasarkan aturan tetap — entitas yang ditandai penyedia sebagai utama, jika tidak ada maka entitas pertama, selain itu null. sanctioned_entities[] menampung entitas dari entities[] yang ditandai aktif setelah tanggal sanksi.
Porsi adalah pecahan, tidak pernah persentase
Setiap porsi dalam respons adalah bidang tunggal, share_fraction, berupa string desimal antara "0" dan "1".
text
Elliptic reports 31.574732212596924 % -> "share_fraction": "0.31574732212596924"
BitOK reports 0.8488 -> "share_fraction": "0.8488"Penyedia tidak sepakat mengenai satuan: sepertiga paparan yang sama datang sebagai 31.57 dari satu penyedia dan 0.3157 dari penyedia lainnya. Satu bidang yang memuat keduanya akan mustahil dibaca tanpa mengetahui penyedianya. Angka milik penyedia itu sendiri dalam satuan milik penyedia itu sendiri tetap berada di provider_data.
Angka adalah string
Setiap angka yang berasal dari penyedia — skor, porsi, volume USD, dan setiap jumlah dalam billing — adalah string desimal.
json
"score": "0.9634087310611608"Mem-parsing nilai tersebut sebagai angka JSON di JavaScript, Go, atau bahasa lain apa pun dengan titik mengambang biner (binary floating point) akan menghasilkan nilai perkiraan, dan nilai yang Anda cetak tidak lagi sesuai dengan nilai yang dikeluarkan penyedia. Parsing bidang-bidang ini dengan tipe desimal: Decimal di Python, BigDecimal di Java, decimal.Decimal atau string di JavaScript.
Bidang yang merupakan milik kami dan bukan milik penyedia — scale.min, scale.max, hops — adalah angka JSON biasa.
Menggunakan kembali hasil terbaru
Ketika Anda menapis alamat, jaringan, dan penyedia yang sama lagi dalam 60 detik, hasil sebelumnya akan dikembalikan dan tidak ada biaya yang dikenakan.
Setiap permintaan tetap membuat pesanannya sendiri dengan client_order_id miliknya sendiri; yang digunakan kembali ditandai "cache_hit": true dan blok billing-nya melaporkan "charged": false dengan "payment_status": "not_charged". Pengidentifikasi pesanan asal hasil tersebut tidak diungkapkan — itu mungkin milik akun lain.
Penggunaan kembali hanya terjadi dalam satu akun. Hasil yang ditapis oleh orang lain tidak pernah dikembalikan kepada Anda.
Idempotensi
Kirimkan X-Idempotency-Key dengan nilai Anda sendiri untuk membuat percobaan ulang aman: kunci yang sama dengan body yang sama mengembalikan respons yang tersimpan alih-alih memesan pemeriksaan kedua.
| Situasi | Kode | Respons |
|---|---|---|
| Permintaan pertama dengan kunci ini masih berjalan | 409 | 4090 |
| Kunci yang sama, body permintaan berbeda | 409 | 4093 |
| Kunci yang sama, body yang sama, sudah selesai | kode yang tersimpan | respons yang tersimpan |
Jika Anda tidak mengirimkan header tersebut, kunci akan dibuatkan untuk Anda dari kunci API, alamat, penyedia, dan alamat IP Anda, dalam rentang waktu dua detik. Ini melindungi dari klik ganda dan percobaan ulang gateway, bukan dari pengulangan satu menit kemudian: yang itu adalah pesanan baru yang sebenarnya dan dikenakan biaya.
Error Responses
Setiap kesalahan yang dimunculkan oleh aplikasi menggunakan RFC 9457 dengan Content-Type: application/problem+json:
json
{
"type": "https://doc.netts.io/api/v2/errors/insufficient-funds",
"title": "Insufficient funds",
"status": 403,
"detail": "Insufficient funds. Required: 2.888742 TRX, Available: 1.203000 TRX",
"instance": "/apiv2/screening",
"code": 1004,
"required_trx": "2.888742",
"available_trx": "1.203000"
}type, title, status, detail, dan instance adalah bidang standar. code numerik adalah ekstensi: cocokkan penanganan kesalahan Anda padanya. Bidang tambahan bergantung pada kesalahannya dan harus diabaikan jika Anda tidak mengetahuinya.
| Kode | HTTP | Arti |
|---|---|---|
4000 | 400 | Body bukan JSON yang valid |
4001 | 400 | Bidang gagal validasi, atau bidang yang tidak dikenal terkirim |
4002 | 403 | Penyedia tidak tersedia untuk akun Anda |
4003 | 400 | Pengidentifikasi pesanan salah bentuk |
4004 | 400 | Penyedia tidak mendukung jaringan yang diminta |
4010 | 401 | Tidak ada kunci API |
4011 | 401 | Kunci API atau alamat IP tidak diterima |
4040 | 404 | Pesanan tidak ditemukan |
4041 | 404 | Akun tidak ditemukan |
4090 | 409 | Permintaan dengan kunci idempotensi ini masih berjalan |
4091 | 409 | Permintaan duplikat |
4093 | 409 | Kunci idempotensi ini digunakan dengan body yang berbeda |
1004 | 403 | Saldo tidak mencukupi |
5000 | 500 | Kesalahan internal |
5001 | 500 | Penagihan tidak berhasil |
5002 | 500 | Pesanan tidak dibuat |
5030 | 503 | Penyedia tidak tersedia |
Kesalahan yang tidak menggunakan format ini
Beberapa kegagalan terjadi di gateway, sebelum mencapai aplikasi, dan kegagalan tersebut mempertahankan bentuk milik gateway itu sendiri. Perlakukan respons apa pun yang Content-Type-nya bukan application/problem+json sebagai salah satu dari ini:
| Situasi | HTTP | Body |
|---|---|---|
| Tidak ada kunci API, atau kunci yang tidak diterima | 401 | {"detail":{"code":-1,"msg":"Invalid or missing API key"}} |
| Batas laju terlampaui | 429 | {"message":"API rate limit exceeded"} |
| Jalur tidak dikenal, atau metode yang tidak dilayani oleh rute | 404 / 405 | {"detail":"Method Not Allowed"} |
Batas Tarif
5 permintaan per detik dan 150 per menit, digunakan bersama oleh semua jalur penapisan.
Akun Pascabayar
Akun dengan penagihan pascabayar menggunakan endpoint, URL, header, dan body permintaan yang sama dengan yang lainnya. Perbedaannya adalah cara pembayaran pemeriksaan:
- Tidak ada yang dipotong dari deposit Anda. Harga setiap pemeriksaan yang selesai dalam dolar AS (misalnya, $0.98 untuk Elliptic) ditambahkan ke saldo terutang akun Anda dalam mata uang penyelesaian yang disepakati dalam kontrak Anda. Anda membayarnya melalui faktur, sesuai dengan perjanjian Anda.
- Akun Anda memiliki batas kredit. Selama jumlah terutang berada dalam batas tersebut, pemeriksaan tetap diterima bahkan dengan deposit nol.
- Hanya pemeriksaan yang selesai yang ditagih. Pemeriksaan yang gagal, alamat tanpa aktivitas (
skipped), dan hasil terbaru yang digunakan kembali tidak dikenakan biaya.
Penagihan pascabayar diaktifkan oleh Netts untuk akun berdasarkan permintaan.
billing dari pemeriksaan pascabayar
json
"billing": {
"charged": false,
"price_usdt": "0.98",
"base_amount": "2.960725",
"markup_amount": "0",
"charged_amount": "2.960725",
"charged_currency": "TRX",
"exchange_rate": "0.33100000",
"payment_status": "postpaid"
}| Bidang | Deskripsi |
|---|---|
| charged | false: tidak ada yang diambil dari deposit |
| price_usdt | Harga pemeriksaan dalam dolar AS. Ini adalah jumlah yang ditambahkan ke saldo terutang Anda |
| charged_amount | Harga yang sama dalam TRX, sebagai referensi |
| payment_status | postpaid. Untuk pemeriksaan yang gagal atau dilewati — not_charged |
Batas kredit tercapai (402)
json
{
"type": "https://doc.netts.io/api/v2/errors/credit-limit-reached",
"title": "Postpaid credit limit reached",
"status": 402,
"detail": "Postpaid credit limit reached.",
"instance": "/apiv2/screening",
"code": 1004,
"payment_mode": "postpaid",
"reason": "limit_reached"
}Pemeriksaan tidak dipesan dan tidak ada yang ditagih. Pemeriksaan baru diterima kembali setelah pembayaran Anda terdaftar atau batas kredit Anda dinaikkan.
Kode kesalahan pascabayar
| Kode | HTTP | Deskripsi |
|---|---|---|
1004 | 402 | Batas kredit pascabayar tercapai |
5032 | 503 | Harga sementara tidak tersedia |
5034 | 503 | Penagihan sementara tidak tersedia — pemeriksaan tidak diterima |
5036 | 503 | Pemeriksaan kredit sementara tidak tersedia — coba lagi nanti |
Untuk semua respons di atas, tidak ada yang dipesan dan tidak ada yang ditagih.
Catatan
- Penetapan Harga: harga tetap per pemeriksaan untuk setiap penyedia, lihat GET /apiv2/screening/providers; ditagih dari saldo TRX dengan kurs pada saat penagihan.
- Waktu pemrosesan: sebagian besar pemeriksaan selesai dalam beberapa detik; alamat dengan riwayat yang panjang dapat memakan waktu hingga tiga menit. Gunakan mode asinkron dan baca hasilnya dengan GET /apiv2/screening/{client_order_id}.
- Alamat tidak aktif mengembalikan
skippeddan tidak dikenakan biaya. - Respons penyedia mentah tidak pernah dikembalikan.
provider_dataadalah proyeksi yang telah ditinjau; bidang yang menjadi milik akun kami dengan penyedia dan bukan milik alamat yang ditapis tidak dipublikasikan kepada siapa pun.
Laporan
Endpoint ini mengembalikan JSON dan tidak ada yang lain. Tidak ada PDF dan tidak ada Markdown.
Semua bagian pembentuk laporan sudah ada di dalam respons: blok terpadu dan provider_data. Merendernya di sisi Anda memberi Anda dokumen yang benar-benar Anda inginkan — merek Anda, bahasa Anda, tata letak Anda — yang sangat penting terutama jika Anda menjual kembali pemeriksaan, karena laporan yang memuat nama kami adalah dokumen yang salah untuk diserahkan kepada pelanggan Anda sendiri.
Jika Anda memerlukan laporan sebagai bukti untuk pihak ketiga — bank, regulator, pihak lawan — perhatikan bahwa PDF yang tidak ditandatangani bukanlah bukti siapa pun yang membuatnya: dokumen tersebut dapat diedit di editor teks dalam satu menit. Artefak yang dapat diverifikasi membutuhkan tanda tangan atau halaman verifikasi publik, dan itu adalah fitur yang berbeda. Jika itu masalah Anda, beri tahu kami apa yang diwajibkan oleh pihak lawan Anda.
Laporan PDF yang dapat dibaca manusia memang ada untuk pemeriksaan yang sama di dasbor Netts, dalam tujuh belas bahasa.
Lihat Juga
- GET /apiv2/screening/{client_order_id} — baca pemeriksaan
- GET /apiv2/screening/history — pemeriksaan Anda, dengan paginasi kursor
- GET /apiv2/screening/providers — penyedia, harga, jaringan, skala
- GET /apiv2/screening/price — harga dari satu penyedia
- Sanctions in an AML result — apa yang dinyatakan
sanctionsdan apa yang dinyatakan tanda penyedia