Skip to main content
Action endpoints require the user to be a registered Turtle member.
Some vaults do not settle a deposit in one transaction. They queue it, process it on their own schedule, and only then is the position active. For those vaults the user has a follow-up decision once funds are pending: claim to finalize, or cancel to take the funds back. Both branches start from the same pending state and live on this page. This applies only to opportunities with complex settlement (for example Mellow and Lagoon). Standard instant vaults never reach a pending state. See Deposit modes for how to detect which kind you are dealing with.

Overview

POST /v1/actions/claim-deposit/{opportunityId} POST /v1/actions/cancel-deposit/{opportunityId} A pending deposit resolves exactly once. After the vault processes the queued funds, call claim-deposit to finalize the position; before processing completes, call cancel-deposit to return the funds to the user. Both endpoints take the same path parameter and body, and each returns an actionId and an ordered transactions array to sign and submit.

The pending-deposit state machine

StateHow it got hereWhat you can do
PendingUser deposited into a complex vault; the vault has queued the funds.Wait for the vault to process, or cancel to recover funds now.
ProcessedThe vault finished processing the queued deposit.Claim to finalize the position.
ClaimedThe user claimed the processed deposit.Done. The position is active.
CancelledThe user cancelled before processing completed.Done. Funds returned to the user.
Claim and cancel are mutually exclusive resolutions of the same pending deposit. Both endpoints take only the user’s address and your distributor ID, because the vault already holds the pending-deposit details keyed to that wallet.

Detect a pending deposit

A deposit is pending only when the opportunity is complex. Read the deposit-steps type off the opportunity object before assuming a claim is needed.

Claim to finalize

Once the vault has processed the queued deposit, generate the claim transaction to finalize the position. POST /v1/actions/claim-deposit/{opportunityId}
curl -X POST "https://earn.turtle.xyz/v1/actions/claim-deposit/{opportunityId}" \
  -H "Content-Type: application/json" \
  -d '{
    "userAddress": "0x1234...",
    "distributorId": "your-distributor-id"
  }'

Response Example

{
  "actionId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "transactions": [
    {
      "type": "claimDeposit",
      "transaction": {
        "to": "0x...",
        "data": "0x...",
        "value": "0",
        "gasLimit": "200000",
        "chainId": 1
      },
      "description": "Claim pending deposit"
    }
  ]
}

Cancel to abort

If the user would rather recover funds than wait for the vault to process the deposit, generate the cancel transaction. Funds are returned to the user. POST /v1/actions/cancel-deposit/{opportunityId}
curl -X POST "https://earn.turtle.xyz/v1/actions/cancel-deposit/{opportunityId}" \
  -H "Content-Type: application/json" \
  -d '{
    "userAddress": "0x1234...",
    "distributorId": "your-distributor-id"
  }'

Response Example

{
  "actionId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "transactions": [
    {
      "type": "cancelDeposit",
      "transaction": {
        "to": "0x...",
        "data": "0x...",
        "value": "0",
        "gasLimit": "200000",
        "chainId": 1
      },
      "description": "Cancel pending deposit"
    }
  ]
}

Shared parameters

Both endpoints take the same path parameter and body. Path Parameters
opportunityId
uuid
required
The opportunity holding the pending deposit. Get it from Get Opportunities.
Body Parameters
userAddress
string
required
The user’s EVM wallet address. Must belong to a registered Turtle member with a pending deposit in this opportunity.
distributorId
string
required
Your distributor ID for attribution tracking.

Response Fields

Both endpoints return the same shape.
actionId
string
required
Unique identifier for this action, returned for both claim and cancel.
transactions
array
required
Ordered array of transactions to sign and submit. Each element follows the Transaction Object shape rendered below; claim returns a single claimDeposit transaction and cancel returns a single cancelDeposit transaction.

Broadcast

Each endpoint returns a single transaction. Sign and submit it.
const { transactions } = await response.json();
const tx = transactions[0];
const txResponse = await wallet.sendTransaction(tx.transaction);
await txResponse.wait();

Transaction Object

Each transaction in the transactions array contains:
type
string
required
Transaction type, e.g. approve, deposit, withdraw, claimDeposit, cancelDeposit.
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 interactions; 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.

Operational Notes

Claim and cancel apply only to opportunities with complex settlement. Instant vaults complete on deposit and have nothing to claim or cancel.
Neither endpoint takes a token or amount. The vault already holds the pending-deposit details keyed to the user’s address, so the request only needs userAddress and distributorId.
A pending deposit resolves once, either to claimed or cancelled. After the vault processes the deposit, claim finalizes it; before processing completes, cancel returns the funds.

Error Handling

Status: 403 Forbidden
{
  "error": "not_a_member",
  "message": "User is not a Turtle member. Please complete the membership flow first.",
  "docsUrl": "https://docs.turtle.xyz/sdk/authentication/register-wallet"
}
Solution: Complete the membership flow first.
Status: 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: 404 Not Found
{
  "error": "opportunity_not_found",
  "message": "Opportunity not found"
}
Solution: Check the opportunity ID with Get Opportunities.

Deposit

Generate the initial deposit that may go async.

Deposit modes

How to tell instant vaults from complex ones.