LedgerCore
Compliance

Know Your Transaction / Address (KYT & KYA)

Risk-score a blockchain address (KYA) or transaction (KYT) for compliance screening. Both run through the same asynchronous job API described below.

Authentication

KYT/KYA endpoints accept an API key via the x-api-key header:

-H "x-api-key: llk_your_api_key_here"

Create and manage keys from Account → API Keys. (Session-based Clerk JWTs via Authorization: Bearer … also work from the dashboard, but programmatic callers should use an API key.)

KYT vs KYA — it's auto-detected

You call the same endpoint for both. The service picks the analysis type from your payload:

You sendAnalysis runapi_type in the result
addressKYA (Know Your Address)KYA
txidKYT (Know Your Transaction)KYT
Same endpoint for both

A POST /kyt/job with an address returns a KYA result. That is expected, not a bug: the analysis type follows the payload, not the path.

The flow: submit, then poll

Analysis is asynchronous. You submit a job, get a request_id back immediately, then poll that id until the status is completed.

POST /api/v1/kyt/job            ->  202  { request_id, status: "queued" }
GET  /api/v1/kyt/job/{id}       ->  200  { status: "queued" | "completed", response }

1. Submit a job

curl -X POST "http://localhost:8090/api/v1/kyt/job" \
  -H "x-api-key: llk_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "address": "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa",
    "chain": "bitcoin",
    "crawlTimeout": 60000,
    "reference_id": "customer-12345"
  }'

For a transaction (KYT), send txid instead of address:

  -d '{ "txid": "0x1234…", "chain": "ethereum", "reference_id": "customer-12345" }'

Request fields

FieldRequiredDescription
addressone of address / txidAddress to screen (runs KYA)
txidone of address / txidTransaction hash to screen (runs KYT)
chainyese.g. bitcoin, ethereum
crawlTimeoutnoMax crawl time in ms (e.g. 60000)
reference_idnoYour own correlation id, echoed back on the result — for example, store an internal customer ID or case ID here to associate the analysis with one of your customers or cases. (referenceId is accepted as a deprecated alias.)

Response — 202 Accepted

{
  "success": true,
  "data": {
    "request_id": "0692ee28-2942-4b46-b906-4fbee0d69c1b",
    "status": "queued",
    "reference_id": "customer-12345",
    "created_at": 1783580778153
  }
}

Hold on to request_id — that is what you poll with.

2. Poll for the result

curl "http://localhost:8090/api/v1/kyt/job/0692ee28-2942-4b46-b906-4fbee0d69c1b" \
  -H "x-api-key: llk_your_api_key_here"

While running, status is queued. Poll every few seconds until it is completed; typical jobs finish in a few seconds.

Response — 200 OK (completed)

{
  "success": true,
  "data": {
    "request_id": "0692ee28-2942-4b46-b906-4fbee0d69c1b",
    "status": "completed",
    "reference_id": "customer-12345",
    "response": {
      "api_type": "KYA",
      "chain": "bitcoin",
      "risk_level": "HIGH",
      "risk_score": 81.9,
      "response_id": "522f0569-08e4-4ce8-96c8-10a5b0117e58",
      "risk_reason": "Entity with highest risk score is txid 367f5e71… Its top risk rule is 'tagScore' with score 81.90.",
      "rule_scores": {
        "tag_score": 10,
        "is_sanctioned": 0,
        "is_blacklisted": 0,
        "receive_count": 8,
        "address_type": 2,
        "active_duration": 1
      },
      "target_summary": {
        "address": "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa",
        "tags": [{ "name": "satoshi-nakamoto", "type": "label", "display": "Satoshi Nakamoto" }],
        "balances": [{ "asset": "BTC", "amount": 57.23311933, "usd": 3595393.05 }]
      }
    }
  }
}

3. Full response (optional)

For the complete payload including graph and performance metadata:

curl "http://localhost:8090/api/v1/kyt/job/{request_id}/fullresponse" \
  -H "x-api-key: llk_your_api_key_here"

Two IDs, don't mix them up

request_id vs response_id

request_id identifies your job — you get it from the submit call and use it to poll (GET /kyt/job/{request_id}). response_id identifies the finished result, returned inside response; store it for your records, but it is not the id you poll with.

Reading the result

FieldMeaning
risk_levelLOW | MEDIUM | HIGH
risk_score0–100 composite score
risk_reasonHuman-readable driver of the score
rule_scoresPer-rule contributions (is_sanctioned, tag_score, …)
target_summary.tagsKnown labels/tags for the address
target_summary.balancesCurrent holdings and USD value

Credits

Each completed analysis consumes credits from your account (KYA and KYT have a small per-run minimum, with additional cost scaling to crawl depth/complexity). A 402 response means the account behind the API key is out of credits — top up from Account → Plan.

Errors

StatusMeaning
401Missing or invalid API key
402Insufficient credits
404Unknown request_id when polling

Legacy synchronous API (deprecated)

Deprecated endpoints

POST /api/v1/kyt/analyze and POST /api/v1/kya/analyze are deprecated. They block until the analysis completes (10–60s or more) and offer no way to recover a result if the connection drops. They remain available for backwards compatibility, but new integrations should use the asynchronous job flow above (POST /kyt/job + polling).

Was this page helpful?