Skip to main content

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.

There is no 1delta SDK

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": [] }
}
FieldMeaning
dataInformation: market data, quotes, simulations, positions. null when an endpoint only produces calldata.
actionsWork for you to do on-chain. null on every /v1/data/* endpoint.
actions.permissionsApprovals that must be mined first. Already filtered against on-chain state, so anything returned is genuinely missing.
actions.transactionsThe transactions to send after the approvals.
actions.alternativesPresent 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:

accountResult
omittedQuote only. data.quotes holds routes and price impact; actions is null. Nothing is built.
providedFull 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

  1. Branch on success, not on the HTTP status. A missing parameter currently surfaces as 502, not 400.
  2. Amounts are raw integers as strings. 10 USDC is "10000000", not "10".
  3. Chain ids are decimal strings. "1", not 1.
  4. Lender ids are upper snake case. AAVE_V3, never aave-v3 — see Market identifiers.
  5. slippage is basis points. 50 = 0.5%. Passing 0.5 means 0.005%, and your transaction will revert.
  6. Approvals before actions, each one mined.
  7. Exactly one of alternatives.
  8. 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:

FileContents
/llms.txtIndex of every page and endpoint, ~16 KB.
/llms-full.txtEvery endpoint, parameter, field and example as plain text.
/openapi.jsonOpenAPI 3.1 — generate a typed client from it.

Next