응답은 어떻게 읽습니까: unknown, null, 빈 목록, no-store
여기서 시작 · 결과는 둘이 아니라 셋입니다: 이름이 붙은 결과, 없음, 알 수 없음 — 그리고 응답이 불완전하다는 네 가지 신호
- API 가이드
- 8분
- 중급
- 개발자
- 읽기
이 API의 모든 판정에는 세 가지 결과가 있으며, 코드는 세 가지를 모두 유지해야 합니다. 이름이 붙은 결과(sanctioned, frozen, severe), none(충분한 집계 범위에서 확인했고 아무것도 찾지 못함), unknown(확인할 수 없었음)입니다. unknown은 결코 none이 아니며, 항상 incomplete_reasons에 이유를 밝힙니다. 응답이 보이는 것보다 부족하다는 신호가 네 가지 더 있습니다. 숫자가 있어야 할 곳의 null, 판정이 아니라 목록일 뿐인 빈 목록, 일부를 잃은 조회에 붙은 Cache-Control: no-store, 요청한 것보다 늦게 시작하는 그래프의 window_from입니다. 이 페이지는 정직성 계약을 분기 규칙으로 다시 쓴 것입니다.
코드로 본 세 가지 결과
2026-10-24에 한 제재 대상 주소의 위험 판정은 "tier": "severe", "incomplete_reasons": []였습니다. 같은 시각 바이낸스(Binance) 핫월렛의 위험 판정은 "tier": "unknown", "incomplete_reasons": ["time_budget"]였고, 이를 설명하는 evidence 행이 있었습니다. exposure not assessed: the walk stopped on its time budget with 0 of 3 hops completed(노출 평가 안 됨: 순회가 시간 예산에 걸려 3홉 중 0홉을 완료하고 멈춤). 둘 다 완결된 문장입니다. 첫 번째는 하지 마십시오라고 말하고, 두 번째는 판단할 수 없었습니다라고 말합니다. 두 번째를 괜찮음으로 처리하는 프로그램은 스캐너가 기반으로 삼는 단 하나의 규칙을 깨뜨린 것입니다.
risk = scan(f"/v1/addresses/{addr}/risk", chain=1)
if risk["tier"] in ("severe", "high"):
decision = "refuse"
elif risk["tier"] == "unknown":
decision = "escalate" # not "allow": the reasons are in risk["incomplete_reasons"]
elif risk["tier"] == "none":
decision = "allow"
else: # "low", "medium": a label or an indirect reach set it
decision = "review"evidence 행은 사람을 위한 것이고, 필드는 프로그램을 위한 것입니다. detail 텍스트가 아니라 tier, flags, exposure, incomplete_reasons로 분기하십시오.
incomplete_reasons: 평가되지 않은 것
빠짐없이 고정된 순서로 나열된 목록이며, 빠진 것이 없으면 []입니다. 각 값과 그 값이 요구하는 것은 다음과 같습니다.
| 이유 | 위치 | 의미 |
|---|---|---|
time_budget | risk, exposure | 요청 기한 안에 머물기 위해 노출 순회가 중단되었습니다. 한산한 시점에 같은 조회를 하면 완료될 수 있습니다 — 응답은 약 10초만 유지되므로(60 대신 Cache-Control: max-age=10), 반복하기 전에 간격을 두십시오 |
frontier_cap | risk, exposure | 한 홉이 탐색 경계 상한보다 넓었습니다. 주소의 속성이므로 매 호출마다 반복됩니다 |
short_history | risk, exposure | 관측된 유입이 1달러 미만 — 평가할 것이 없습니다 |
ofac_list_unloaded, ofac_list_stale | risk, exposure | 제재 목록이 없거나 7일보다 오래되었습니다(sanctions_list_as_of). 순회가 도달한 출발점은 그대로 유효합니다 |
no_accusation_labels | risk, exposure | 해당 네트워크에 해킹 / 드레이너 / 믹서 라벨이 로드되어 있지 않습니다 |
coverage_pending, coverage_partial | 솔라나 전용 | 주소의 기록이 아직 채워지는 중이거나, 문서화된 한도까지 채워졌습니다(coverage_status) |
freeze_history_incomplete | risk | 발행사 로그가 소급 수집되지 않은 동결 쌍 — 등급이 none일 수 없습니다 |
labels_unread, new_counterparty_unread | risk | 조회가 끝나지 않았습니다. 응답은 no-store입니다 — 다시 요청하십시오 |
이유는 사실이 정한 등급을 낮추지 않습니다. 제재 대상 주소는 순회가 어떻게 되었든 severe로 남습니다. 또한 중단된 순회 자체가 unknown을 뜻하지는 않습니다. 중단 전에 순회가 출발점에 도달했다면 exposure는 sanctioned, direct 또는 indirect이며 그대로 유효합니다. truncation_reason만 보지 말고 exposure를 읽으십시오.
null은 읽지 못함, 0은 측정됨
freshness_seconds: null은 이번 응답에서 가장 최근 전송의 경과 시간을 읽을 수 없었다는 뜻입니다 — 0도 아니고 추정치도 아닙니다. chains_with_data: null은 존재 여부 조사가 실행되지 않았다는 뜻이고, []는 인덱싱된 어떤 네트워크에도 그 주소의 전송, 라벨, 유효한 동결 기록이 없다는 뜻입니다. 피드에서 "total": null과 total_unavailable_reason: "timeout"은 개수 집계가 끝나지 않았다는 뜻입니다 — 행은 실제이므로 계속 페이지를 넘기십시오. /v1/verify에서 found: null은 적어도 하나의 네트워크가 응답하지 않았다는 뜻입니다 — 다시 시도하십시오. 부정 결과가 아닙니다. found: false는 각 네트워크의 chains[].sync 시점 기준으로 모든 네트워크의 핫 윈도우에 걸친 부정 결과입니다.
다시 요청해도 채워지지 않는 null이 하나 있습니다. /v1/stats/home 또는 /v1/stats/overview에서 organic_unavailable_reason이 붙은 오가닉 수치입니다. 이는 실패한 조회가 아니라 배치의 상태입니다.
빈 목록은 목록일 뿐입니다
freeze: []— 해당 네트워크에서는 아무것도 동결될 수 없다는 뜻입니다(동결 가능한 스테이블코인이 없는 네트워크의 주소 개요). 동결된 것이 없음이 아닙니다.frozen_elsewhere: []— 다른 인덱싱된 네트워크에 유효한 동결 기록이 없다는 뜻입니다. 모든 곳에서 깨끗함이 아닙니다.freeze_proposals: []— 공개된 제안이 없다는 뜻입니다. 결코 대기 중인 것 없음이 아닙니다(대기 중인 제안을 공개할지는 배포별 설정이며, 제안 목록의note가 알려 줍니다).items: []인/v1/freezes/acts?address=— 행이 없는 목록이지, 주소에 대한 판정이 아닙니다./approvals에서worst_band: "none"과 함께open: []— 이 체인에서, 인덱싱된 로그 범위 안에서 열린 허용량이 발견되지 않았다는 뜻입니다.
주소에 대한 판정은 /risk에 있습니다. 목록들은 그 판정을 만든 사실입니다.
no-store는 다시 요청하라는 뜻입니다
일부를 잃은 응답은 Cache-Control: no-store로 제공되며 보관되지 않습니다. 라벨을 제때 읽지 못한 판정(labels_unread), 최신성이 null인 주소 또는 동기화 응답, total: null인 피드 페이지, degraded_reason이 있는 /graph, found: null인 /v1/verify가 그렇습니다. 잠시 후 같은 요청은 완전할 수 있습니다. 오류 응답과 /v1/stats/slo도 no-store이지만, 이 경우에는 재시도에 대해 아무것도 말하지 않습니다 — 503 timeout에는 자체 Retry-After가 있습니다.
코드에서 Cache-Control을 정보로 읽으십시오.
const res = await fetch(`${BASE}/v1/addresses/${addr}/risk?chain=1`);
const risk = await res.json();
const cc = res.headers.get("cache-control") ?? "";
if (cc.includes("no-store")) schedule(retry, 2_000); // a part was lost: ask again
else if (cc.includes("max-age=10")) schedule(retry, 10_000); // the walk was cut: a quieter moment may finish itwindow_from: 그래프가 요청한 지점이 아닌 곳에서 시작할 때
/walk, /graph, 그래프 순회 스킬은 고정된 기간 동안 보관되는 일 단위 데이터를 읽습니다. window_from이 있으면 — 2026-10-24에 바이낸스 순회는 window all에서 "window_from": "2026-10-03"으로 응답했습니다 — 응답은 지정한 기간의 시작이 아니라 그 날짜부터 만들어진 것입니다. 그래프는 그 구간만 다룬다고 읽으십시오. 거래 상대, 경로, 제재 대상 노드가 없다는 것은 그 이전에 대해 아무것도 말하지 않습니다. window_from이 없으면 전체 기간입니다. /graph에서 edge_source: "lifetime"은 인덱싱된 모든 날입니다.
솔라나: coverage_status는 주소의 상태입니다
솔라나(Solana)에서는 주소 개요, risk, exposure, walk, graph, volume에 주소별 coverage_status가 있습니다. pending(기록이 아직 채워지는 중이거나, 아직 채우기를 요청하지 않음 — 개요를 한 번 조회하면 요청됩니다) 또는 partial(문서화된 한도까지 채워짐, 주기적으로 다시 채워짐)입니다. 둘 다 오류가 아니며, 체인 상태도 아닙니다. 둘 다 unknown과 같은 부류로 취급하십시오. 또한 솔라나의 위험 등급은 결코 none이 아닙니다. 솔라나 발행사 기록은 수집되지 않으며, 모든 솔라나 동결 쌍은 unknown으로 읽히기 때문입니다.
모두 unknown인 결과도 결과입니다
인덱싱된 스테이블코인 기록이 없는 주소는 모든 경로에서 unknown 또는 빈 값으로 응답합니다. chains_with_data: [], tier: "unknown", short_history입니다. 그것이 발견 사항입니다 — 이 인터페이스에는 불리한 것도, 해명이 되는 것도 없습니다 — 그리고 그 뒤에 더 깊은 엔드포인트는 없습니다. 자체 정책에 따라 결정하고, 세 가지 결과 중 무엇이었는지 로그에 남기십시오.
Stablecoin scanner ACHIVX에서
incomplete_reasons: []인 완전한 판정: 제재 대상 예시의 위험.- 완료할 수 없었던 판정과 그 이유, 이를 설명하는 증거 행: 바이낸스 핫월렛의 위험(2026-10-24에 등급은
unknown이었습니다. 한산한 시점에는 순회가 완료될 수 있습니다). - 스캐너 자체의 말로 된 규칙: /agents.md §4.
출처
- 에이전트 매뉴얼 — agents.md(버전 2026-10-05)
- REST 인터페이스의 OpenAPI 3.1 명세(API 1.4.0)
- GET /v1/addresses/…/risk — 2026-10-24에 읽은 두 판정
더 알아보기
관련 질문
- 주소에 대한 단일 위험 판정은 어떻게 얻고, 언제 unknown이 됩니까?
- 주소의 제재 대상 자금이나 해킹 자금 노출은 어떻게 측정합니까?
- 코드에서 오류, 요청 한도, 타임아웃은 어떻게 처리합니까?
여기서 시작 · 읽기 · 2026-10-24 작성, openapi.json, agents.md 및 당일 실제 호출 기반. 구조는 인용한 것이며, 수치는 날짜 기준이고 인덱스에 따라 바뀝니다.
이 페이지는 ACHIVX Academy 영어 원문을 한국어로 옮긴 것입니다. 번역과 원문이 다르면 영어 원문이 기준입니다.