Prerequisites
- A backend with your Yield.xyz project API key and a mapping from your internal account or user identifier to the address your custody platform controls for the target chain.
- A custody, HSM, or MPC signer capable of either returning a signed transaction for you to broadcast, or signing and broadcasting itself.
The pattern
1
Build the action under your project key
Call
POST /v1/actions/enter (or /exit, /manage) with the yieldId, the custody-controlled address, and arguments built from mechanics.arguments.enter.fields. See Discover yields and Enter and exit flows. Log the resulting action.id and each transaction.id against your own internal account or request identifier before doing anything else with them; this is the row your audit trail and any later reconciliation hangs off.2
Validate before it reaches the signer
Run policy checks appropriate to your custody setup, and validate the transaction’s structure with Shield before it’s handed to a signer, so a malformed or unexpected Shield also ships as a standalone binary, callable from any language over stdin and stdout, for a signing process that isn’t Node. See Shield integration.
unsignedTransaction never reaches custody:3
Sign, broadcast, and report
Two shapes are common, depending on what your custody platform returns:
- Custody signs, you broadcast: decode
unsignedTransactionfor the chain family (see Transaction signing), have custody sign it, broadcast through your own infrastructure, then report the hash withPUT /v1/transactions/{transactionId}/submit-hash. - Custody signs and returns a ready-to-submit payload: hand the signed transaction to Yield.xyz instead with
POST /v1/transactions/{transactionId}/submit, and let it broadcast.
transactions[] in stepIndex order, waiting for each to confirm before the next, unless executionPattern is batch.4
Poll to a terminal status
Poll
GET /v1/transactions/{transactionId} (or the whole action) to a terminal status. Record the terminal status and hash against the same internal identifier from step 1, closing the audit trail entry you opened when the action was built.Idempotency
POST /v1/actions/enter (and /exit, /manage) is not idempotent: calling it again mints a new action with new transaction ids, it does not return the one already in flight. Never re-request an action for the same intent while a prior one may already have broadcast; a signed transaction that later confirms on-chain after you requested a second one can result in the position being entered or exited twice.
If your process loses track of an in-flight action (a crash or a timeout), recover it instead of re-requesting:
GET /v1/actions/{actionId}, if you logged the id, to read its transactions and their statuses and hashes.- Poll rather than assume: an action with no progress for a period becomes
STALE, which is not a final status. Check what was actually broadcast before deciding whether to build a new action; see the STALE row in Enter and exit flows.
Address mapping and audit trail
Keep the mapping between your internal account identifier and the custody-controlledaddress you pass to Yield.xyz outside of Yield.xyz itself; the API has no concept of your account structure. Log, per request: the internal identifier, the action.id, each transaction.id and its stepIndex, the signed payload or the hash you submitted, and the terminal status you polled. That log is what lets you reconcile a custody platform’s own transaction history against Yield.xyz’s without re-deriving anything from on-chain state.
Transaction broadcast, confirmation, and failure, and each action’s SUCCESS or FAILED status once it settles on chain, are also pushed as webhooks if you’d rather not poll every entry in your audit log; see Webhooks for the event model.
Next steps
Transaction signing
Decode unsignedTransaction by chain family before it reaches a signer.
Webhooks
Get transaction and position status changes pushed instead of polled.

