Overview
Returns one ready-to-sign selfBatchDeposit transaction on the
strategy's chain, covering local vault deposits plus per-remote-chain
CCTP burns. The matching intent (kind deposit) is written server-side;
do not post an intent separately. No auth; no request body (the id is
in the path).
Strategy must be pending_setup (top-ups are not supported).
Timing: expiresAt is an advisory ~1h plan-freshness bound. The intent
itself has a 30-day TTL; regenerating an unchanged plan within it returns
the same intentId, and regenerating after expiry or fulfillment mints a
new one. A strategy that has never received a deposit is purged about one
hour after it was last touched, taking its intent with it; calling this
endpoint refreshes that hour. If signing takes longer than an hour (e.g.
a multisig), regenerate at least hourly until the transaction is
broadcast.
Approve vault share tokens and USDC before calling: live allowances
affect vault selection, and approvalsNeeded reflects what is still
missing.
Submit the returned data verbatim (re-encoding breaks intent
attribution) and use gasHint as the gas limit (wallet re-estimates can
run out of gas).
Endpoint
POST https://earn-api.quicknode.dev/functions/v1/api/v1/strategies/{id}/calldata/deposit
Authorization
Include the published apikey header. This endpoint is public and does not require a SIWE signature.
Rate limits
This operation belongs to the calldata rate-limit bucket. It allows 10 requests per 60 seconds, keyed by strategy+ip. A coarser limit of approximately 30 requests per 60 seconds also applies per IP across deposit, withdrawal, and claim calldata requests.
Parameters
| Parameter | Location | Type | Required | Description |
|---|---|---|---|---|
| id | path | string | Yes | Strategy UUID. |
Request body
Deposit calldata request body. Public (no SIWE). The deposit endpoint takes no parameters, so send no body or an empty JSON object ({}).
Example request
curl --request POST \
--url 'https://earn-api.quicknode.dev/functions/v1/api/v1/strategies/<PENDING_STRATEGY_ID>/calldata/deposit' \
--header 'Accept: application/json' \
--header 'apikey: <EARN_PUBLIC_API_KEY>' \
--header 'Content-Type: application/json' \
--data '{}'
Response
| Field | Type | Required | Description |
|---|---|---|---|
| kind | string (deposit) | Yes | Identifies the response as a deposit calldata plan. |
| transactions | array<object> | Yes | Exactly one transaction, on the strategy's chain. |
| approvalsNeeded | array<object> | Yes | Token allowances that must be granted before submitting the deposit transaction. |
| expiresAt | string | Yes | ~1h ADVISORY plan-freshness bound. NOT the intent attribution window (the intent carries a 30-day TTL). Regenerate after this passes; regeneration within the intent TTL returns the same `intentId`. |
| plan | object | Yes | The deposit allocation plan. |
| transactions[].chainId | integer | Yes | Chain on which to submit the transaction. |
| transactions[].to | string | Yes | Quicknode Earn proxy address on `chainId`. |
| transactions[].data | string | Yes | Transaction calldata. Submit it verbatim. |
| transactions[].value | string | Yes | Native-token value. Always `"0"`. |
| transactions[].intentId | string | Yes | Intent UUID used to track the transaction. |
| transactions[].kind | string (deposit) | Yes | Transaction intent kind. |
| transactions[].description | string | Yes | Human-readable transaction summary. |
| transactions[].gasHint | string | null | Yes | Recommended gas limit, or `null` when it cannot be estimated. |
| transactions[].gasHintReason | string | No | `approvals_required` or `estimation_failed` when `gasHint` is `null`. |
| approvalsNeeded[].chainId | integer | Yes | Chain where approval is required. |
| approvalsNeeded[].token | string | Yes | Token contract requiring an allowance. |
| approvalsNeeded[].spender | string | Yes | Quicknode Earn proxy address. |
| approvalsNeeded[].currentAllowance | string | Yes | Current allowance in token base units. |
| approvalsNeeded[].requiredAllowance | string | Yes | Required allowance in token base units. |
| approvalsNeeded[].tx | object | Yes | Ready-to-sign token approval transaction. |
| approvalsNeeded[].tx.to | string | Yes | Token contract receiving the approval call. |
| approvalsNeeded[].tx.data | string | Yes | ABI-encoded approval calldata. |
| approvalsNeeded[].tx.value | string | Yes | Native-token value, normally `"0"`. |
| plan.totalUsdc | string | Yes | Total allocated USDC as a six-decimal base-unit string. |
| plan.vaults | array<string> | Yes | Local-chain vault addresses. |
| plan.amounts | array<string> | Yes | Base-unit amounts aligned with `plan.vaults`. |
| plan.burns | array<object> | Yes | Combined CCTP burns for remote chains. |
| plan.burns[].destDomain | integer | Yes | CCTP destination domain. |
| plan.burns[].mintRecipient | string | Yes | Bytes32-padded mint recipient. |
| plan.burns[].destinationCaller | string | Yes | Bytes32-padded destination caller. |
| plan.burns[].amount | string | Yes | Burn amount in USDC base units. |
| plan.burns[].maxFee | string | Yes | Maximum CCTP fee in base units. |
| plan.burns[].minFinalityThreshold | integer | Yes | Minimum CCTP finality threshold. |
| plan.burnVaultBreakdown | array<array<object>> | Yes | Destination vault allocations aligned with `plan.burns`. |
| plan.burnVaultBreakdown[][].vault | string | Yes | Destination vault address. |
| plan.burnVaultBreakdown[][].amount | string | Yes | Vault allocation in USDC base units. |
| plan.burnVaultBreakdown[][].name | string | Yes | Destination vault name. |
| plan.burnVaultBreakdown[][].apy | number | Yes | Destination vault APY percentage. |
| plan.apys | object | Yes | Map of vault keys to APY percentages. |
| plan.vaultNames | object | Yes | Map of vault keys to vault names. |
| plan.chainIds | object | Yes | Map of vault keys to chain IDs. |
Example response
{
"kind": "deposit",
"transactions": [
{
"chainId": 8453,
"to": "0x48b415841165304f7EfaA7D5dD5FC65cc7B4bd8e",
"data": "0x5a6b7c8d0000000000000000000000000000000000000000000000000000000000000060",
"value": "0",
"intentId": "7f3a1c2b-0000-4000-8000-000000000abc",
"kind": "deposit",
"description": "Deposit $1000 into 2 vault(s), bridging to 1 chain(s)",
"gasHint": "480000"
}
],
"approvalsNeeded": [],
"plan": {
"totalUsdc": "1000000000",
"vaults": ["0x616a4e1db48e22028f6bbf20444cd3b8e3273738"],
"amounts": ["600000000"],
"burns": [
{
"destDomain": 3,
"mintRecipient": "0x00000000000000000000000048b415841165304f7efaa7d5dd5fc65cc7b4bd8e",
"destinationCaller": "0x00000000000000000000000048b415841165304f7efaa7d5dd5fc65cc7b4bd8e",
"amount": "400000000",
"maxFee": "0",
"minFinalityThreshold": 2000
}
],
"burnVaultBreakdown": [
[
{
"vault": "0x1a996cb54bb95462040408c06122d45d6cdb6096",
"amount": "400000000",
"name": "Gauntlet USDC Core",
"apy": 5.117
}
]
],
"apys": {
"8453:0x616a4e1db48e22028f6bbf20444cd3b8e3273738": 6.482,
"42161:0x1a996cb54bb95462040408c06122d45d6cdb6096": 5.117
},
"vaultNames": {
"8453:0x616a4e1db48e22028f6bbf20444cd3b8e3273738": "Seamless USDC Vault",
"42161:0x1a996cb54bb95462040408c06122d45d6cdb6096": "Gauntlet USDC Core"
},
"chainIds": {
"8453:0x616a4e1db48e22028f6bbf20444cd3b8e3273738": 8453,
"42161:0x1a996cb54bb95462040408c06122d45d6cdb6096": 42161
}
},
"expiresAt": "2026-07-07T19:00:00.000Z"
}
HTTP responses
| Status | Description |
|---|---|
| 200 | One deposit transaction, approvals needed, plan transparency, and an advisory expiry. |
| 400 | One of: the strategy is not `pending_setup` (`invalid_state`); no eligible vaults (`no_eligible_vaults`); gas estimation failed (`gas_estimation_failed`, the tx would revert, usually unfunded or unapproved); or a malformed JSON body (`invalid_request`). |
| 404 | Resource not found. |
| 429 | Rate limit exceeded. `Retry-After` (seconds) tells you when to retry. Reads, feedback, and push writes are keyed per IP; create/update/delete are keyed per wallet+IP; deposit/withdraw/claim calldata is keyed per strategy+IP. |
| 500 | Internal error, or `burn_route_unavailable` when a required remote chain has no CCTP burn route configured. |
| 503 | The hide list could not be loaded (`hide_lookup_failed`, fails closed). |
This page is based on operation depositCalldata in the Earn OpenAPI 3.1 specification.