API Agent Acceptance Run¶
This page is the end-to-end acceptance artifact for the JustLend DAO API: proof that an agent with nothing but the docs and an HTTP client can call the API and get responses matching the documented contract (justlend_apis.yaml).
- What it exercises: every anonymous GET read endpoint (no wallet, no key, no auth) plus the V1 and V2 error contracts.
- How to reproduce: from the repo root, run
node scripts/api-acceptance.mjs(Node ≥ 18, read-only, ~8 GET requests). Exit code0means every assertion holds. - Status: 8/8 probes passed on the last run. If a re-run fails, the live service has drifted from the documented contract — update
apis.mdand the YAML, and record the new run here.
Last verified run¶
JustLend API agent acceptance — 2026-07-15T08:09:17.239Z — base https://openapi.just.network
PASS V1 market list HTTP 200 /lend/jtoken
PASS V1 sTRX + Energy Rental dashboard HTTP 200 /lend/strx
PASS V1 mining APY map HTTP 200 /mining/apy
PASS V1 high-risk account list HTTP 200 /justlend/liquidate/highRiskAccountList
PASS V2 vault list HTTP 200 /v2/index/vault/list
PASS V2 market list HTTP 200 /v2/index/market/list
PASS V1 error contract (unknown path) HTTP 200 /lend/nonExistentXYZ
PASS V2 error contract (missing params) HTTP 200 /v2/vault/position
8/8 endpoint probes passed.
What each probe asserts¶
| Probe | Endpoint | Key assertions |
|---|---|---|
| V1 market list | /lend/jtoken |
HTTP 200; code: 0, message: "SUCCESS"; tokenList ≥ 20 entries; supplyRate/cash/exchangeRate are decimal strings; borrowIndex is a BigInt-safe integer string; underlyingDecimal is a JSON integer. |
| V1 sTRX dashboard | /lend/strx |
code: 0; stakeInfo.reserves present as decimal string (key renamed from the historical reserse); stakeInfo.decimal serialized as the string "18"; rentInfo prices are decimal strings. |
| V1 mining APY | /mining/apy |
code: 0; one key per market (≥ 20); every value is { "USDD": "<decimal string>" }. |
| V1 high-risk list | /justlend/liquidate/highRiskAccountList |
code: 0; jtokens is a plain object map (not an array); updateTime epoch-ms integer; account entries carry string risk / USD fields and integer liquidateStatusStartTime. |
| V2 vault list | /v2/index/vault/list |
HTTP 200; code: 200, message: "Success" (V2 success code); top-level timestamp; allVaults.list entries have string tvl/apy and array tags/markets/allocations; user-scoped fields are null without address. |
| V2 market list | /v2/index/market/list |
code: 200; the key is allMarkets; id matches 0x… bytes32; lltv is a decimal string; ltv/risk/loanAmount are null without address. |
| V1 error contract | /lend/nonExistentXYZ |
HTTP 200 even for errors; body code: 404 with a message; data omitted. |
| V2 error contract | /v2/vault/position (missing params) |
HTTP 200 even for errors; body code ≠ 200 (observed 202); data: null; timestamp still present. |
Recorded real responses (truncated)¶
Captured 2026-07-15 with plain curl — no headers, no auth.
1. GET /lend/jtoken — first of 24 entries¶
{
"code": 0,
"message": "SUCCESS",
"data": {
"tokenList": [
{
"address": "TE2RzoSV3wFK99w6J9UnnZ4vLfXYoxvRwP",
"symbol": "jTRX",
"underlyingSymbol": "TRX",
"underlyingAddress": "T9yD14Nj9j7xAB4dbGeiX9h8unkKHxuWwb",
"underlyingPriceInTrx": "1.000000000000000000000000000",
"underlyingDecimal": 6,
"reserveFactor": "0.100000000000000000",
"collateralFactor": "0.750000000000000000",
"supplyRate": "0.004196584241280000",
"borrowRate": "0.047954914361424000",
"exchangeRate": "0.010582523128618106",
"cash": "2021157853.515481000000000000",
"totalBorrows": "217298348.792278000000000000",
"totalSupply": "211176098544.66409163",
"reserves": "3680255.247515000000000000",
"borrowIndex": "1361223278609682980"
}
]
}
}
2. GET /v2/index/market/list — first of 9 markets (anonymous, so user fields are null)¶
{
"code": 200,
"message": "Success",
"data": {
"userMarketsCount": 0,
"allMarketsCount": 9,
"userMarkets": [],
"allMarkets": [
{
"id": "0x8fa76896548f751c9009583976933e6cb355513a180548df5d47b1833d20cb17",
"ltv": null,
"lltv": "0.800000000000000000",
"risk": null,
"liquidity": "113190.228074",
"liquidityUsd": "113190.228074000000000000",
"loanSymbol": "USDT",
"loanAddress": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
"loanAmount": null,
"loanUsd": null,
"borrowRate": "0.000250508418242629",
"collateralSymbol": "USDD",
"collateralAddress": "TXDk8mbtRbXeYuMNS83CfKPaYYT8XWv9Hz",
"collateralAmount": null,
"collateralUsd": null,
"collateralDecimals": 18,
"tags": []
}
]
},
"timestamp": 1784101532797
}
3. Error contracts — business errors ride on HTTP 200¶
GET /lend/nonExistentXYZ → HTTP 200:
{ "code": 404, "message": "interface [/lend/nonExistentXYZ] non exist" }
GET /v2/vault/position (required params missing) → HTTP 200:
{ "code": 202, "message": "error: Invalid value for field 'address': Invalid format; error: Invalid value for field 'vaultAddress': Invalid format", "data": null, "timestamp": 1784101590046 }
Notes for agents¶
- Branch on the body
code(0= success on V1,200on V2), never on the HTTP status (apis.md §1.6). - Parse all decimal quantities as strings with big-decimal/BigInt (apis.md §1.3).
- Account-scoped endpoints (
/lend/account?addresses=…,/mining/reward?address=…,/mining/distributions?addr=…,/v2/*/position) were also verified with a live wallet during the same session; note theaddrparameter quirk on/mining/distributions. - The script intentionally avoids provoking
429s; rate-limit behavior is documented in apis.md §1.7.