Skip to main content
ACTIVITY_TYPE_EXECUTE_SWAP_V3 returns a swapRequestId. Query get_swap_status with it to observe the full lifecycle — including failures that occur before broadcast, such as pre-flight simulation failures. Same-chain, cross-chain, and EVM ↔ SVM swaps share the same query and the same response shape; provider-specific state machines are normalized to three states: PENDING, COMPLETED, FAILED.

Lifecycle model

Turnkey normalizes swap lifecycle to three states across same-chain and cross-chain routes:
  • PENDING: still in flight. Broadcast pending, origin transaction not yet included, or (cross-chain) destination-side execution not yet settled.
  • COMPLETED: the user received the destination asset. Terminal, happy path.
  • FAILED: the swap will not fill as intended. Terminal. Same-chain FAILED comes from the origin send-transaction only. Cross-chain FAILED can appear before refund fields exist.
Intermediate provider states (bridge_pending, delayed, submitted, and so on) collapse into PENDING on purpose. PENDING means wait. COMPLETED means the output landed. FAILED means read error and, for cross-chain, keep polling if refund is absent.

Query get_swap_status

Query get_swap_status with:
string
required
The organization that executed the swap: the same organization the execute activity was submitted against, parent or sub-organization.
string
required
The handle returned by ACTIVITY_TYPE_EXECUTE_SWAP_V3, e.g. sha256:9a80031c2def....
cURL:
cURL
JavaScript:
JavaScript
Response:

Response fields

  • status: normalized state. PENDING, COMPLETED, or FAILED.
  • swapKind: SAME_CHAIN or CROSS_CHAIN. Set at execute time; does not change.
  • provider: the provider that executed the swap. Always present.
  • inputToken, outputToken, inputAmount: echoed from the execute intent.
  • originTxHash: origin-chain transaction hash. Present once the swap is broadcast, for both same-chain and cross-chain routes.
  • destinationTxHashes: array of destination-chain transaction hashes on COMPLETED. Cross-chain only.
  • destinationAddress: address that receives the output asset. For EVM ↔ SVM this is the destinationAddress you set on quote and execute. For same-protocol routes it is the swapping wallet.
  • outputAmount: actual amount received, on COMPLETED. May lag the status transition by seconds while the monitor fetches the final settled amount.
  • refund: present on cross-chain FAILED when funds moved and came back. Contains asset (CAIP-19), amount (raw onchain units), and optional txHash. Omitted for origin failures and same-chain swaps. See What FAILED means.
  • error: present on FAILED. Contains reason (ORIGIN_TRANSACTION_FAILED or PROVIDER_FILL_FAILED), message (human-readable detail), originTxError (decoded revert detail, origin failures only), and providerReason (provider-specific detail, fill failures only). See What FAILED means.
  • updatedAt: last observed state change, as a Unix timestamp in milliseconds (stringified).

Same-chain vs. cross-chain differences

The response shape is identical. Two behaviors differ in practice:
  • Timing. Same-chain swaps reach a terminal state within roughly one block time of the origin chain. Cross-chain swaps can take tens of seconds to several minutes depending on the route. Each quote’s estimatedTimeSeconds is the per-swap estimate.
  • Field population. destinationTxHashes is populated only for cross-chain COMPLETED swaps. Same-chain outcomes are fully described by originTxHash: on COMPLETED, that transaction delivered the output; on FAILED, either the transaction reverted or — if originTxHash is absent — the swap failed before broadcast and nothing moved onchain. Same-chain FAILED never includes refund or PROVIDER_FILL_FAILED.
swapKind (SAME_CHAIN or CROSS_CHAIN) tells you which model applies. Branch on it client-side only where the difference matters — for example, showing a bridge-progress state for cross-chain PENDING — and otherwise treat both kinds uniformly through the three-state model.

What FAILED means

Same-chain and cross-chain FAILED are not the same event.
  • Same-chain. FAILED comes from the origin send-transaction only. error.reason is ORIGIN_TRANSACTION_FAILED. The response never includes refund or PROVIDER_FILL_FAILED.
  • Cross-chain. FAILED can come from the origin send-transaction (ORIGIN_TRANSACTION_FAILED) or from a provider fill failure after origin success (PROVIDER_FILL_FAILED). FAILED can appear before refund fields exist. Keep polling if you need refund. PENDING means the destination leg can still fill — it does not mean a refund is in flight.
On FAILED, two fields together describe the outcome:
  • error.reason — why it failed: ORIGIN_TRANSACTION_FAILED (the origin transaction failed pre-flight simulation or reverted onchain) or PROVIDER_FILL_FAILED (the origin transaction succeeded but the provider could not fill). error.message and, for origin failures, error.originTxError carry the decoded detail, including the full revert chain.
  • refund — present on cross-chain FAILED when funds moved and came back: refund.asset (CAIP-19), refund.amount (raw onchain units), and optional refund.txHash. The refunded asset can differ from the original input if the route included an origin-side swap, and it lands on the origin chain.
Reading the user’s position from the response: If the user still wants the swap, re-quote — with the refunded asset as the new input where a refund occurred. Caveats worth surfacing to end users:
  • A refund is reduced by refund gas and any origin-side swap losses; it will not equal the original input.
  • A re-swap is a new swap: new quote, new fees, new slippage.
  • If the original destination was another chain, the re-swap is again cross-chain.
If a cross-chain swap stays FAILED with PROVIDER_FILL_FAILED and no refund after you keep polling, the provider did not return funds through its automated flows. Contact support.

Polling cadence

  • Same-chain: poll every ~1 second while PENDING. Typically settles within one block time.
  • Cross-chain: poll every 5 to 10 seconds while PENDING. Settlement can take from tens of seconds to several minutes depending on route.
Websocket and event-driven updates are on the roadmap and will replace polling for cross-chain lifecycles.

Next steps