Quickstart
Four HTTP calls take you from nothing to a mined deposit. Every request below is real and runnable as-is — no SDK, no API key, no wallet connection needed until the last step.
The API is plain HTTP + JSON. Use fetch, curl, requests, or anything else
that speaks HTTP. Any code you see referencing an onedelta or @1delta/sdk
package is not real.
The shape of every response
Before anything else, learn the envelope — it is identical on all 100+ endpoints.
{
"success": true,
"data": { },
"actions": { "transactions": [], "permissions": [] }
}
| Field | Meaning |
|---|---|
data | Information: market data, quotes, simulations, positions. null when an endpoint only produces calldata. |
actions | Work for you to do on-chain. null on every /v1/data/* endpoint. |
actions.permissions | Approvals that must be mined first. Already filtered against on-chain state, so anything returned is genuinely missing. |
actions.transactions | The transactions to send after the approvals. |
actions.alternatives | Present on loop and swap endpoints: competing DEX routes, best output first. Pick exactly one. |
On failure:
{
"success": false,
"error": { "code": "MISSING_PARAM", "message": "marketUid is required" }
}
Branch on success, never on the HTTP status code — see Errors & retries.
1. Find a market
Markets are addressed by a marketUid, formatted lender:chainId:address.
List the pools on a chain for one lender:
curl "https://portal.1delta.io/v1/data/lending/pools?chainId=1&lender=AAVE_V3"
{
"success": true,
"data": {
"start": 0,
"count": 45,
"items": [
{
"marketUid": "AAVE_V3:1:0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
"chainId": "1",
"lenderKey": "AAVE_V3",
"name": "Aave V3 WETH",
"depositRate": 1.41624773,
"variableBorrowRate": 2.0744452,
"utilization": 0.8005563978698457,
"totalDepositsUsd": 4033189395.3983254,
"totalLiquidityUsd": 705855814.4854279
}
]
},
"actions": null
}
Rates are percentages (1.416… is 1.42% APR), and utilization is a
fraction between 0 and 1. Drop the lender parameter to compare every protocol
on the chain at once — that comparison is the whole point of the aggregation
layer, and the response shape is identical for all 185 of them.
2. Build the transaction
Pass the marketUid, a raw on-chain amount, and the address that will sign:
curl "https://portal.1delta.io/v1/actions/lending/deposit\
?marketUid=AAVE_V3:1:0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2\
&amount=1000000000000000000\
&operator=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"
amount is always in the token's smallest unit — 1000000000000000000 is 1 WETH
at 18 decimals. Never send a decimal string.
{
"success": true,
"data": {
"simulation": {
"pre": { "healthFactor": 1000000000000000000, "borrowCapacity": 0 },
"post": { "healthFactor": 1000000000000000000, "borrowCapacity": 1499.1354 }
}
},
"actions": {
"transactions": [
{
"to": "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2",
"data": "0x617ba037000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa960450000000000000000000000000000000000000000000000000000000000000000",
"value": "0"
}
],
"permissions": [
{
"to": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
"data": "0x095ea7b300000000000000000000000087870bca3f3fd6335c3f4ce8392d69350b4fa4e20000000000000000000000000000000000000000000000000de0b6b3a7640000",
"value": "0",
"description": "Approve for AAVE_V3",
"type": "ERC20"
}
]
}
}
The API never signs and never broadcasts. It hands you calldata; sending it is your job.
3. Execute, in order
permissions first — each one mined — then the entries in transactions.
Sending the deposit before the approval is mined is the single most common
integration bug, and it reverts.
import { createWalletClient, http } from "viem";
import { mainnet } from "viem/chains";
const BASE = "https://portal.1delta.io";
const res = await fetch(
`${BASE}/v1/actions/lending/deposit?` +
new URLSearchParams({
marketUid: "AAVE_V3:1:0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
amount: "1000000000000000000",
operator: account.address,
})
);
const body = await res.json();
if (!body.success) throw new Error(`${body.error.code}: ${body.error.message}`);
const client = createWalletClient({ account, chain: mainnet, transport: http() });
// Approvals must be mined before the action transaction is sent.
for (const permission of body.actions.permissions ?? []) {
const hash = await client.sendTransaction({
to: permission.to,
data: permission.data,
value: BigInt(permission.value),
});
await client.waitForTransactionReceipt({ hash });
}
for (const tx of body.actions.transactions ?? []) {
await client.sendTransaction({
to: tx.to,
data: tx.data,
value: BigInt(tx.value),
});
}
to, data and value are already encoded. Pass them straight through — do not
re-encode, re-pack, or "fix" the calldata.
4. Read the position back
curl "https://portal.1delta.io/v1/data/lending/user-positions\
?chainId=1&account=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"
Quote first, then build
Loop and swap endpoints have two modes, selected by whether you send account:
account | Result |
|---|---|
| omitted | Quote only. data.quotes holds routes and price impact; actions is null. Nothing is built. |
| provided | Full build. actions is populated with calldata ready to send. |
So you can price a leveraged position without a wallet:
curl "https://portal.1delta.io/v1/actions/loop/leverage\
?marketUidIn=AAVE_V3:1:0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48\
&marketUidOut=AAVE_V3:1:0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2\
&debtAmount=1000000000&slippage=50"
marketUidIn is the debt side, marketUidOut the collateral side.
slippage is in basis points — 50 means 0.5%.
When you add account, the response carries actions.alternatives: several
aggregator routes, sorted best-output-first. Execute one. Sending two is
sending the position twice.
Rules that will save you a debugging session
- Branch on
success, not on the HTTP status. A missing parameter currently surfaces as502, not400. - Amounts are raw integers as strings.
10 USDCis"10000000", not"10". - Chain ids are decimal strings.
"1", not1. - Lender ids are upper snake case.
AAVE_V3, neveraave-v3— see Market identifiers. slippageis basis points.50= 0.5%. Passing0.5means 0.005%, and your transaction will revert.- Approvals before actions, each one mined.
- Exactly one of
alternatives. - Quotes go stale. Rates and routes move per block. Build, then send promptly; re-request rather than reusing a quote from minutes ago.
Feeding this API to a coding agent
The endpoint pages on this site render their parameters and schemas in the browser, so fetching the HTML does not reveal them. Point tooling at these instead — they are static, complete, and need no JavaScript:
| File | Contents |
|---|---|
/llms.txt | Index of every page and endpoint, ~16 KB. |
/llms-full.txt | Every endpoint, parameter, field and example as plain text. |
/openapi.json | OpenAPI 3.1 — generate a typed client from it. |
Next
- Market identifiers —
marketUid, lender ids, chain ids - Errors & retries — codes, status mismatches, backoff
- Looping — what the leverage endpoints do under the hood
- API reference — all 106 endpoints