Проверка адреса
Синхронно проверяет блокчейн-адрес, сохраняет запись и возвращает полный обезличенный отчёт в теле ответа 201. Идентификатор проверки (id) используйте для повторного получения отчёта и выгрузки PDF - см. Отчёты и PDF.
/api/v1/aml/checks
Проверить блокчейн-адрес
Body
address
string
required
network
string
optional
tron, ethereum, bitcoin, litecoin и т.д. Максимум 20 символов. Если не указана - сеть определяется по формату адреса; для адресов, валидных в нескольких сетях (например EVM-совместимых), указывайте явно.| Name | Type | Required | Description |
|---|---|---|---|
address
|
string
|
required | Блокчейн-адрес. Максимум 120 символов. |
network
|
string
|
optional |
Сеть адреса: tron, ethereum, bitcoin, litecoin и т.д. Максимум 20 символов. Если не указана - сеть определяется по формату адреса; для адресов, валидных в нескольких сетях (например EVM-совместимых), указывайте явно.
|
Заголовки
Idempotency-Key
string
optional
| Name | Type | Required | Description |
|---|---|---|---|
Idempotency-Key
|
string
|
optional | Необязательный ключ повтора (до 80 символов). Запрос с уже использованным ключом возвращает ту же проверку и не выполняет её повторно. Ключ действует в пределах вашей учётной записи и окружения (live и sandbox не пересекаются). |
Idempotency-Key - в ответ придёт ранее выполненная проверка. Без заголовка каждый запрос считается новым вызовом.
Responses
{
"data": {
"id": "b7e4c1a2-3f5d-4e8a-9c1b-2d6f7a8e0b3c",
"address": "TXYZ1234567890abcdefGHIJKLmnop",
"network": "tron",
"risk_score": 64,
"risk_level": "high",
"report": {
"risk_score": 64,
"risk_level": "high",
"recommendation": "reject",
"signals": {
"sanctioned": false,
"watchlisted": false,
"watchlist_category": null,
"community_reports": 4,
"high_risk_counterparties": 1,
"fatf_country": true,
"is_stablecoin_contract": false,
"defi_exposure_score": 24
},
"factors": [
{ "code": "cluster_risk", "label": "Кластерный риск", "score": 4 },
{ "code": "direct_exposure", "label": "Прямая экспозиция к рисковым адресам", "score": 14 },
{ "code": "anomaly_ml", "label": "Поведенческие ML-аномалии", "score": 64 }
],
"networks": [
{
"network": "tron",
"native_balance": 0,
"tx_count": 231,
"first_tx_at": null,
"last_tx_at": null,
"is_contract": false
}
],
"balances": {
"USDT": 0,
"USDC": 0,
"tx_count": 231,
"account_age_days": 512
},
"checked_at": "2026-07-13T10:24:00+00:00",
"sandbox": true
},
"price": null,
"pricing": { "markup_pct": 0, "price": null, "currency": "USDT" },
"report_url": "https://fin-os.io/api/v1/aml/checks/b7e4c1a2-3f5d-4e8a-9c1b-2d6f7a8e0b3c/report.pdf",
"created_at": "2026-07-13T10:24:00+00:00"
}
}
{
"error": {
"code": "service_balance_insufficient",
"message": "Недостаточно средств на сервисном счёте. Пополните мастер-счёт.",
"request_id": "req_3Nd8Vc1Xz5Bm7Kq0Lp2Rt6W",
"currency": "USDT",
"required": "0.2",
"available": "0.0500000000"
}
}
Поле report.sandbox присутствует и равно true только в sandbox-ответах; в live его нет.
Вердикт: score → level → recommendation
risk_score (0-100) платформа сама отображает в risk_level, а risk_level - в готовую рекомендацию recommendation. Пороги перевода балла в уровень - настройка платформы: они пересматриваются по мере накопления данных и в публичном контракте не фиксируются. Поэтому в своей логике опирайтесь на risk_level и recommendation и не сравнивайте risk_score с собственными константами - иначе после очередной калибровки ваши правила разойдутся с решением платформы.
Уровень и рекомендация (связь жёсткая)
low
allow
optional
medium
review
optional
high
reject
optional
critical
block
optional
| Name | Type | Required | Description |
|---|---|---|---|
low
|
allow
|
optional | Пропустить операцию. |
medium
|
review
|
optional | Отдать на ручную проверку. |
high
|
reject
|
optional | Отклонить операцию. |
critical
|
block
|
optional | Заблокировать. |
sk_test_ балл и уровень вычисляются детерминированно по самому адресу и служат только для проверки формата ответа и вашей обработки. С боевыми значениями по тому же адресу они не совпадают, поэтому пороговые правила, «подобранные» на песочнице, в бою работать не будут.
signals.sanctioned = true) и при risk_level: critical рекомендация всегда block. Такие адреса блокируйте жёстко на своей стороне - не полагайтесь только на «мягкие» пороги.
signals
Плоский набор булевых и числовых сигналов - самые «читаемые» поля для быстрых правил на вашей стороне.
report.signals
sanctioned
bool
optional
watchlisted
bool
optional
watchlist_category
string|null
optional
high_risk_entity) или null.community_reports
int
optional
high_risk_counterparties
int
optional
fatf_country
bool
optional
is_stablecoin_contract
bool
optional
defi_exposure_score
int|null
optional
null.| Name | Type | Required | Description |
|---|---|---|---|
sanctioned
|
bool
|
optional | Адрес найден в санкционных списках. |
watchlisted
|
bool
|
optional | Адрес найден в watchlist. |
watchlist_category
|
string|null
|
optional |
Категория watchlist-совпадения (например high_risk_entity) или null.
|
community_reports
|
int
|
optional | Число публичных жалоб сообщества на адрес. |
high_risk_counterparties
|
int
|
optional | Число контрагентов с высоким риском. |
fatf_country
|
bool
|
optional | Связь с юрисдикцией из индикаторов FATF. |
is_stablecoin_contract
|
bool
|
optional | Адрес является контрактом стейблкоина. |
defi_exposure_score
|
int|null
|
optional |
Оценка экспозиции к DeFi (0-100) или null.
|
factors
Разложение скоринга по факторам. Каждый элемент - { code, label, score }, где score - вклад фактора (0-100). Состав массива зависит от адреса и может пополняться, поэтому обрабатывайте его как список, а не как фиксированный набор ключей. Возможные коды:
report.factors[].code
cluster_risk
optional
direct_exposure
optional
community_reports
optional
balance_risk
optional
fatf_indicators
optional
historical_coin_risk
optional
anomaly_ml
optional
loo_toxicity
optional
multihop_trace
optional
bridge_contamination
optional
defi_exposure
optional
time_of_day_pattern
optional
velocity_decay
optional
token_mix_entropy
optional
realtime_security
optional
intelligence_verdicts
optional
deprecated_stablecoins
optional
| Name | Type | Required | Description |
|---|---|---|---|
cluster_risk
|
string
|
optional | Кластерный риск. |
direct_exposure
|
string
|
optional | Прямая экспозиция к рисковым адресам. |
community_reports
|
string
|
optional | Публичные жалобы сообщества. |
balance_risk
|
string
|
optional | Риск по балансу и активности. |
fatf_indicators
|
string
|
optional | Юрисдикционные индикаторы (FATF). |
historical_coin_risk
|
string
|
optional | Исторический риск актива. |
anomaly_ml
|
string
|
optional | Поведенческие ML-аномалии. |
loo_toxicity
|
string
|
optional | Токсичность окружения. |
multihop_trace
|
string
|
optional | Многоступенчатая трассировка. |
bridge_contamination
|
string
|
optional | Контаминация через кросс-чейн мосты. |
defi_exposure
|
string
|
optional | DeFi-экспозиция. |
time_of_day_pattern
|
string
|
optional | Временной паттерн активности. |
velocity_decay
|
string
|
optional | Затухание скорости операций. |
token_mix_entropy
|
string
|
optional | Энтропия набора токенов. |
realtime_security
|
string
|
optional | Реал-тайм проверка безопасности контракта. |
intelligence_verdicts
|
string
|
optional | Сводные вердикты разведданных. |
deprecated_stablecoins
|
string
|
optional | Устаревшие стейблкоины. |
networks и balances
report.networks[] - агрегаты активности по каждой затронутой сети.
report.networks[]
network
string
optional
tron, ethereum, bitcoin, litecoin и т.д.native_balance
number
optional
tx_count
int
optional
first_tx_at
datetime|null
optional
null.last_tx_at
datetime|null
optional
null.is_contract
bool
optional
| Name | Type | Required | Description |
|---|---|---|---|
network
|
string
|
optional |
Сеть: tron, ethereum, bitcoin, litecoin и т.д.
|
native_balance
|
number
|
optional | Баланс нативной монеты сети. |
tx_count
|
int
|
optional | Число транзакций в этой сети. |
first_tx_at
|
datetime|null
|
optional |
Первая транзакция (ISO 8601) или null.
|
last_tx_at
|
datetime|null
|
optional |
Последняя транзакция (ISO 8601) или null.
|
is_contract
|
bool
|
optional | Адрес - смарт-контракт. |
report.balances - сводные балансы и метрики по адресу.
report.balances
USDT
number
optional
USDC
number
optional
tx_count
int
optional
account_age_days
int|null
optional
null.| Name | Type | Required | Description |
|---|---|---|---|
USDT
|
number
|
optional | Баланс USDT. |
USDC
|
number
|
optional | Баланс USDC. |
tx_count
|
int
|
optional | Совокупное число транзакций. |
account_age_days
|
int|null
|
optional |
Возраст адреса в днях или null.
|
price и pricing
Каждый ответ несёт стоимость выполненной проверки. Пример выше - sandbox, поэтому оба поля null: песочница не тарифицируется.
price
string|null
optional
null - вызов был бесплатным (песочница, освобождение по договору или обязательная проверка платформы).pricing.price
string|null
optional
pricing.currency
string
optional
USDT.pricing.markup_pct
number
optional
0. Проверка - ваш расход, а не товар для перепродажи: надбавки у неё нет.| Name | Type | Required | Description |
|---|---|---|---|
price
|
string|null
|
optional |
Сумма, фактически списанная с мастер-счёта за эту проверку. null - вызов был бесплатным (песочница, освобождение по договору или обязательная проверка платформы).
|
pricing.price
|
string|null
|
optional | То же значение внутри объекта тарифа. |
pricing.currency
|
string
|
optional |
Валюта списания - всегда USDT.
|
pricing.markup_pct
|
number
|
optional |
Историческое поле, всегда 0. Проверка - ваш расход, а не товар для перепродажи: надбавки у неё нет.
|
Цена фиксируется в момент проверки и в сохранённом отчёте больше не меняется, даже если тариф впоследствии пересмотрят. Сумма списания видна и в леджере мастер-счёта - строкой типа aml_fee (см. Merchant Balance). Если проверка не дала вердикта, там же появится парная строка aml_fee_refund.
402 service_balance_insufficient. Ответ содержит currency, required и available - показывайте нехватку пользователю как есть и пополняйте счёт.
Примеры кода
# Проверить адрес (sandbox - по префиксу sk_test_)
curl -X POST https://fin-os.io/api/v1/aml/checks \
-H "Authorization: Bearer sk_test_..." \
-H "Content-Type: application/json" \
-d '{"address": "TXYZ1234567890abcdefGHIJKLmnop", "network": "tron"}'
const FINOS = 'https://fin-os.io/api/v1';
const KEY = process.env.FINOS_SECRET_KEY; // sk_test_ (sandbox) или sk_live_ (live)
async function checkAddress(address, network) {
const res = await fetch(`${FINOS}/aml/checks`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ address, network }),
});
const { data } = await res.json();
// Готовое решение по единому вердикту:
if (data.report.recommendation === 'block' || data.report.recommendation === 'reject') {
console.warn(`Отклонить: ${address} - ${data.risk_level} (${data.risk_score})`);
}
console.log('PDF-отчёт:', data.report_url);
return data;
}
checkAddress('TXYZ1234567890abcdefGHIJKLmnop', 'tron');
use Illuminate\Support\Facades\Http;
class FinosAml
{
private string $base = 'https://fin-os.io/api/v1';
public function __construct(private string $secretKey) {}
public function check(string $address, ?string $network = null): array
{
return Http::withToken($this->secretKey)
->post("{$this->base}/aml/checks", array_filter([
'address' => $address,
'network' => $network,
]))
->json('data');
}
}
$aml = new FinosAml(config('services.finos.secret_key'));
$check = $aml->check('TXYZ1234567890abcdefGHIJKLmnop', 'tron');
if (in_array($check['report']['recommendation'], ['reject', 'block'], true)) {
// задержать операцию / отправить на ручной комплаенс
}
import requests, os
FINOS = 'https://fin-os.io/api/v1'
KEY = os.environ['FINOS_SECRET_KEY'] # sk_test_ (sandbox) или sk_live_ (live)
H = {'Authorization': f'Bearer {KEY}'}
def check_address(address, network=None):
payload = {'address': address}
if network:
payload['network'] = network
r = requests.post(f'{FINOS}/aml/checks', headers=H, json=payload)
r.raise_for_status()
return r.json()['data']
data = check_address('TXYZ1234567890abcdefGHIJKLmnop', 'tron')
print(data['risk_level'], data['risk_score'], data['report']['recommendation'])