Skip to content
This translation is behind the English original, updated 2026-09-15. Read the English version for the current text.

POST /apiv2/screening

Pesan penapisan (screening) AML untuk alamat blockchain. Ini adalah kontrak versi 2: satu bentuk respons untuk setiap penyedia dan setiap status pesanan, angka desimal sebagai string, dan format kesalahan tunggal.

Metode ini menggantikan POST /apiv2/aml, yang tetap berfungsi dan tidak akan dihapus tanpa pemberitahuan.

URL Endpoint

POST https://netts.io/apiv2/screening

Header Permintaan

HeaderWajibDeskripsi
Content-TypeYaapplication/json
X-API-KEYYaKunci API Anda dari dasbor Netts
X-Idempotency-KeyTidakKunci Anda sendiri untuk pengulangan (retry) yang aman. Lihat Idempotensi

Isi Permintaan

json
{
    "address": "YOUR_ADDRESS_HERE",
    "network": "trx",
    "provider": "elliptic",
    "wait_for_result": true
}

Parameter

ParameterTipeWajibDeskripsi
addressstringYaAlamat yang akan ditapis, 10–128 karakter
networkstringYaTicker jaringan. Ticker yang dicakup oleh masing-masing penyedia dicantumkan oleh GET /apiv2/screening/providers; tabel lengkap jaringan beserta namanya ada di sini
providerstringYaelliptic atau bitok. Tidak ada nilai default
wait_for_resultbooleanTidaktrue menunggu hasil hingga 15 detik. Default false
languagestringTidakBahasa laporan. Hanya en

Field yang tidak dikenal akan ditolak. Body yang memuat field yang tidak ada dalam tabel di atas akan mengembalikan 400 dengan kode 4001. Pada versi 1 field yang tidak dikenal diabaikan secara diam-diam, dan kesalahan ketik pada wait membuat pemanggil menunggu hasil yang tidak akan pernah tiba secara sinkron.

provider wajib diisi dan tidak memiliki nilai default. Pada versi 1 penyedia yang diabaikan berarti Elliptic, sehingga pemanggil yang tidak memilih tetap membayar untuk penyedia yang tidak pernah mereka sebutkan.

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 saja yang memvalidasi respons terhadap skema. Daftar saat ini, jaringan yang dicakup masing-masing penyedia, dan skala penilaian masing-masing penyedia berasal dari GET /apiv2/screening/providers.

Contoh Permintaan

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

SituasiKodeHeader
Pesanan dibuat, penapisan berjalan di latar belakang202 AcceptedLocation: /apiv2/screening/{client_order_id}
Hasil ada di dalam respons (wait_for_result)200 OK
Hasil digunakan kembali dari pemeriksaan baru-baru ini, tidak ada biaya200 OK
Alamat tidak memiliki aktivitas blockchain, tidak ada biaya200 OK
Kesalahanlihat KesalahanContent-Type: application/problem+json

Respons yang membawa hasil penapisan dikirim 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 field tidak pernah berubah

Setiap blok yang tercantum di atas selalu ada dalam setiap respons, apa pun penyedianya dan apa pun status pesanannya. Data yang tidak disediakan oleh penyedia bernilai null; daftar yang kosong bernilai [], bukan null; blok yang belum memiliki data diisi dengan nilai null daripada dihilangkan. Satu parser dapat menangani pemeriksaan yang baru saja diterima maupun pemeriksaan yang sama setelah selesai.

Dua konsekuensi untuk kode Anda:

  • abaikan field yang tidak Anda ketahui. Field baru ditambahkan ke blok-blok ini tanpa versi baru. Menolak field yang tidak dikenal adalah kesalahan di sisi Anda, bukan kami;
  • provider_data bukan bagian dari kontrak. Strukturnya mengikuti penyedia, dan berubah saat penyedia berubah. Segala hal yang dijamin oleh kontrak berada di blok-blok di atas.

order

FieldTipeDeskripsi
client_order_idstringPengidentifikasi pesanan, digunakan untuk membaca hasil nanti
statusstringpending, processing, completed, skipped, failed
api_versionstringKontrak yang membuat pesanan
cache_hitbooleantrue ketika hasil terbaru digunakan kembali dan tidak ada biaya yang dikenakan
created_atstringRFC 3339, UTC, mikrodetik
started_atstring | nullSaat pemanggilan ke penyedia dimulai. null untuk skipped
completed_atstring | nullSaat hasil diterima
errorstringHanya untuk failed: alasan kegagalan
reasonstringHanya untuk skipped: address_inactive

Semua stempel waktu menggunakan UTC, RFC 3339, dengan akhiran Z dan presisi mikrodetik.

billing

FieldTipeDeskripsi
chargedbooleanApakah saldo dipotong
price_usdtstringHarga resmi (list price) penyedia dalam USDT
base_amountstringHarga pesanan dalam mata uang yang ditagihkan, tanpa markup sub-pengguna
markup_amountstringMarkup sub-pengguna. "0" untuk akun langsung
charged_amountstringJumlah yang sebenarnya dipotong dari saldo
charged_currencystringTRX
exchange_ratestring | nullKurs yang digunakan untuk konversi
payment_statusstringpaid, pending, failed, not_charged

payment_status bernilai pending untuk waktu singkat setelah pemeriksaan berhasil: biaya awalnya ditahan dan diselesaikan dalam waktu satu jam. failed berarti dana telah dikembalikan. not_charged berarti tagihan tidak pernah dibuat — hasil yang digunakan kembali atau alamat yang dilewati.

precheck

Sebelum penapisan berbayar, alamat diperiksa aktivitas blockchain-nya. Alamat tanpa aktivitas tidak dikirim ke penyedia dan tidak dikenakan biaya.

FieldTipeDeskripsi
activity_checkedbooleanApakah pemeriksaan dijalankan. false pada jaringan di mana fitur ini tidak ada
activity_statusstringactive, inactive, unknown
sourcestring | nullNama mekanisme

unknown tidak menghentikan penapisan berbayar: jika layanan aktivitas tidak tersedia, alamat akan diperlakukan sebagai aktif.

check

FieldTipeDeskripsi
providerstringPenyedia yang melakukan pemeriksaan
provider_check_idstring | nullPengidentifikasi milik penyedia itu sendiri — sebutkan ini saat menyanggah hasil kepada mereka
checked_atstring | nullKapan penyedia menghasilkan hasil tersebut
statusstringLihat tabel di bawah
provider_statusstring | nullRedaksi asli dari penyedia, tanpa perubahan
order.statuscheck.statusArti
pendingpendingPesanan diterima, belum dimulai
processingrunningPenyedia sedang memprosesnya
completedcompletedHasil diterima
failedfailedDitolak sebelum atau selama panggilan ke penyedia
skippednot_performedAlamat tidak memiliki aktivitas; penyedia tidak pernah dipanggil dan tidak ada biaya

risk

FieldTipeDeskripsi
scorestring | nullSkor milik penyedia itu sendiri, sebagai string desimal
scaleobjectNilai min dan max dari skala penyedia tersebut
levelstringnone, low, medium, high, severe
level_sourcestringcomputed — kami menetapkan level dari skor; provider — penyedia yang menyatakannya
provider_levelstring | nullIstilah milik penyedia itu sendiri, jika menyediakannya
policystringNama kebijakan ambang batas (threshold), netts-risk-v1
by_directionobjectSkor yang dipecah menjadi source dan destination, jika penyedia memecahnya

Skor tidak pernah diskalakan ulang. Elliptic berjalan pada 0–10 dan BitOK berjalan pada 0–1, dan nilai 7 pada satu skala bukanlah 0.7 pada skala lainnya dalam arti apa pun yang bermakna. Skala disertakan dalam respons agar integrasi yang ditulis untuk satu penyedia tidak salah membaca penyedia lain setelah adanya perubahan konfigurasi tunggal.

Tingkat (level) menggunakan satu kosakata di seluruh API. Di mana penyedia menyatakan levelnya sendiri, kami meneruskannya dan menyatakannya di level_source; jika tidak, kami menetapkan 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[] memecah 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 yang pertama, jika tidak ada maka null. sanctioned_entities[] menampung entitas dari entities[] yang ditandai aktif setelah tanggal sanksi.

Porsi adalah pecahan, bukan persentase

Setiap porsi dalam respons adalah satu field tunggal, share_fraction, sebuah string desimal antara "0" dan "1".

text
Elliptic melaporkan 31.574732212596924 %  ->  "share_fraction": "0.31574732212596924"
BitOK melaporkan    0.8488                ->  "share_fraction": "0.8488"

Penyedia memiliki perbedaan satuan: sepertiga exposure yang sama muncul sebagai 31.57 dari satu pihak dan 0.3157 dari pihak lainnya. Field tunggal yang memuat keduanya tidak mungkin dibaca tanpa mengetahui penyedianya. Angka milik penyedia dalam satuannya 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 dengan floating point biner akan menghasilkan nilai perkiraan, dan nilai yang Anda cetak tidak lagi cocok dengan nilai yang dikeluarkan penyedia. Parsing field-field ini dengan tipe desimal: Decimal di Python, BigDecimal di Java, decimal.Decimal atau string di JavaScript.

Field 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 masing-masing; hasil 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 — data tersebut mungkin milik akun lain.

Penggunaan kembali hanya terjadi dalam satu akun. Hasil yang ditapis oleh pihak lain tidak akan pernah dikembalikan kepada Anda.

Idempotensi

Kirim X-Idempotency-Key dengan nilai milik Anda sendiri untuk membuat percobaan ulang (retry) menjadi aman: kunci yang sama dengan body yang sama akan mengembalikan respons yang tersimpan alih-alih memesan pemeriksaan kedua.

SituasiKodeRespons
Permintaan pertama dengan kunci ini masih berjalan4094090
Kunci yang sama, body permintaan yang berbeda4094093
Kunci yang sama, body yang sama, sudah selesaikode yang tersimpanrespons yang tersimpan

Jika Anda tidak mengirimkan header tersebut, sebuah kunci akan dibuatkan untuk Anda dari kunci API, alamat, penyedia, dan alamat IP Anda, dalam jangka waktu dua detik. Kunci ini melindungi dari klik ganda dan pengulangan gateway, bukan dari pengulangan satu menit kemudian: permintaan yang terakhir adalah pesanan baru yang sesungguhnya dan dikenakan biaya.

Kunci dicakup per endpoint. Nilai yang sama yang dikirim ke POST /apiv2/aml dan ke endpoint ini adalah dua janji independen mengenai dua permintaan yang berbeda — bodynya berbeda, begitu pula responsnya. Menggunakan kembali kunci Anda saat memindahkan integrasi dari versi 1 ke versi 2 adalah aman: ini tidak mengembalikan respons versi 1 maupun dihitung sebagai kunci yang sama yang digunakan dengan body berbeda.

Kesalahan

Setiap kesalahan yang dihasilkan 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 field standar. Nilai numerik code dipertahankan sebagai ekstensi agar integrasi yang ditulis untuk versi 1 dapat terus mencocokkannya. Field tambahan bergantung pada jenis kesalahan dan harus diabaikan jika Anda tidak mengetahuinya.

KodeHTTPArti
4000400Body bukan JSON yang valid
4001400Ada field yang gagal divalidasi, atau field yang tidak dikenal terkirim
4002403Penyedia tidak tersedia untuk akun Anda
4003400Pengidentifikasi pesanan tidak sesuai format
4004400Penyedia tidak mendukung jaringan yang diminta
4010401Tidak ada kunci API
4011401Kunci API atau alamat IP tidak diterima
4040404Pesanan tidak ditemukan
4041404Akun tidak ditemukan
4090409Permintaan dengan kunci idempotensi ini masih berjalan
4091409Permintaan duplikat
4093409Kunci idempotensi ini digunakan dengan body yang berbeda
1004403Saldo tidak mencukupi
5000500Kesalahan internal
5001500Pemotongan biaya gagal diproses
5002500Pesanan tidak terbuat
5030503Penyedia tidak tersedia

Kesalahan yang tidak menggunakan format ini

Beberapa kegagalan terjadi di tingkat gateway, sebelum mencapai aplikasi, dan kegagalan tersebut tetap memakai format bawaan gateway. Perlakukan respons apa pun yang Content-Type-nya bukan application/problem+json sebagai salah satu dari kondisi berikut:

SituasiHTTPBody
Tidak ada kunci API, atau kunci tidak diterima401{"detail":{"code":-1,"msg":"Invalid or missing API key"}}
Batas laju terlampaui429{"message":"API rate limit exceeded"}
Path tidak diketahui, atau metode yang tidak dilayani oleh rute tersebut404 / 405{"detail":"Method Not Allowed"}

Batas Laju

Batas ini digunakan bersama dengan POST /apiv2/aml dan path AML lainnya: 5 permintaan per detik dan 150 per menit. Beralih ke endpoint ini tidak memberi Anda kuota tambahan kedua.

Catatan

  • Harga: Elliptic $0.98, BitOK $0.50 per pemeriksaan, dipotong dari saldo TRX sesuai kurs pada saat pemotongan biaya.
  • Waktu pemrosesan: sebagian besar pemeriksaan selesai dalam beberapa detik; alamat dengan riwayat transaksi panjang dapat memakan waktu hingga tiga menit. Gunakan mode asinkron dan baca hasilnya dengan GET /apiv2/screening/{client_order_id}.
  • Alamat tidak aktif mengembalikan skipped dan tidak dikenakan biaya.
  • Respons mentah penyedia tidak pernah dikembalikan. provider_data adalah proyeksi yang telah ditinjau; field milik akun kami di sisi penyedia dan bukan milik alamat yang ditapis tidak akan dipublikasikan kepada siapa pun.

Laporan

Endpoint ini mengembalikan JSON dan tidak ada format lainnya. Tidak tersedia PDF maupun Markdown.

Semua bagian pembentuk laporan sudah ada di dalam respons: blok yang telah disatukan dan provider_data. Melakukan rendering di sisi Anda akan memberikan dokumen yang benar-benar Anda inginkan — branding Anda, bahasa Anda, tata letak Anda — hal ini sangat relevan jika Anda menjual kembali hasil pemeriksaan, karena laporan yang memuat nama kami bukanlah dokumen yang tepat untuk diserahkan ke pelanggan Anda sendiri.

Jika Anda memerlukan laporan sebagai bukti untuk pihak ketiga — bank, regulator, mitra transaksi — perlu diingat bahwa PDF yang tidak ditandatangani bukanlah bukti sah siapa pun yang membuatnya: dokumen tersebut dapat diubah di editor teks dalam satu menit. Artefak yang dapat diverifikasi memerlukan tanda tangan digital atau halaman verifikasi publik, dan itu adalah fitur yang berbeda. Jika itu kebutuhan Anda, beri tahu kami apa saja yang disyaratkan oleh mitra transaksi Anda.

Laporan PDF yang dapat dibaca manusia memang tersedia untuk pemeriksaan yang sama di dasbor Netts, dalam tujuh belas bahasa.

Lihat Juga