🖥️API Docs

You can use the Lulo API to fetch a user's deposit information (configured protocols, and latest balances), as well as create deposit and withdrawal transactions for an account.

Authentication

All API requests require a valid API key for authentication, reach out to us to permission an API Key for your team

headers: {
    'x-api-key': process.env.FLEXLEND_API_KEY,
},

GET /account : list a user account information

  • The wallet parameter should be added as a header into the GET specified with a header in the request

bash - get account
curl "https://api.flexlend.fi/account"  \
--header "x-wallet-pubkey: 6pZiqTT81nKLxMvQay7P6TrRx9NdWG5zbakaZdQoWoUb"  \
--header "x-api-key: ${FLEXLEND_API_KEY}"
TS - get account
const response = await fetch(`https://api.flexlend.fi/account`, {
	headers: {
		'x-wallet-pubkey': wallet.toString(),
		'x-api-key': process.env.FLEXLEND_API_KEY,
	},
})

const { data } = await response.json()

console.log(data)

Response:

{
    "totalValue": 434.28859145610005,
    "interestEarned": 19.369569777759786,
    "realtimeAPY": 7.69,
    "settings": {
      "owner": "6pZiqTT81nKLxMvQay7P6TrRx9NdWG5zbakaZdQoWoUb",
      "allowedProtocols": "solend,marginfi,drift,mango",
      "homebase": null,
      "minimumRate": "0",
  }

Generate APIs

Generate API's abstract the complexity of interacting with the underlying protocols when depositing or withdrawing. These APIs handle all the calculations for certain functionality, and return the resulting transactions as base64 serialized strings. The strings can be unwrapped and signed by the sending wallet (owner).

Priority fee is required on all generated transactions, and is specified in terms of total SOL lamports. i.e priorityFee=500_000 will add a 0.0005 SOL priority fee to the transaction

The data model for the response is the same for all of the /generate API's:

{
    "transactionMeta": [
      {
        "transaction": "<serialized_base64_transaction>",
        "protocol": "kamino",
        "totalDeposit": 500
      },
      
      {
        "transaction": "<serialized_base64_transaction>",
        "protocol": "marginfi",
        "totalDeposit": 500
      }
    ]

}

POST /generate/account/deposit

Generate a new deposit transaction (or transactions), which the sending wallet can sign and submit.

TS - deposit request
const request = {
	owner: '6pZiqTT81nKLxMvQay7P6TrRx9NdWG5zbakaZdQoWoUb',
	mintAddress: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
	depositAmount: '500',
}

const priority = `?priorityFee=50000`

const response = await fetch(`https://api.flexlend.fi/generate/account/deposit${priority}`, {
	method: 'POST',
	headers: {
		'Accept': 'application/json',
		'Content-Type': 'application/json',
		'x-wallet-pubkey': '6pZiqTT81nKLxMvQay7P6TrRx9NdWG5zbakaZdQoWoUb',
		'x-api-key': process.env.FLEXLEND_API_KEY,
	},
	body: JSON.stringify(request),
})

const { data: { transactionMeta } } = response.json()

// wallet can deserialize and sign the transactions
conosle.log({ transactionMeta })
bash - deposit request
curl "https://api.flexlend.fi/generate/account/deposit?priorityFee=50000" \
--header "Content-Type: application/json" \
--header "x-wallet-pubkey: 6pZiqTT81nKLxMvQay7P6TrRx9NdWG5zbakaZdQoWoUb"  \
--header "x-api-key: ${FLEXLEND_API_KEY}" \
-d '{
    "owner": "6pZiqTT81nKLxMvQay7P6TrRx9NdWG5zbakaZdQoWoUb",
    "mintAddress": "So11111111111111111111111111111111111111112",
    "depositAmount": "50000"
}'

POST /generate/account/withdraw

Generate a withdrawal transaction (or transactions) for an account, which the sending wallet can sign and submit

bash - withdraw request
curl "https://api.flexlend.fi/generate/account/withdraw?priorityFee=50000" \
--header "Content-Type: application/json" \
--header "x-wallet-pubkey: 6pZiqTT81nKLxMvQay7P6TrRx9NdWG5zbakaZdQoWoUb"  \
--header "x-api-key: ${FLEXLEND_API_KEY}" \
-d '{
    "owner": "6pZiqTT81nKLxMvQay7P6TrRx9NdWG5zbakaZdQoWoUb",
    "mintAddress": "So11111111111111111111111111111111111111112",
    "withdrawAmount": "5",
    "withdrawAll": true
}'

POST /generate/account/update

Generate a transaction that updates the user's settings (protocols, homebase, minimumRate). Returns a single serialized transaction.

curl "https://api.flexlend.fi/generate/account/update?priorityFee=50000" \
--header "Content-Type: application/json" \
--header "x-wallet-pubkey: 6pZiqTT81nKLxMvQay7P6TrRx9NdWG5zbakaZdQoWoUb"  \
--header "x-api-key: ${FLEXLEND_API_KEY}" \
-d '{
    "owner": "6pZiqTT81nKLxMvQay7P6TrRx9NdWG5zbakaZdQoWoUb",
    "allowedProtocols": "marginfi,kamino",
    "homebase": null,
    "minimumRate": null
}'

Instructions Endpoints

Follows the pattern laid out here: https://station.jup.ag/docs/apis/swap-api#instructions-instead-of-transaction

POST /generate/instructions/deposit

const response = await fetch(`https://api.flexlend.fi/generate/instructions/deposit?priorityFee=50000`,{
	method: 'POST',
	headers: {
		Accept: 'application/json',
		'Content-Type': 'application/json',
	},
	body: JSON.stringify({
		owner: '6pZiqTT81nKLxMvQay7P6TrRx9NdWG5zbakaZdQoWoUb',
		mintAddress: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
		depositAmount: '500',
		allowedProtocols: 'drift,kamino,marginfi,solend,kamino_jlp',
		isMultiSigTransaction: true
	}),
})

const instructions = await response.json()

const {
	computeBudgetInstructions, // Required 
	setupInstructions,  // Required
	depositInstructions,  // Required
	addressLookupTableAddresses,  // Always one lookup table: 7fxC1WGaJs8fB9xk8LDdMcsyLcD7geKP7uLGL8qoPDTA
	targetProtocol, // Destination protocol for the deposit transaction
} = instructions

// follow similar jupiter workflow, with one exception:
// compute and setup instructions are arrays and are required:

 const blockhash = (await connection.getLatestBlockhash()).blockhash;
 const messageV0 = new TransactionMessage({
	payerKey: owner,
	recentBlockhash: blockhash,
	instructions: [
	  ...computeBudgetInstructions.map(deserializeInstruction),
	  ...setupInstructions.map(deserializeInstruction),
	  ...depositInstructions.map(deserializeInstruction),
	],
 }).compileToV0Message(addressLookupTableAccounts);
 const transaction = new VersionedTransaction(messageV0);

POST /generate/instructions/withdraw

If the account was initially deposited using the generate/instructions/deposit endpoint, the funds will only be in one protocol at a time

const response = await fetch(`https://api.flexlend.fi/generate/instructions/withdraw?priorityFee=50000`,{
	method: 'POST',
	headers: {
		Accept: 'application/json',
		'Content-Type': 'application/json',
	},
	body: JSON.stringify({
		owner: '6pZiqTT81nKLxMvQay7P6TrRx9NdWG5zbakaZdQoWoUb',
		mintAddress: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
		withdrawAmount: '500',
		withdrawAll: true,

	}),
})

const instructions = await response.json()

const {
	computeBudgetInstructions,  // Required 
	setupInstructions, // Required
	withdrawInstructions, // Required
	addressLookupTableAddresses, // Always one lookup table: 7fxC1WGaJs8fB9xk8LDdMcsyLcD7geKP7uLGL8qoP
	protocol, // Protocol to withdraw from
} = instructions

// follow similar jupiter workflow, with one exception:
// compute and setup instructions are arrays and are required:

 const blockhash = (await connection.getLatestBlockhash()).blockhash;
 const messageV0 = new TransactionMessage({
	payerKey: owner,
	recentBlockhash: blockhash,
	instructions: [
	  ...computeBudgetInstructions.map(deserializeInstruction),
	  ...setupInstructions.map(deserializeInstruction),
	  ...withdrawInstructions.map(deserializeInstruction),
	],
 }).compileToV0Message(addressLookupTableAccounts);
 const transaction = new VersionedTransaction(messageV0);

Last updated