Skip to main content

Overview

The Actions API handles the transactional lifecycle for deposits on Turtle Earn. The typical flow is: deposit → user signs & submits tx → attribute the tx hash → optionally verify tracking.
All deposit action endpoints require the user to be a Turtle member. Make sure the user has completed the membership flow before calling these endpoints.

Create Deposit

Generate the transactions needed to deposit into an opportunity. The response contains an ordered list of transactions the user must sign and submit (e.g., approve + deposit).
curl -X POST "https://earn.turtle.xyz/v1/actions/deposit/{opportunityId}" \
  -H "Content-Type: application/json" \
  -d '{
    "userAddress": "0x1234...",
    "tokenIn": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
    "amount": "1000000",
    "distributorId": "your-distributor-id",
    "mode": "direct",
    "slippageBps": 50
  }'
Path Parameters
opportunityId
uuid
required
The unique identifier of the opportunity to deposit into. Get this from the Opportunities API.
Body Parameters
userAddress
string
required
The user’s EVM wallet address. Must belong to a registered Turtle member.
tokenIn
string
required
The address of the token being deposited. Must be a supported token on the opportunity’s chain. Cannot be the vault’s receipt token.
amount
string
required
The deposit amount in the token’s smallest unit (wei). Must be greater than 0.
distributorId
string
required
Your distributor ID for attribution tracking.
mode
string
default:"direct"
Deposit mode. Use direct for direct deposits into the vault, or swap to use a DEX router when the input token differs from the vault’s deposit token.
slippageBps
integer
default:"50"
Slippage tolerance in basis points when using swap mode. For example, 50 = 0.5% slippage.
referralCode
string
Optional referral code for deposit attribution.
Response
{
  "actionId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "transactions": [
    {
      "type": "approve",
      "transaction": {
        "to": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
        "data": "0x095ea7b3000000000000000000000000...",
        "value": "0",
        "gasLimit": "60000",
        "chainId": 1
      },
      "description": "Approve USDC spending"
    },
    {
      "type": "deposit",
      "transaction": {
        "to": "0x...",
        "data": "0x...",
        "value": "0",
        "gasLimit": "250000",
        "chainId": 1
      },
      "description": "Deposit USDC into vault"
    }
  ]
}

Transaction Object

Each transaction in the transactions array contains:
type
string
required
Transaction type: approve, swap, or deposit.
transaction
object
required
The raw transaction data to sign and submit.
transaction.to
string
required
Target contract address.
transaction.data
string
required
Encoded calldata (hex string with 0x prefix).
transaction.value
string
required
Value in wei. Usually "0" for token deposits; non-zero for native token deposits.
transaction.gasLimit
string
required
Estimated gas limit.
transaction.chainId
integer
required
Chain ID for the transaction.
description
string
required
Human-readable description of what this transaction does.
metadata
object
Optional metadata for swap transactions, including provider info, amount out, gas estimate, and route details.

Complete Example

Here’s a full deposit flow from start to finish:
// 1. Create the deposit action
const depositResponse = await fetch(
  `https://earn.turtle.xyz/v1/actions/deposit/${opportunityId}`,
  {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      userAddress: walletAddress,
      tokenIn: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
      amount: '1000000000', // 1000 USDC
      distributorId: 'your-distributor-id',
      mode: 'direct',
    }),
  }
);
const { actionId, transactions } = await depositResponse.json();

// 2. Sign and submit each transaction in order
let lastTxHash: string;
for (const tx of transactions) {
  const txResponse = await wallet.sendTransaction(tx.transaction);
  await txResponse.wait(); // Wait for confirmation
  lastTxHash = txResponse.hash;
}

// 3. Attribute the final transaction hash to the action
await fetch(
  `https://earn.turtle.xyz/v1/actions/attribute/${actionId}`,
  {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ txHash: lastTxHash }),
  }
);

Error Handling

Status Code: 403 Forbidden
{
  "error": "not_a_member",
  "message": "User is not a Turtle member. Please complete the membership flow first.",
  "docsUrl": "https://docs.turtle.club/sdk/earn-api/membership"
}
Solution: Complete the membership flow before calling action endpoints.
Status Code: 404 Not Found
{
  "error": "distributor_not_found",
  "message": "Distributor not found with the provided ID"
}
Solution: Verify your distributor ID is correct and active.
Status Code: 404 Not Found
{
  "error": "opportunity_not_found",
  "message": "Opportunity not found"
}
Solution: Check the opportunity ID using the Opportunities API.
Status Code: 400 Bad Request
{
  "error": "deposits_disabled",
  "message": "Deposits are disabled for this opportunity"
}
Solution: This opportunity has temporarily disabled deposits. Try a different opportunity.
Status Code: 400 Bad Request
{
  "error": "invalid_token",
  "message": "Token 0x... not supported for chain 1"
}
Solution: Use a supported deposit token. Check the opportunity’s depositTokens array.
  • Attribute - Link an on-chain transaction hash to a tracked action
  • Verify - Verify that a transaction contains valid Turtle tracking data
  • Opportunities API - Discover available opportunities and their IDs
  • Membership API - Register users before they can deposit
  • Deposits API - Track deposits after they’re completed