# 05-Uppsala-KYT-Report



05-Uppsala-KYT-Report [#05-uppsala-kyt-report]

Retrieves the KYT analysis report using the `requestId` returned by the KYT Search API (\[04-Uppsala-KYT-Search.md]).

The response structure varies depending on the analysis status: `PENDING` (still processing), `RELEASED` (completed), or `FAILED` (analysis failed).

> **Note**: This API is jointly operated by CodeVASP and Uppsala Security. For inquiries or access requests, please contact [partnership@codevasp.com](mailto:partnership@codevasp.com).

Endpoint [#endpoint]

`GET` `/v1/code/uppsala/kytreport`

Request Parameters [#request-parameters]

Query Parameters [#query-parameters]

| Name      | Type    | Required | Description                                           |
| :-------- | :------ | :------- | :---------------------------------------------------- |
| requestId | integer | Required | Request ID received from the KYT Search API response. |

No request body is required.

Response [#response]

Fields [#fields]

| Name        | Type     | Nullable | Description                                                   |
| :---------- | :------- | :------- | :------------------------------------------------------------ |
| requestId   | integer  | No       | The search request ID.                                        |
| status      | string   | No       | `PENDING`, `RELEASED`, or `FAILED`.                           |
| error       | string   | Yes      | Error description. Present only when status is `FAILED`.      |
| submittedAt | datetime | No       | Timestamp when the analysis was requested.                    |
| report      | object   | Yes      | Full analysis report. Present only when status is `RELEASED`. |

Status Values [#status-values]

| Status     | Meaning                                                          |
| :--------- | :--------------------------------------------------------------- |
| `PENDING`  | Analysis is still in progress. Retry after a short interval.     |
| `RELEASED` | Analysis completed. The `report` field contains the full result. |
| `FAILED`   | Analysis failed. The `error` field contains the reason.          |

> **Note**: Analysis is performed asynchronously. When the status is `PENDING`, it is recommended to poll at intervals of 5–10 seconds until the status changes to `RELEASED` or `FAILED`.

Error Values (when `FAILED`) [#error-values-when-failed]

| error                         | Meaning                                                    |
| :---------------------------- | :--------------------------------------------------------- |
| `Tx hash not found`           | The transaction hash could not be found on the blockchain. |
| `Transaction analysis failed` | The analysis process encountered a failure.                |

> **Troubleshooting `Tx hash not found`**: This error occurs when:
>
> 1. The transaction hash does not exist on the specified blockchain.
> 2. The transaction is unconfirmed (pending in mempool) — retry after block confirmation.
> 3. The `blockchain` value submitted in \[04-Uppsala-KYT-Search.md] does not match the actual chain of the transaction (e.g., an EVM hash submitted with `blockchain: "TRX"`).

***

Report [#report]

When `status` is `RELEASED`, the `report` field contains the full analysis result.

Top-Level Report Fields [#top-level-report-fields]

| Name             | Type                  | Description                                                                                                                 |
| :--------------- | :-------------------- | :-------------------------------------------------------------------------------------------------------------------------- |
| reportId         | integer               | Unique report identifier.                                                                                                   |
| verdict          | string                | Risk verdict: `Clean`, `Suspicious`, or `Malicious`.                                                                        |
| totalAmount      | number                | Total amount traced in the transaction graph.                                                                               |
| maliciousAmount  | number                | Amount traced to blacklisted sources. Basis for `Malicious` verdict.                                                        |
| suspiciousAmount | number                | Amount traced to suspicious sources (mixers, gamblers, etc.). Basis for `Suspicious` verdict.                               |
| receiver         | string                | Receiving address of the analyzed transaction.                                                                              |
| generatedAt      | datetime              | Report generation timestamp.                                                                                                |
| senders          | string\[]             | List of sender addresses. UTXO chains (BTC/LTC) may have multiple senders.                                                  |
| riskIndicators   | object                | Detected risk indicators. See Risk Indicators section below.                                                                |
| annotations      | `map<string, object>` | Address-to-label mapping for addresses found in the transaction path.                                                       |
| byToken          | `map<string, object>` | Amount breakdown by token symbol (e.g., ETH, USDT, BTC). Separates risk amounts per token for EVM multi-token transactions. |

Verdict Logic [#verdict-logic]

| Verdict      | Trigger Condition                                                                                                                            |
| :----------- | :------------------------------------------------------------------------------------------------------------------------------------------- |
| `Malicious`  | `blacklistedAddresses` contains 1 or more entries.                                                                                           |
| `Suspicious` | No blacklisted addresses, but `suspiciousServices`, `behavioralPatterns`, `transactionPatterns`, or `mlFeatures` has at least one detection. |
| `Clean`      | All risk indicators are empty.                                                                                                               |

***

Risk Indicators (`riskIndicators`) [#risk-indicators-riskindicators]

| Field                | Type                   | Description                                              |
| :------------------- | :--------------------- | :------------------------------------------------------- |
| blacklistedAddresses | string\[]              | Uppsala blacklist matched addresses.                     |
| suspiciousServices   | `map<address, label>`  | High-risk services in the trace path.                    |
| behavioralPatterns   | object                 | Behavioral pattern detections.                           |
| transactionPatterns  | object                 | Transaction pattern detections.                          |
| mlFeatures           | `map<string, integer>` | ML model laundering detections. Value is `1` (detected). |

`blacklistedAddresses` (string[]) [#blacklistedaddresses-string]

Addresses matching the Uppsala blacklist. &#x2A;*If non-empty, the verdict is always `Malicious`.** These are wallets directly linked to hacking, scams, darknet, or theft.

`suspiciousServices` (`map<address, label>`) [#suspiciousservices-mapaddress-label]

Addresses identified as high-risk services in the trace path. Label examples: `Mixer`, `Tumbler`, `Gambling`, `Darknet Market`.

`behavioralPatterns` [#behavioralpatterns]

| Key             | Description                                                             |
| :-------------- | :---------------------------------------------------------------------- |
| swift\_movement | Layering indicator. Rapid fund forwarding through intermediate wallets. |

`swift_movement` [#swift_movement]

Detects funds rapidly forwarded through intermediate wallets within a threshold time window.

| Field                                     | Type     | Description                                                                          |
| :---------------------------------------- | :------- | :----------------------------------------------------------------------------------- |
| addresses\_count                          | integer  | Number of unique addresses that received and forwarded funds within the time window. |
| movement\_count                           | integer  | Total number of receive-then-forward movements detected.                             |
| threshold\_seconds                        | integer  | Time window threshold (movements within this time are flagged as swift).             |
| path\_count                               | integer  | Number of forwarding chains found in the trace graph.                                |
| paths\[].path\_length                     | integer  | Number of hops (intermediate wallets) in the chain.                                  |
| paths\[].movements\[].address             | string   | Address that received then forwarded funds.                                          |
| paths\[].movements\[].receive\_tx         | string   | Receive transaction hash.                                                            |
| paths\[].movements\[].send\_tx            | string   | Send transaction hash.                                                               |
| paths\[].movements\[].receive\_time       | datetime | Time funds were received.                                                            |
| paths\[].movements\[].send\_time          | datetime | Time funds were forwarded.                                                           |
| paths\[].movements\[].time\_diff\_seconds | integer  | Seconds between receive and forward (key layering signal).                           |
| paths\[].movements\[].receive\_amount     | number   | Amount received at this hop (native token).                                          |
| paths\[].summary.start\_address           | string   | Forwarding chain start address.                                                      |
| paths\[].summary.end\_address             | string   | Forwarding chain end address.                                                        |
| paths\[].summary.total\_time\_seconds     | integer  | Total elapsed time from start to end of chain.                                       |
| paths\[].summary.avg\_hop\_time\_seconds  | integer  | Average time per hop.                                                                |

`transactionPatterns` [#transactionpatterns]

| Key                      | Description                                           |
| :----------------------- | :---------------------------------------------------- |
| dormant status           | Wallets suddenly active after long dormancy.          |
| high\_value\_transaction | Transfers exceeding USD threshold.                    |
| high\_gas\_fee           | Abnormally high gas fees relative to transfer amount. |

`dormant status` [#dormant-status]

Wallets that became suddenly active after a long dormant period.

| Field                            | Type     | Description                                                       |
| :------------------------------- | :------- | :---------------------------------------------------------------- |
| pattern                          | string   | Pattern identifier (`"dormant_account"`).                         |
| is\_suspicious                   | boolean  | `true` if the dormant pattern is judged as an obfuscation signal. |
| addresses\_count                 | integer  | Number of wallets matching the pattern.                           |
| threshold\_days                  | integer  | Dormancy threshold in days.                                       |
| wallets\[].address               | string   | Wallet address matching the dormant pattern.                      |
| wallets\[].holding\_type         | string   | `long_hold_then_sent`, `still_holding`, or `never_sent`.          |
| wallets\[].holding\_period\_days | number   | Actual holding period in days.                                    |
| wallets\[].hold\_start           | datetime | Holding start time.                                               |
| wallets\[].hold\_end             | datetime | Holding end time (may be `"still holding"`).                      |
| wallets\[].hold\_start\_tx       | string   | Transaction hash when holding started.                            |
| wallets\[].hold\_end\_tx         | string   | Transaction hash when holding ended (`null` if still holding).    |

`high_value_transaction` [#high_value_transaction]

Transfers exceeding a configured USD threshold.

| Field                       | Type    | Description                                                        |
| :-------------------------- | :------ | :----------------------------------------------------------------- |
| pattern                     | string  | Pattern identifier (`"high_value_transaction"`).                   |
| is\_suspicious              | boolean | `true` if the high-value pattern is judged as a laundering signal. |
| count                       | integer | Number of transactions exceeding the threshold.                    |
| total\_usd                  | number  | Total USD value of flagged transactions.                           |
| threshold\_usd              | number  | USD threshold used for detection.                                  |
| transactions\[].tx\_hash    | string  | Transaction hash.                                                  |
| transactions\[].amount      | number  | Transfer amount (native token).                                    |
| transactions\[].amount\_usd | number  | USD value at time of transfer.                                     |
| transactions\[].symbol      | string  | Token symbol.                                                      |

`high_gas_fee` [#high_gas_fee]

Transactions with abnormally high gas fees relative to the transfer amount.

| Field                                        | Type    | Description                                                     |
| :------------------------------------------- | :------ | :-------------------------------------------------------------- |
| pattern                                      | string  | Pattern identifier (`"high_gas_fee"`).                          |
| is\_suspicious                               | boolean | `true` if the gas fee pattern is judged as a laundering signal. |
| count                                        | integer | Number of flagged transactions.                                 |
| total\_gas\_cost                             | number  | Total gas cost of flagged transactions (native token).          |
| avg\_gas\_percentage                         | number  | Average gas cost as percentage of transfer amount.              |
| transactions\[].tx\_hash                     | string  | Transaction hash.                                               |
| transactions\[].gas\_used                    | integer | Gas units consumed.                                             |
| transactions\[].gas\_cost                    | number  | Gas cost (native token).                                        |
| transactions\[].gas\_cost\_symbol            | string  | Gas payment token symbol.                                       |
| transactions\[].tx\_amount                   | number  | Transfer amount (native token).                                 |
| transactions\[].gas\_percentage              | number  | Gas cost as percentage of transfer amount.                      |
| transactions\[].exceeds\_absolute\_threshold | boolean | Whether gas cost exceeds the absolute threshold.                |
| transactions\[].exceeds\_ratio\_threshold    | boolean | Whether gas cost exceeds the ratio threshold.                   |
| transactions\[].threshold\_used              | number  | Absolute threshold applied.                                     |

`mlFeatures` (`map<string, integer>`) [#mlfeatures-mapstring-integer]

FATF guideline-based ML model detections for money laundering behaviors. Non-empty values contribute to `Suspicious` or `Malicious` verdicts.

Known feature keys: `Blacklisted wallet in trail`, `Relaying and Mixing`, `Tumbling`, `Abnormal Mixing`, `Abnormal Relaying`.

***

Annotations (`annotations`) [#annotations-annotations]

Map where each key is a **wallet address** (string) and the value is:

| Field            | Type   | Description                                                                                                                                          |
| :--------------- | :----- | :--------------------------------------------------------------------------------------------------------------------------------------------------- |
| annotation       | string | Human-readable label (e.g., `"Binance"`, `"Wrapped Ether, Token Contract"`, `"Huobi"`, `"OKEx, Exchange"`). May be `null` for blacklisted addresses. |
| securityCategory | string | Risk grade: `whitelist` (safe), `graylist` (neutral — exchanges, contracts), `blacklist` (malicious).                                                |

By Token (`byToken`) [#by-token-bytoken]

Map where each key is a **token symbol** (e.g., `"ETH"`, `"USDT"`, `"BTC"`) and the value is:

| Field      | Type   | Description                           |
| :--------- | :----- | :------------------------------------ |
| total      | number | Total amount traced for this token.   |
| malicious  | number | Amount traced to blacklisted sources. |
| suspicious | number | Amount traced to suspicious sources.  |

***

Errors [#errors]

Error Response Format [#error-response-format]

```json
{
  "errorType": "type",
  "errorMsg": "message"
}
```

Error Codes [#error-codes]

| HTTP | errorType               | Condition                                                                     |
| :--- | :---------------------- | :---------------------------------------------------------------------------- |
| 403  | `ACCESS_DENIED`         | No access permission for this resource.                                       |
| 404  | `NOT_FOUND`             | The requestId does not exist.                                                 |
| 422  | `INVALID_ORIGIN`        | VASP KYT feature not registered, request limit exceeded, or feature disabled. |
| 503  | `SERVICE_UNAVAILABLE`   | Temporary service disruption.                                                 |
| 500  | `INTERNAL_SERVER_ERROR` | Internal server error.                                                        |

Examples [#examples]

Request [#request]

```bash
curl --request GET \
     --url 'https://trapi.codevasp.com/v1/code/uppsala/kytreport?requestId=5714' \
     --header 'X-Code-Req-Datetime: datetime' \
     --header 'X-Code-Req-Nonce: nonce' \
     --header 'X-Code-Req-PubKey: Your key' \
     --header 'X-Code-Req-Signature: Sig' \
     --header 'X-Request-Origin: code:yourVaspEntityId' \
     --header 'accept: application/json'
```

Response (PENDING) [#response-pending]

```json
{
  "requestId": 5714,
  "status": "PENDING",
  "error": null,
  "submittedAt": "2026-03-24T09:05:43",
  "report": null
}
```

Response (FAILED) [#response-failed]

```json
{
  "requestId": 5713,
  "status": "FAILED",
  "error": "Tx hash not found",
  "submittedAt": "2026-03-24T09:02:52",
  "report": null
}
```

Response (RELEASED — Clean) [#response-released--clean]

```json
{
  "requestId": 5714,
  "status": "RELEASED",
  "error": null,
  "submittedAt": "2026-03-24T09:05:43",
  "report": {
    "reportId": 4154,
    "verdict": "Clean",
    "totalAmount": 0.01305,
    "maliciousAmount": 0,
    "suspiciousAmount": 0,
    "receiver": "0x4675c7e5baafbffbca748158becba61ef3b0a263",
    "generatedAt": "2026-03-24T09:08:02",
    "senders": ["0x4838b106fce9647bdf1e7877bf73ce8b0bad5f97"],
    "riskIndicators": {
      "blacklistedAddresses": [],
      "suspiciousServices": {},
      "behavioralPatterns": {},
      "transactionPatterns": {},
      "mlFeatures": {}
    },
    "annotations": {
      "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2": {
        "annotation": "Wrapped Ether, Token Contract",
        "securityCategory": "graylist"
      },
      "0x51c72848c68a965f66fa7a88855f9f7784502a7f": {
        "annotation": "Wintermute, Market Maker",
        "securityCategory": "graylist"
      }
    },
    "byToken": {
      "ETH": { "total": 0.01305, "malicious": 0, "suspicious": 0 }
    }
  }
}
```

Response (RELEASED — Malicious) [#response-released--malicious]

```json
{
  "requestId": 5715,
  "status": "RELEASED",
  "error": null,
  "submittedAt": "2026-03-04T06:20:00",
  "report": {
    "reportId": 2934,
    "verdict": "Malicious",
    "totalAmount": 27.71263268,
    "maliciousAmount": 27.71263268,
    "suspiciousAmount": 0,
    "receiver": "0xeaf19109fd5fb9cffff7d602e1bf35203afd443a",
    "generatedAt": "2026-03-04T06:22:55",
    "senders": ["0xda39b8f19ae780aa07ff512a79f03df52c1c7e43"],
    "riskIndicators": {
      "blacklistedAddresses": [
        "0xc5d431ee2470484b94ce5660aa6ae835346abb19"
      ],
      "suspiciousServices": {},
      "behavioralPatterns": {},
      "transactionPatterns": {
        "dormant status": {
          "pattern": "dormant_account",
          "is_suspicious": false,
          "addresses_count": 1,
          "threshold_days": 365,
          "wallets": [
            {
              "address": "0xda39b8f19ae780aa07ff512a79f03df52c1c7e43",
              "holding_type": "never_sent",
              "holding_period_days": 3498.32,
              "hold_start": "2016-08-04 22:41:16",
              "hold_end": "still holding",
              "hold_start_tx": "0x2ea57f652edb269495...",
              "hold_end_tx": null
            }
          ]
        }
      },
      "mlFeatures": {
        "Blacklisted wallet in trail": 1
      }
    },
    "annotations": {
      "0xc5d431ee2470484b94ce5660aa6ae835346abb19": {
        "annotation": null,
        "securityCategory": "blacklist"
      }
    },
    "byToken": {
      "ETH": { "total": 27.712632679, "malicious": 27.712632679, "suspicious": 0 }
    }
  }
}
```

Response (RELEASED — Suspicious) [#response-released--suspicious]

```json
{
  "requestId": 5716,
  "status": "RELEASED",
  "error": null,
  "submittedAt": "2026-03-04T09:10:00",
  "report": {
    "reportId": 2942,
    "verdict": "Suspicious",
    "totalAmount": 30000,
    "maliciousAmount": 0,
    "suspiciousAmount": 1700,
    "receiver": "TEkS7DeWpHmy6Wty3nLhKmcgCvbWZ1oyAa",
    "generatedAt": "2026-03-04T09:12:04",
    "senders": ["TRPS8prmSJrGcv8K6NUhDzMG8tQ8pu1GPA"],
    "riskIndicators": {
      "blacklistedAddresses": [],
      "suspiciousServices": {},
      "behavioralPatterns": {},
      "transactionPatterns": {},
      "mlFeatures": {
        "Abnormal Relaying": 1
      }
    },
    "annotations": {
      "TMqDrZa5kEebg5wi3W3wusVZ6ZF2w6JczH": {
        "annotation": "Huione",
        "securityCategory": "graylist"
      },
      "TLaGjwhvA8XQYSkFAcAXyYDvuue9eGYitv": {
        "annotation": "OKEx, Exchange",
        "securityCategory": "graylist"
      }
    },
    "byToken": {
      "USDT": { "total": 30000, "malicious": 0, "suspicious": 1700 }
    }
  }
}
```
