Appearance
POST /apiv2/screening
Solicite uma triagem AML para um endereço de blockchain: um único formato de resposta para cada provedor e cada estado do pedido, números decimais como strings e um formato de erro único.
URL do endpoint
POST https://netts.io/apiv2/screeningCabeçalhos da requisição
| Header | Obrigatório | Descrição |
|---|---|---|
| Content-Type | Sim | application/json |
| X-API-KEY | Sim | Sua chave de API do painel da Netts |
| X-Idempotency-Key | Não | Sua própria chave para tentativas seguras. Veja Idempotência |
Corpo da requisição
json
{
"address": "YOUR_ADDRESS_HERE",
"network": "trx",
"provider": "elliptic",
"wait_for_result": true
}Parâmetros
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| address | string | Sim | Endereço a ser triado, 10–128 caracteres |
| network | string | Sim | Ticker da rede. Os tickers cobertos por cada provedor são listados por GET /apiv2/screening/providers |
| provider | string | Sim | elliptic ou bitok. Não há valor padrão |
| wait_for_result | boolean | Não | true aguarda pelo resultado por até 15 segundos. Padrão false |
| language | string | Não | Idioma do relatório. Apenas en |
Campos desconhecidos são rejeitados. Um corpo contendo um campo que não esteja na tabela acima retorna 400 com o código 4001.
provider é obrigatório e não possui valor padrão. Você sempre escolhe o provedor pelo qual paga.
provider é uma string de formato livre no esquema, não uma enumeração. Atualmente, dois valores são aceitos; um terceiro provedor não deve ser uma alteração incompatível (breaking change) para quem valida respostas em relação ao esquema. A lista atual, as redes cobertas por cada provedor e a escala em que cada um pontua vêm de GET /apiv2/screening/providers.
Exemplos de Requisição
cURL — aguardar pelo resultado
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 — aceitar e consultar (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"
}'A resposta é 202 Accepted com um cabeçalho Location apontando para o pedido.
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"])Códigos de Resposta
| Situação | Código | Cabeçalhos |
|---|---|---|
| Pedido criado, triagem é executada em segundo plano | 202 Accepted | Location: /apiv2/screening/{client_order_id} |
O resultado está na resposta (wait_for_result) | 200 OK | — |
| Resultado reutilizado de uma verificação recente, nada cobrado | 200 OK | — |
| Endereço não possui atividade na blockchain, nada cobrado | 200 OK | — |
| Erro | veja Erros | Content-Type: application/problem+json |
Respostas que contêm um resultado de triagem são enviadas com Cache-Control: private, no-store.
Resposta
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": { }
}O conjunto de campos nunca muda
Cada bloco listado acima está presente em todas as respostas, qualquer que seja o provedor e qualquer que seja o estado do pedido. O que um provedor não fornece é null; uma lista que não contém nada é [], e não null; um bloco que ainda não possui dados é preenchido com nulos em vez de ser omitido. Um único analisador (parser) lida com uma verificação que acabou de ser aceita e com a mesma verificação depois de concluída.
Duas consequências para o seu código:
- ignore campos que você não conhece. Novos campos são adicionados a esses blocos sem uma nova versão. Rejeitar um campo desconhecido é um bug seu, não nosso;
provider_datanão faz parte do contrato. Seu formato segue o provedor e muda quando o provedor muda. Tudo o que o contrato garante reside nos blocos acima.
order
| Campo | Tipo | Descrição |
|---|---|---|
| client_order_id | string | Identificador do pedido, usado para ler o resultado posteriormente |
| status | string | pending, processing, completed, skipped, failed |
| api_version | string | Contrato que criou o pedido |
| cache_hit | boolean | true quando um resultado recente foi reutilizado e nada foi cobrado |
| created_at | string | RFC 3339, UTC, microssegundos |
| started_at | string | null | Quando a chamada ao provedor começou. null para skipped |
| completed_at | string | null | Quando o resultado chegou |
| error | string | Apenas para failed: motivo da falha |
| reason | string | Apenas para skipped: address_inactive |
Todos os carimbos de data/hora (timestamps) estão em UTC, RFC 3339, com sufixo Z e precisão de microssegundos.
billing
| Campo | Tipo | Descrição |
|---|---|---|
| charged | boolean | Se o valor foi cobrado |
| price_usdt | string | Preço de tabela do provedor em USDT |
| base_amount | string | Preço do pedido na moeda cobrada, sem margem de subusuário |
| markup_amount | string | Margem de subusuário. "0" para uma conta direta |
| charged_amount | string | O que foi efetivamente debitado do saldo |
| charged_currency | string | TRX |
| exchange_rate | string | null | Taxa utilizada para a conversão |
| payment_status | string | paid, pending, failed, not_charged, postpaid |
payment_status fica como pending por um curto período após uma verificação bem-sucedida: a cobrança é retida primeiro e liquidada dentro de uma hora. failed significa que o dinheiro foi devolvido. not_charged significa que nenhuma cobrança foi criada — um resultado reutilizado ou um endereço ignorado. postpaid — veja Contas Pós-pagas.
precheck
Antes de uma triagem paga, o endereço é verificado quanto à atividade na blockchain. Um endereço sem atividade não é enviado ao provedor e não é cobrado.
| Campo | Tipo | Descrição |
|---|---|---|
| activity_checked | boolean | Se a verificação foi executada. false em redes onde ela não existe |
| activity_status | string | active, inactive, unknown |
| source | string | null | Nome do mecanismo |
unknown não interrompe a triagem paga: se o serviço de atividade estiver indisponível, o endereço é tratado como ativo.
check
| Campo | Tipo | Descrição |
|---|---|---|
| provider | string | Provedor que realizou a verificação |
| provider_check_id | string | null | O identificador próprio do provedor — mencione-o ao contestar um resultado com eles |
| checked_at | string | null | Quando o provedor produziu o resultado |
| status | string | Veja a tabela abaixo |
| provider_status | string | null | A formulação original do provedor, sem modificações |
order.status | check.status | Significado |
|---|---|---|
pending | pending | Pedido aceito, ainda não iniciado |
processing | running | O provedor está processando |
completed | completed | Resultado recebido |
failed | failed | Recusado antes ou durante a chamada ao provedor |
skipped | not_performed | O endereço não possui atividade; o provedor nunca foi chamado e nada foi cobrado |
risk
| Campo | Tipo | Descrição |
|---|---|---|
| score | string | null | A pontuação própria do provedor, como uma string decimal |
| scale | object | min e max da escala desse provedor |
| level | string | none, low, medium, high, severe |
| level_source | string | computed — derivamos o nível a partir da pontuação; provider — o provedor informou |
| provider_level | string | null | O termo próprio do provedor, quando ele retorna um |
| policy | string | Nome da política de limites (thresholds), netts-risk-v1 |
| by_direction | object | Pontuação dividida em source e destination, quando o provedor a divide |
A pontuação nunca é reescalonada. A Elliptic opera de 0 a 10 e a BitOK de 0 a 1, e 7 em uma escala não é 0,7 na outra em nenhum sentido prático. A escala vem na resposta para que uma integração desenvolvida para um provedor não interprete outro incorretamente após uma simples alteração de configuração.
O nível utiliza um único vocabulário em toda a API. Onde o provedor declara um nível próprio, nós o repassamos e indicamos isso em level_source; onde não o faz, derivamos o nível da pontuação com os limites de netts-risk-v1 e indicamos essa informação. A mesma palavra aparece na resposta da API, no painel e no relatório em PDF para a mesma verificação.
exposure[], rules[], entities[]
exposure[] detalha os fundos por categoria de contraparte. rules[] lista as regras do provedor que foram acionadas. entities[] lista as entidades às quais o próprio endereço pertence; primary_entity escolhe uma delas por uma regra fixa — a entidade que o provedor marcou como primária, caso contrário a primeira, caso contrário null. sanctioned_entities[] contém aquelas de entities[] que estão sinalizadas como ativas após uma data de sanções.
As participações são frações, nunca porcentagens
Cada participação na resposta é um único campo, share_fraction, uma string decimal entre "0" e "1".
text
Elliptic reports 31.574732212596924 % -> "share_fraction": "0.31574732212596924"
BitOK reports 0.8488 -> "share_fraction": "0.8488"Os provedores divergem nas unidades: o mesmo um terço de exposição chega como 31.57 de um e 0.3157 do outro. Um único campo carregando ambos seria impossível de interpretar sem conhecer o provedor. O número próprio do provedor em suas unidades originais permanece em provider_data.
Números são strings
Todo número proveniente de um provedor — pontuações, participações, volumes em USD e cada valor em billing — é uma string decimal.
json
"score": "0.9634087310611608"Analisar isso como um número JSON em JavaScript, Go ou qualquer outra linguagem com ponto flutuante binário resulta em uma aproximação, e o valor exibido deixa de corresponder ao valor emitido pelo provedor. Faça a análise desses campos com um tipo decimal: Decimal em Python, BigDecimal em Java, decimal.Decimal ou uma string em JavaScript.
Campos que são nossos e não do provedor — scale.min, scale.max, hops — são números JSON simples.
Reutilizando um resultado recente
Ao triar o mesmo endereço, rede e provedor novamente dentro de 60 segundos, o resultado anterior é retornado e nada é cobrado.
Cada requisição ainda cria seu próprio pedido com seu próprio client_order_id; o pedido reutilizado é marcado com "cache_hit": true e seu bloco billing reporta "charged": false com "payment_status": "not_charged". O identificador do pedido de onde veio o resultado não é divulgado — ele pode pertencer a outra conta.
A reutilização ocorre apenas dentro de uma mesma conta. Um resultado triado por outra pessoa nunca é retornado para você.
Idempotência
Envie X-Idempotency-Key com um valor próprio para tornar uma nova tentativa segura: a mesma chave com o mesmo corpo retorna a resposta armazenada em vez de solicitar uma segunda verificação.
| Situação | Código | Resposta |
|---|---|---|
| A primeira requisição com esta chave ainda está em execução | 409 | 4090 |
| A mesma chave, um corpo de requisição diferente | 409 | 4093 |
| A mesma chave, o mesmo corpo, já concluída | o código armazenado | a resposta armazenada |
Se você não enviar o cabeçalho, uma chave será gerada para você a partir da chave de API, do endereço, do provedor e do seu endereço IP, em uma janela de dois segundos. Isso protege contra um clique duplo e uma nova tentativa de gateway, não contra uma repetição um minuto depois: essa será um novo pedido genuíno e será cobrada.
Erros
Todo erro gerado pela aplicação utiliza o padrão RFC 9457 com 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 e instance são os campos padrão. O code numérico é uma extensão: baseie seu tratamento de erros nele. Campos extras dependem do erro e devem ser ignorados quando você não os conhecer.
| Código | HTTP | Significado |
|---|---|---|
4000 | 400 | O corpo não é um JSON válido |
4001 | 400 | Um campo falhou na validação ou um campo desconhecido foi enviado |
4002 | 403 | O provedor não está disponível para a sua conta |
4003 | 400 | Identificador de pedido malformado |
4004 | 400 | O provedor não suporta a rede solicitada |
4010 | 401 | Chave de API ausente |
4011 | 401 | Chave de API ou endereço IP não aceito |
4040 | 404 | Pedido não encontrado |
4041 | 404 | Conta não encontrada |
4090 | 409 | Uma requisição com esta chave de idempotência ainda está em execução |
4091 | 409 | Requisição duplicada |
4093 | 409 | Esta chave de idempotência foi usada com um corpo diferente |
1004 | 403 | Saldo insuficiente |
5000 | 500 | Erro interno |
5001 | 500 | A cobrança não foi processada |
5002 | 500 | O pedido não foi criado |
5030 | 503 | O provedor está indisponível |
Erros que não usam este formato
Algumas falhas ocorrem no gateway, antes que a aplicação seja alcançada, e mantêm o formato do próprio gateway. Trate qualquer resposta cujo Content-Type não seja application/problem+json como uma destas:
| Situação | HTTP | Corpo |
|---|---|---|
| Chave de API ausente ou chave não aceita | 401 | {"detail":{"code":-1,"msg":"Invalid or missing API key"}} |
| Limite de taxa excedido | 429 | {"message":"API rate limit exceeded"} |
| Caminho desconhecido ou método não atendido pela rota | 404 / 405 | {"detail":"Method Not Allowed"} |
Limites de taxa
5 requisições por segundo e 150 por minuto, compartilhadas por todas as rotas de triagem.
Contas Pós-pagas
Contas com faturamento pós-pago utilizam o mesmo endpoint, URL, cabeçalhos e corpo de requisição que todas as outras. A diferença é como a verificação é paga:
- Nada é deduzido do seu depósito. O preço de cada verificação concluída em dólares americanos (por exemplo, US$ 0,98 para a Elliptic) é adicionado ao saldo devedor da sua conta na moeda de liquidação acordada em seu contrato. Você efetua o pagamento via fatura, conforme o seu acordo.
- Sua conta possui um limite de crédito. Enquanto o valor devido estiver dentro do limite, as verificações serão aceitas mesmo com depósito zerado.
- Apenas verificações concluídas são faturadas. Uma verificação com falha, um endereço sem atividade (
skipped) e um resultado recente reutilizado não custam nada.
O faturamento pós-pago é ativado pela Netts para uma conta mediante solicitação.
billing de uma verificação pós-paga
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"
}| Campo | Descrição |
|---|---|
| charged | false: nada é debitado do depósito |
| price_usdt | Preço da verificação em dólares americanos. Este é o valor adicionado ao seu saldo devedor |
| charged_amount | O mesmo preço em TRX, para referência |
| payment_status | postpaid. Para uma verificação com falha ou ignorada — not_charged |
Limite de crédito atingido (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"
}A verificação não é solicitada e nada é faturado. Novas verificações voltam a ser aceitas assim que seu pagamento for registrado ou seu limite for aumentado.
Códigos de erro de pós-pago
| Código | HTTP | Descrição |
|---|---|---|
1004 | 402 | Limite de crédito pós-pago atingido |
5032 | 503 | Preço temporariamente indisponível |
5034 | 503 | Faturamento temporariamente indisponível — a verificação não foi aceita |
5036 | 503 | Verificação de crédito temporariamente indisponível — tente novamente mais tarde |
Para todas as respostas acima, nada é solicitado e nada é faturado.
Notas
- Preços: um preço fixo por verificação para cada provedor, consulte GET /apiv2/screening/providers; cobrado do saldo em TRX à taxa do momento da cobrança.
- Tempo de processamento: a maioria das verificações termina em alguns segundos; um endereço com um histórico longo pode levar até três minutos. Utilize o modo assíncrono e leia o resultado com GET /apiv2/screening/{client_order_id}.
- Endereços inativos retornam
skippede não são cobrados. - A resposta bruta do provedor nunca é retornada.
provider_dataé uma projeção revisada; campos que pertencem à nossa conta com o provedor, e não ao endereço triado, não são divulgados a ninguém.
Relatórios
O endpoint retorna JSON e nada mais. Não há PDF nem Markdown.
Tudo o que compõe um relatório já está na resposta: o bloco unificado e provider_data. Renderizá-lo do seu lado fornece o documento que você realmente deseja — sua marca, seu idioma, seu layout —, o que é fundamental caso você revenda verificações, pois um relatório com nosso nome é o documento errado para entregar ao seu próprio cliente.
Se você precisar de um relatório como comprovante para terceiros — um banco, um regulador, uma contraparte —, observe que um PDF não assinado não serve como comprovante, independentemente de quem o gere: ele pode ser editado em um editor de texto em um minuto. Um artefato verificável precisa de uma assinatura ou de uma página pública de verificação, e esse é um recurso diferente. Se esse for o seu caso, informe-nos o que a sua contraparte exige.
Relatórios em PDF legíveis por humanos existem para as mesmas verificações no painel da Netts, em dezessete idiomas.
Veja Também
- GET /apiv2/screening/{client_order_id} — consultar uma verificação
- GET /apiv2/screening/history — suas verificações, paginadas por cursor
- GET /apiv2/screening/providers — provedores, preços, redes, escalas
- GET /apiv2/screening/price — preço de um provedor
- Sanções em um resultado AML — o que
sanctionsdiz e o que a sinalização do provedor diz