Calldata
Ready-to-sign deposit/withdraw/emergency-claim transaction generation.
/v1/strategies/{id}/calldata/depositGenerate deposit calldata (public, no SIWE)
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.
Two modes. No body (or {}): the first-funding flow: strategy must
be pending_setup. Body amountUsdc: a TOP-UP into an active,
uncovered strategy: only the new amount is planned. Gates: a 10 USDC
floor on the total; every bridged portion must clear 20x its LIVE
relay cost (priced by the same relayAndDeposit simulation the
rebalance fee engine uses); an in-flight-transfer guard; a 24/hour
per-strategy limit. Covered strategies reject top-ups
(covered_topup_not_available) until the covered phase ships. While
the partial rollout flag is off, top-ups return 503
feature_disabled.
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).
Auth: apikey header
Parameters
| Parameter | Type | Description |
|---|---|---|
idpathrequired | string (uuid) | Strategy UUID. |
Request bodyCalldataRequest
| Field | Type | Description |
|---|---|---|
amountUsdc | number | Optional top-up amount in decimal USDC. Requires strategy status
active and an uncovered strategy. Must meet the per-chain
minimum action size (amount_below_minimum otherwise). Rejected
while a bridge transfer is in flight (transfer_in_flight, 409). |
Responses
| Status | Type | Description |
|---|---|---|
200 | DepositCalldataResponse | One deposit transaction, approvals needed, plan transparency, and an advisory expiry. |
400 | ApiError | One of: the strategy is not pending_setup: or, with
amountUsdc, not active (invalid_state); no eligible vaults
(no_eligible_vaults); gas estimation failed
(gas_estimation_failed, the tx would revert, usually unfunded or
unapproved); a malformed JSON body or a non-positive amountUsdc
(invalid_request); a covered strategy top-up
(covered_topup_not_available); or a top-up under the per-chain
minimum action size (amount_below_minimum). |
404 | ApiError | Resource not found. |
409 | ApiError | A bridge transfer for this strategy is still settling
(transfer_in_flight): top-ups only. Retry after it confirms. |
429 | ApiError | 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 | ApiError | Internal error, or burn_route_unavailable when a required remote
chain has no CCTP burn route configured. |
503 | ApiError | The hide list could not be loaded (hide_lookup_failed, fails
closed), or gas/price data for the top-up minimum-action gate is
unavailable (pricing_unavailable, fails closed). |
/v1/strategies/{id}/calldata/withdrawGenerate withdraw/close calldata (public, no SIWE)
Returns one ready-to-sign selfBatchWithdraw transaction per chain,
source chain first then ascending chain id. Sign and submit in that
order, data verbatim. Paused and zero-share positions are excluded.
Each transaction has its own intentId (kind close), written
server-side. No auth; no status gate. Optional chainIds in the JSON
body restricts the plan to those chains.
If nothing is withdrawable, transactions is [] and fallback is
"delete": close via DELETE /v1/strategies/{id} instead.
PARTIAL withdrawals: body amountUsdc withdraws that gross amount
pro-rata across positions (intents kind partial_withdraw, standard
30-day TTL). Requires an active, uncovered strategy; the FLOOR /
90% / minimum-action gates, an in-flight-transfer guard, and a
24/hour per-strategy limit apply. Each remote chain's relay fee is
withheld in shares inside that chain's own transaction
(partial.feeUsdc is the total; the wallet receives
partial.receiveUsdc). Body quote: true returns the policy
numbers (withdraw_quote) without writing intents. While the
partial rollout flag is off, both forms return 503
feature_disabled.
expiresAt and intent TTL semantics match the deposit endpoint (the
pre-deposit purge does not apply). The fee quote is priced at plan
time: regenerate past expiresAt rather than signing a stale plan.
Auth: apikey header
Parameters
| Parameter | Type | Description |
|---|---|---|
idpathrequired | string (uuid) | Strategy UUID. |
Request bodyWithdrawCalldataRequest
| Field | Type | Description |
|---|---|---|
chainIds | array of integer | Optional subset of chain ids to withdraw from. Omit to close all chains. Cannot be combined with amountUsdc. |
amountUsdc | number | Optional PARTIAL withdrawal amount in decimal USDC (gross: the
wallet receives amountUsdc minus the network fee). Requires an
active, uncovered strategy. Constraints: at least the per-chain
minimum action size; at most min(90% of live value, live value − FLOOR) where FLOOR is the most expensive enabled-chain minimum
(below_chain_minimum / amount_below_minimum otherwise). |
quote | boolean | When true, returns the partial-withdraw policy numbers
(withdraw_quote response) without writing any intent.
amountUsdc is ignored in quote mode. |
Responses
| Status | Type | Description |
|---|---|---|
200 | WithdrawCalldataResponse | WithdrawQuoteResponse | Per-chain withdraw transactions (source-first), approvals needed, plan
transparency, and an advisory expiry. May be an empty plan with a
fallback hint. |
400 | ApiError | A malformed JSON body or a bad chainIds value (invalid_request),
or a chainIds subset that matches no withdrawable position
(no_positions_for_chains). Partial withdrawals also return:
covered_withdraw_not_available (covered strategies close only);
invalid_state (strategy not active); amount_below_minimum
(under the minimum action size, or too small after the network
fee); below_chain_minimum (the remainder would fall under the
enabled-chain FLOOR, the amount exceeds the 90% cap, or the
strategy is too small for any partial: full close only). |
404 | ApiError | Resource not found. |
409 | ApiError | A bridge transfer for this strategy is still settling
(transfer_in_flight): partial withdrawals only. |
429 | ApiError | 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 | ApiError | Internal server error. |
503 | ApiError | Gas/price data for the partial-withdraw gates or fee quote is
unavailable (pricing_unavailable, fails closed). |
/v1/strategies/{id}/calldata/claimGenerate emergency CCTP claim calldata (public, no SIWE)
Escape hatch for a stalled deposit bridge leg: fetches the finalized
Circle attestation and returns one ready-to-sign emergencyClaimBridge
transaction on the destination chain. Minted USDC goes directly to the
burn-time beneficiary's wallet, bypassing the destination vault deposit.
The matching intent (kind emergency_claim) is written server-side. No
auth.
Eligibility (each failure is a 400 invalid_state): the transfer must be
a deposit leg, not already confirmed or user_claimed, at least 30
minutes old, and its recorded beneficiary must be the strategy owner. If
Circle has not finalized the attestation, the response is a 409
attestation_pending; poll on that status code.
approvalsNeeded is always []. expiresAt is nominal: the claim stays
valid until the message nonce is consumed on the destination chain. A
null gasHint with estimation_failed can mean the nonce was already
consumed (the transfer completed normally); the on-chain result is
authoritative.
Auth: apikey header
Parameters
| Parameter | Type | Description |
|---|---|---|
idpathrequired | string (uuid) | Strategy UUID. |
Request bodyClaimCalldataRequest, required
| Field | Type | Description |
|---|---|---|
transferIdrequired | string (uuid) | The stalled transfer's cctp_transfers row id (find it via GET /v1/strategies/{id}/bridges). |
Responses
| Status | Type | Description |
|---|---|---|
200 | ClaimCalldataResponse | One emergency-claim transaction on the destination chain. |
400 | ApiError | A malformed JSON body or transferId (invalid_request), or the
transfer is not claimable (invalid_state: already terminal, not
deposit-shaped, not 30 minutes old yet, or the beneficiary does
not match the strategy owner). |
404 | ApiError | Strategy not found (not_found), or no such CCTP transfer for this
strategy (transfer_not_found; also returned when the transfer
belongs to another strategy). |
409 | ApiError | Attestation not finalized yet (attestation_pending). Retry after
Retry-After seconds. |
429 | ApiError | 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 | ApiError | Internal error (including a failed intent write), or
unsupported_chain_pair when the transfer's chain pair has no CCTP
route configured. |