Skip to main content
POST
Request fields accept both camelCase and snake_case. See Request Field Names.
For each approval: the raw allowance, the realistic exposure after capping to the current balance, the USD value at risk, and — opt-in — risk assessments for the spender, the token, and the owner. A top-level summary aggregates total USD at risk so an approval-manager screen can render its banner without walking the array.

Request Notes

Supported Chains

Only Ethereum (1), BNB Smart Chain (56), and TRON. See Supported Chains. Any other chainId is rejected with 400. Responses are cached ~60 seconds per unique query + flag combination. A revocation the user just made may take up to that long to disappear. On TRON, responses echo case-preserved base58 — TRON encodes its checksum in letter casing, so a lowercased TRON address is not usable. Use the returned form for anything sent to a node or explorer.

Request Combinations

At least one of owner or spender is required. token cannot be sent on its own.

Opt-In Fields

These response fields are added only when you set the matching request flag to true. All flags default to false. Enable only the enrichments you render — each flag adds a lookup and its own latency. For a wallet-facing approval list, includeBalance + includeSpenderRisk is usually the right pairing. If the flag is false or omitted, that field is left out of the JSON — you did not ask for it. If the flag is true, the field is always in the JSON. A value means the lookup succeeded. null means the lookup failed; the rest of the row is still valid. Prefer retrying over showing an error screen. In JavaScript, check that the key exists ("spender_risk" in row) before reading it. Do not use row.spender_risk !== null — a missing key is undefined, and undefined !== null is true. Always send includeBalance: true on an approval-management screen. It turns “Unlimited / Unlimited” into “$4.50 at risk now, unlimited going forward”, and it lets an unlimited approval on an emptied wallet correctly report valid_allowance: "0".

Response Notes

USD Fields

Every row always includes both fields. They are never null. They price different amounts and can disagree. amount_raw, valid_allowance, and balance are uint256-scale strings — parse with BigInt. The USD fields are ordinary floats when they are numbers. Each value is one of three types. Check the type before formatting — do not assume a number. With includeBalance: true, an infinite on-chain approval often returns both a number and "Unlimited":
  • affected_usd_amount: 4.5 — the wallet holds $4.50, so only that can be taken today
  • potential_affected_usd_amount: "Unlimited" — the allowance is still unbounded, so later deposits can be taken too
Without includeBalance, both fields are often "Unlimited", even if the wallet is empty.

Risk Object

Returned on a row when you set includeSpenderRisk, includeTokenRisk, or includeOwnerRisk. Do not decide “risky” from risk_level yourself (for example risk_level >= 4). Use is_risky. Do not write logic against risk_details values (for example "blacklist_manual"). Those strings are not a stable list and can change. The array is [] when is_risky is false. When risk_level is 0, the address is considered safe. -1 means “no data” — do not consider the address as safe.

summary Totals

summary is a page-level banner. Do not add up the rows yourself.
  • The same token balance approved to several spenders is counted once, not once per spender.
  • Only rows with a number USD value are included. "Unlimited" and "Unknown" add 0.
  • So 0 can mean “nothing at risk” or “every row on this page is unlimited or unpriceable.”
  • If any row is "Unlimited" or "Unknown", treat the total as a floor: at least $X, plus N unlimited approvals.
  • includeBalance: true turns most unlimited rows into a number and closes that gap.
valid_approved_tokens is a lookup table for tokens HashDit has indexed (name, address, price, decimals). Unindexed tokens still appear in approval_status; they are just missing from this list. hasMore is evaluated before filter: "only-valid" runs, so a filtered page can show count well below limit while hasMore is still true. Do not stop paginating on a short count.

Headers

X-API-KEY
string
required

Your HashDit API key

Body

application/json

Approval query. At least one of owner or spender is required. token cannot be sent on its own.

chainId
string
required

int or string. Only 1 (Ethereum), 56 (BSC), or 728126428 / "tron" (TRON). Any other chain is rejected with 400. See Supported Chains.

Example:

"56"

owner
string

Owner / approver address. At least one of owner or spender is required.

Example:

"0x26d61f23bbc94d7b2139f9c581722bf4e8b64b87"

spender
string

Spender address. At least one of owner or spender is required.

token
string

Restrict to one token contract. Cannot be sent on its own — token alone returns 400.

page
integer
default:1

1-based page number. Values below 1 are treated as 1.

limit
integer
default:50

Rows per page. Ceiling 100 — higher values are clamped, not rejected.

filter
string

Only "only-valid" is accepted; it drops rows whose valid_allowance is 0. Any other value is a validation error.

includeBalance
boolean
default:false

Read each token's live on-chain balance for the owner.

includeSpenderRisk
boolean
default:false

Add spender_risk to every row.

includeTokenRisk
boolean
default:false

Add token_risk to every row.

includeOwnerRisk
boolean
default:false

Add owner_risk to every row.

includeAddressTypes
boolean
default:false

Classify each spender and owner as "eoa" or "contract".

Response

Successful response. Envelope is {code, status, data}.

code
string

API status code. "0" indicates success.

Example:

"0"

status
string
Example:

"ok"

data
object