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

Замовте AML-перевірку блокчейн-адреси. Це контракт версії 2: однакова структура відповіді для кожного провайдера та будь-якого стану замовлення, десяткові числа у вигляді рядків і єдиний формат помилок.

Він замінює POST /apiv2/aml, який продовжує працювати і не буде вимкнений без попередження.

URL кінцевої точки

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

Заголовки запиту

ЗаголовокОбов'язковийОпис
Content-TypeТакapplication/json
X-API-KEYТакВаш API-ключ із панелі керування Netts
X-Idempotency-KeyНіВаш власний ключ для безпечних повторних спроб. Див. Ідемпотентність

Тіло запиту

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

Параметри

ПараметрТипОбов'язковийОпис
addressstringТакАдреса для перевірки, від 10 до 128 символів
networkstringТакТікер мережі. Тікери, які підтримує кожен провайдер, наведено у списку GET /apiv2/screening/providers; повна таблиця мереж з їхніми назвами доступна тут
providerstringТакelliptic або bitok. Значення за замовчуванням відсутнє
wait_for_resultbooleanНіtrue очікує на результат до 15 секунд. За замовчуванням false
languagestringНіМова звіту. Лише en

Невідомі поля відхиляються. Тіло запиту, що містить поле, якого немає в таблиці вище, повертає 400 з кодом 4001. У версії 1 невідомі поля мовчки ігнорувалися, і помилка в написанні wait означала, що клієнт чекав на результат, який ніколи не міг надійти синхронно.

Поле provider є обов'язковим і не має значення за замовчуванням. У версії 1 пропущений провайдер означав Elliptic, тому клієнт, який не зробив вибір, сплачував за провайдера, якого взагалі не вказував.

provider є довільним рядком у схемі, а не переліком (enum). Наразі приймаються два значення; додавання третього провайдера не повинно стати критичною зміною (breaking change) для тих, хто валідує відповіді за схемою. Актуальний перелік, мережі, які підтримує кожен провайдер, та шкали їхніх оцінок повертаються у GET /apiv2/screening/providers.

Приклади запитів

cURL — очікування результату

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 — прийняття в обробку та опитування

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"
  }'

Відповідь — 202 Accepted із заголовком Location, що вказує на замовлення.

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"])

Коди відповідей

СитуаціяКодЗаголовки
Замовлення створено, перевірка виконується у фоновому режимі202 AcceptedLocation: /apiv2/screening/{client_order_id}
Результат міститься у відповіді (wait_for_result)200 OK
Результат використано повторно з нещодавньої перевірки, кошти не списувалися200 OK
Адреса не має активності в блокчейні, кошти не списувалися200 OK
Помилкадив. ПомилкиContent-Type: application/problem+json

Відповіді, що містять результат перевірки, надсилаються з Cache-Control: private, no-store.

Відповідь

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": { }
}

Набір полів ніколи не змінюється

Кожен блок, наведений вище, присутній у будь-якій відповіді, незалежно від провайдера та стану замовлення. Дані, які провайдер не надає, повертаються як null; список, у якому немає елементів, повертається як [], а не null; блок, для якого ще немає даних, заповнюється значеннями null, а не опускається. Один і той самий парсер обробляє перевірку, яка щойно була прийнята, і ту саму перевірку після її завершення.

Два важливих правила для вашого коду:

  • ігноруйте незнайомі поля. Нові поля додаються до цих блоків без випуску нової версії API. Відхилення невідомого поля — це помилка на вашому боці, а не на нашому;
  • provider_data не є частиною контракту. Його структура відповідає даним провайдера і змінюється зі зміною провайдера. Усе, що гарантується контрактом, міститься у вищенаведених блоках.

order

ПолеТипОпис
client_order_idstringІдентифікатор замовлення, використовується для подальшого отримання результату
statusstringpending, processing, completed, skipped, failed
api_versionstringКонтракт, за допомогою якого було створено замовлення
cache_hitbooleantrue, якщо було повторно використано нещодавній результат і кошти не списувалися
created_atstringRFC 3339, UTC, мікросекунди
started_atstring | nullЧас початку виклику провайдера. null для skipped
completed_atstring | nullЧас отримання результату
errorstringТільки для failed: причина невдачі
reasonstringТільки для skipped: address_inactive

Усі часові мітки наведено в UTC, форматі RFC 3339, із суфіксом Z та точністю до мікросекунд.

billing

ПолеТипОпис
chargedbooleanЧи було списано кошти
price_usdtstringБазова вартість перевірки провайдера в USDT
base_amountstringВартість замовлення у валюті списання без націнки субкористувача
markup_amountstringНацінка субкористувача. "0" для прямого акаунта
charged_amountstringСума, фактично списана з балансу
charged_currencystringTRX
exchange_ratestring | nullКурс, використаний для конвертації
payment_statusstringpaid, pending, failed, not_charged

payment_status має значення pending протягом короткого часу після успішної перевірки: сума списання спочатку блокується і остаточно списується протягом години. failed означає, що кошти було повернено. not_charged означає, що списання взагалі не створювалося — через повторне використання результату або пропуск неактивної адреси.

precheck

Перед платною перевіркою адреса перевіряється на наявність активності в блокчейні. Адреса без активності не надсилається провайдеру, і кошти за неї не списуються.

ПолеТипОпис
activity_checkedbooleanЧи запускалася попередня перевірка. false для мереж, де вона не підтримується
activity_statusstringactive, inactive, unknown
sourcestring | nullНазва механізму перевірки

Статус unknown не зупиняє платну перевірку: якщо сервіс визначення активності недоступний, адреса вважається активною.

check

ПолеТипОпис
providerstringПровайдер, який виконав перевірку
provider_check_idstring | nullВласний ідентифікатор провайдера — вказуйте його під час оскарження результату перед провайдером
checked_atstring | nullЧас формування результату провайдером
statusstringДив. таблицю нижче
provider_statusstring | nullОригінальний статус провайдера без змін
order.statuscheck.statusЗначення
pendingpendingЗамовлення прийнято, обробку ще не розпочато
processingrunningПровайдер обробляє запит
completedcompletedРезультат отримано
failedfailedЗапит відхилено до або під час звернення до провайдера
skippednot_performedАдреса не має активності; запит до провайдера не виконувався, кошти не списувалися

risk

ПолеТипОпис
scorestring | nullВласна оцінка провайдера у вигляді десяткового рядка
scaleobjectmin та max шкали відповідного провайдера
levelstringnone, low, medium, high, severe
level_sourcestringcomputed — рівень розраховано нашою системою на основі оцінки; provider — рівень надано провайдером
provider_levelstring | nullВласне позначення провайдера, якщо воно повертається
policystringНазва політики порогових значень, netts-risk-v1
by_directionobjectОцінка, розділена на source та destination, якщо провайдер надає такий поділ

Оцінка ніколи не перераховується під іншу шкалу. Elliptic використовує діапазон 0–10, а BitOK — 0–1, і значення 7 за однією шкалою не є еквівалентним 0.7 за іншою в практичному сенсі. Шкала повертається у відповіді для того, щоб інтеграція, налаштована на одного провайдера, не інтерпретувала хибно дані іншого після звичайної зміни конфігурації.

Рівень ризику уніфіковано в межах усього API. Якщо провайдер повертає власний рівень, ми передаємо його без змін і позначаємо це в level_source; якщо ні, ми вираховуємо рівень на основі оцінки за пороговими значеннями netts-risk-v1 і вказуємо відповідне джерело. Одне й те саме слово відображається у відповіді API, панелі керування та PDF-звіті для однієї і тієї ж перевірки.

exposure[], rules[], entities[]

exposure[] розподіляє кошти за категоріями контрагентів. rules[] містить перелік спрацьованих правил провайдера. entities[] містить організації, до яких належить сама адреса; primary_entity обирає одну з них за фіксованим правилом — організація, яку провайдер позначив як основну, інакше перша зі списку, інакше null. sanctioned_entities[] містить ті сутності з entities[], які позначено як активні після дати введення санкцій.

Частки виражаються дробами, а не відсотками

Кожна частка у відповіді міститься в єдиному полі share_fraction — десятковому рядку зі значенням від "0" до "1".

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

Провайдери використовують різні одиниці вимірювання: одна й та сама третина зв'язків надходить як 31.57 від одного та як 0.3157 від іншого. Одне поле, що повертало б такі різні формати, неможливо було б коректно інтерпретувати без знання конкретного провайдера. Початкове число в одиницях вимірювання провайдера залишається в provider_data.

Числа повертаються як рядки

Кожне числове значення від провайдера — оцінки, частки, обсяги в USD, а також будь-яка сума в блоці billing — передається як десятковий рядок.

json
"score": "0.9634087310611608"

Його парсинг як числового типу JSON у JavaScript, Go чи будь-якій іншій мові з двійковою плаваючою комою повертає наближене значення, через що виведене число перестає збігатися зі значенням, яке повернув провайдер. Використовуйте для обробки цих полів типи для точних десяткових чисел: Decimal у Python, BigDecimal у Java, decimal.Decimal або звичайний рядок у JavaScript.

Поля, що формуються нашою платформою, а не провайдером — scale.min, scale.max, hops — є звичайними числами JSON.

Повторне використання нещодавнього результату

Якщо ви повторно перевіряєте ту саму адресу, мережу та провайдера протягом 60 секунд, вам повертається попередній результат, і кошти не списуються.

Кожен запит усе одно створює власне замовлення зі своїм client_order_id; повторно використане замовлення позначається "cache_hit": true, а його блок billing повертає "charged": false зі значенням "payment_status": "not_charged". Ідентифікатор початкового замовлення, з якого взято результат, не розголошується — він може належати іншому акаунту.

Повторне використання діє лише в межах одного акаунта. Результат перевірки, виконаної кимось іншим, ніколи не повернеться до вас.

Idempotency

Надсилайте заголовок X-Idempotency-Key із власним унікальним значенням для безпечного повторення запитів: однаковий ключ з однаковим тілом запиту повертає збережену відповідь замість запуску другого замовлення.

СитуаціяКодВідповідь
Перший запит із цим ключем ще виконується4094090
Той самий ключ, але інше тіло запиту4094093
Той самий ключ, те саме тіло, виконання вже завершенозбережений кодзбережена відповідь

Якщо ви не надсилаєте цей заголовок, ключ генерується автоматично на основі API-ключа, адреси, провайдера та вашої IP-адреси з 2-секундним вікном. Це захищає від подвійного натискання та повторних запитів шлюзу, але не від повторного запиту через хвилину: такий запит вважатиметься новим замовленням і буде тарифікований.

Ключі діють виключно в межах окремого ендпоінта. Одне й те саме значення, надіслане до POST /apiv2/aml і до цього ендпоінта, розглядається як дві незалежні дії для двох різних запитів — тіла запитів відрізняються, як і відповіді на них. Повторне використання ключа під час міграції інтеграції з версії 1 на версію 2 безпечне: воно не поверне вам відповідь версії 1 і не буде розцінено як використання того самого ключа з іншим тілом запиту.

Помилки

Кожна помилка, згенерована сервісом, повертається відповідно до RFC 9457 із заголовком 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 та instance є стандартними полями. Числовий code збережено як розширення, щоб інтеграції, розроблені під версію 1, могли продовжувати перевіряти помилки за ним. Додаткові поля залежать від помилки і мають ігноруватися, якщо вони вам невідомі.

КодHTTPЗначення
4000400Тіло запиту не є коректним JSON
4001400Поле не пройшло валідацію або було передано невідоме поле
4002403Провайдер недоступний для вашого акаунта
4003400Некоректний ідентифікатор замовлення
4004400Провайдер не підтримує запитану мережу
4010401API-ключ відсутній
4011401API-ключ або IP-адресу не прийнято
4040404Замовлення не знайдено
4041404Акаунт не знайдено
4090409Запит із цим ключем ідемпотентності ще обробляється
4091409Дублікат запиту
4093409Цей ключ ідемпотентності вже використовувався з іншим тілом запиту
1004403Недостатньо коштів на балансі
5000500Внутрішня помилка
5001500Не вдалося виконати списання коштів
5002500Замовлення не було створено
5030503Провайдер недоступний

Помилки, які не використовують цей формат

Деякі помилки трапляються на рівні шлюзу (gateway), до того, як запит досягне застосунку, і вони зберігають власний формат шлюзу. Вважайте будь-яку відповідь, чий Content-Type відрізняється від application/problem+json, однією з таких:

СитуаціяHTTPТіло відповіді
API-ключ відсутній або недійсний401{"detail":{"code":-1,"msg":"Invalid or missing API key"}}
Перевищено ліміт запитів429{"message":"API rate limit exceeded"}
Невідомий шлях або метод, який не підтримується маршрутом404 / 405{"detail":"Method Not Allowed"}

Ліміти частоти запитів

Ліміт є спільним із POST /apiv2/aml та іншими AML-маршрутами: 5 запитів на секунду та 150 на хвилину. Перехід на цей ендпоінт не надає окремого ліміту.

Примітки

  • Ціноутворення: Elliptic $0.98, BitOK $0.50 за перевірку, списується з балансу в TRX за курсом на момент списання.
  • Час обробки: більшість перевірок завершується за кілька секунд; перевірка адреси з великою історією може тривати до трьох хвилин. Використовуйте асинхронний режим і перевіряйте результат за допомогою GET /apiv2/screening/{client_order_id}.
  • Неактивні адреси повертають статус skipped і не тарифікуються.
  • Оригінальна відповідь провайдера ніколи не повертається напряму. provider_data є адаптованою вибіркою; поля, що стосуються нашого облікового запису в системі провайдера, а не перевіреної адреси, нікому не розкриваються.

Звіти

Ендпоінт повертає виключно JSON. Формати PDF та Markdown не надаються.

Усе, з чого складається звіт, уже присутнє у відповіді: уніфікований блок та provider_data. Рендеринг даних на вашому боці дає змогу отримати документ у потрібному вам вигляді — з вашим брендингом, мовою та оформленням — що особливо актуально, якщо ви перепродаєте послуги перевірки, оскільки звіт з нашим логотипом не підходить для надання вашим кінцевим клієнтам.

Якщо вам потрібен звіт як підтвердження для третіх сторін — банку, регулятора або контрагента — зверніть увагу, що непідписаний PDF-файл не є юридичним доказом незалежно від того, хто його згенерував: його можна змінити в текстовому редакторі за хвилину. Документ, що має юридичну силу, потребує електронного підпису або публічної сторінки верифікації, а це окремий функціонал. Якщо у вас саме така потреба, повідомте нам вимоги вашого контрагента.

Готові звіти у форматі PDF для цих самих перевірок доступні в панелі керування Netts сімнадцятьма мовами.

Див. також