API reference
Every endpoint, grouped by module. Conventions common to all of them — coverage, as-of block, reason codes, idempotency — are in the overview rather than repeated here.
Sentinel — screening
Screen an address
Returns a weighted risk score, the reason codes behind it, sanctions state and an evidence reference. Repeat screens of the same address within 24 hours are served from cache and billed once.
| Parameter | Type | Notes |
|---|---|---|
| chain | string, required | ethereum · solana · tron · base · arbitrum · polygon · bsc |
| address | string, required | Checksummed or lowercase. Validated per chain. |
| trace_depth | integer, 1–6 | Hops to walk. Default 4. Higher is slower and finds more distant exposure. |
| include_evidence | boolean | Default true. Set false to skip evidence generation and shave latency. |
{
"chain": "ethereum",
"address": "0x7a25…f3b1",
"trace_depth": 4
}{
"risk_score": 71,
"band": "elevated",
"reasons": [ { "code": "MIXER_PROXIMITY",
"weight": 34, "hops": 2 } ],
"sanctions": { "match": false },
"as_of_block": 20914773,
"coverage": { "chains": ["ethereum"] },
"evidence_url": "…/evidence/ev_3f…"
}Screen a transaction
Screens both sides of a transfer plus the path between them. Use this rather than two address calls when you care about the transfer itself — it costs less than two calls and returns path-specific reasons an address screen cannot.
| Parameter | Type | Notes |
|---|---|---|
| tx_hash | string, required | Transaction hash. Must exist on the named chain. |
| perspective | string | Which side you are. sender · receiver. Default inferred from your registered addresses. |
{
"chain": "tron",
"tx_hash": "9f2c…a410"
}{
"risk_score": 44,
"band": "watch",
"direction": "inbound",
"counterparty": { "address": "TQ8x…v2",
"cluster": "exchange-deposit",
"confidence": 0.91 },
"reasons": [ … ],
"as_of_block": 65310022
}Retrieve an evidence trail
Resolves the evidence reference from a score into the transfer paths that produced each reason code. Retained for 12 months by default; this is what you hand an auditor.
GET /v1/screen/evidence/ev_3f… Authorization: Bearer …
{
"score_at_issue": 71,
"issued_at": "2026-07-30T09:12:44Z",
"paths": [
{ "reason": "MIXER_PROXIMITY",
"transfers": [ { "tx": "0x4c…", "value": "12.4",
"asset": "ETH" }, … ] }
]
}Batch screen
Up to 10,000 addresses per submission, processed asynchronously. Use for onboarding backfills rather than looping the single-address endpoint.
{
"chain": "ethereum",
"addresses": ["0x7a…", "0x91…", …],
"callback_url": "https://yourapp/hooks/batch"
}{
"batch_id": "bat_8Kq…",
"accepted": 9841,
"rejected": 159,
"status": "processing"
}CreditGraph — credit
Build a credit profile
Reconstructs borrowing history across supported lending protocols and returns underwriting signals. Returns thin_file: true rather than a fabricated grade where history is too sparse.
| Parameter | Type | Notes |
|---|---|---|
| lookback_days | integer | Default 540. Use 0 for full available history. |
| as_of | string, RFC 3339 | Point-in-time replay: the profile as it would have been on this date. Essential for fair backtesting. |
| protocols | array | Restrict to named protocols. Default all supported. |
{
"chain": "ethereum",
"address": "0x91cd…8ee0",
"lookback_days": 540
}{
"tier": "B+",
"signals": {
"repayment_events": 47,
"repayment_ratio": 0.98,
"liquidations_suffered": 1,
"min_health_factor_90d": 1.34,
"protocol_concentration": 0.62
},
"thin_file": false,
"as_of_block": 20914773
}List open positions
Current borrows, collateral and health factors per protocol. Useful for monitoring an existing book rather than underwriting a new one.
GET /v1/credit/positions ?chain=ethereum&address=0x91cd…8ee0
{
"positions": [
{ "protocol": "aave-v3", "borrowed_usd": "412000.00",
"collateral_usd": "690000.00",
"health_factor": 1.41 }
],
"aggregate_health_factor": 1.41
}Monitor a wallet
Registers a wallet for continuous monitoring. Deterioration in health factor, a new liquidation or a concentration shift fires a webhook.
{
"chain": "ethereum",
"address": "0x91cd…8ee0",
"alert_on": { "health_factor_below": 1.15 }
}{
"monitor_id": "mon_2Bd…",
"active": true
}PayRoute — routing
Quote settlement routes
Ranked routes with itemised landed cost. Every candidate destination is screened first; routes that fail screening appear in withheld[] with a reason, never silently omitted.
| Parameter | Type | Notes |
|---|---|---|
| amount | string, required | Decimal string. Never a float. |
| rank_by | string | landed_cost · speed · custom. Custom uses your contracted weights. |
| max_chains | array | Restrict candidates. Combine with a bridge allowlist for tight control. |
{
"asset": "USDT",
"amount": "250000.00",
"destination": { "chain": "tron",
"address": "TQ8x…v2" },
"rank_by": "landed_cost"
}{
"quote_id": "qte_5Hn…",
"routes": [
{ "rank": 1, "chain": "tron",
"landed_cost_usd": "3.41",
"eta_seconds": 55, "risk_band": "clear" }
],
"withheld": [],
"quote_expires_at": "2026-07-30T11:42:06Z"
}Execute against a quote
Executes the chosen route. Requires an Idempotency-Key; a retry with the same key returns the original result rather than sending twice. Executing after quote expiry fails rather than re-pricing silently.
Idempotency-Key: payout-20614
{
"quote_id": "qte_5Hn…",
"route_rank": 1
}{
"payout_id": "pay_9Cm…",
"status": "submitted",
"tx_hash": "9f2c…a410",
"quoted_cost_usd": "3.41"
}Payout status
Confirmation depth and final on-chain cost against what was quoted. This is the record you reconcile against.
GET /v1/route/payouts/pay_9Cm…
{
"status": "settled",
"confirmations": 41,
"actual_cost_usd": "3.38",
"quoted_cost_usd": "3.41",
"settled_at": "2026-07-30T11:38:02Z"
}Ledger Mind — treasury
Period reconciliation
Matched totals, unmatched items with a suggested cause, and every multisig policy event in the window. An approved_by of null is a signer change with no recorded approval — alert on it.
| Parameter | Type | Notes |
|---|---|---|
| period | string, required | YYYY-MM. Must be a period you have mapped. |
| include_matched | boolean | Default false. True returns all matched pairs — large payload. |
GET /v1/treasury/reconciliation ?period=2026-06
{
"period": "2026-06",
"matched": { "count": 1841,
"value_usd": "48219004.11" },
"unmatched": [
{ "kind": "on_chain_only", "tx": "0x4c1a…",
"suggestion": "fee rebate — no ledger entry" }
],
"policy_events": [
{ "kind": "SIGNER_ADDED", "approved_by": null }
],
"close_pack_url": "…/close/2026-06.pdf"
}Map an address
Registers a wallet, multisig or exchange sub-account against your chart of accounts. Internal-transfer pairs declared here stop treasury movement being counted as revenue.
{
"chain": "solana",
"address": "7xKX…9fT",
"label": "Ops hot wallet",
"gl_account": "1120",
"internal": true
}{
"address_id": "adr_4Tp…",
"watching": true,
"backfill_started": true
}Resolve an exception
Records who resolved an unmatched item and how. Appends to an immutable audit log and regenerates the close pack.
{
"resolution": "matched_manually",
"ledger_entry": "JE-20614",
"note": "Posted to wrong wallet, corrected."
}{
"resolved": true,
"resolved_by": "u_88Kd…",
"close_pack_regenerated": true
}Versioning headers
| Header | Purpose |
|---|---|
| X-FTAI-Scoring-Version | Pin the Sentinel scoring methodology. Omit for current. Pinned versions are supported for the window announced in the changelog. |
| Idempotency-Key | Required on execute, accepted on any state-changing call. Retained 24 hours. |
| X-FTAI-Request-Id | Returned on every response. Quote it in support requests — it resolves to the exact call. |
| X-FTAI-RateLimit-* | Remaining and Reset on every response including errors. See errors and limits. |