Skip to main content
A custody or HSM-backed integration runs the whole loop server-side: your backend builds actions under your project’s API key, validates each transaction before it reaches a signer, has your custody platform or HSM sign it, and reports the result back to Yield.xyz. It does not document any custodian’s own API.

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 unsignedTransaction never reaches custody:
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.
3

Sign, broadcast, and report

Two shapes are common, depending on what your custody platform returns:
  • Custody signs, you broadcast: decode unsignedTransaction for the chain family (see Transaction signing), have custody sign it, broadcast through your own infrastructure, then report the hash with PUT /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.
Use one path per transaction, never both. Sign and submit 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-controlled address 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.