---
title: "Submit a Withdrawal"
method: POST
path: "/v1/withdraw/{withdrawalDetailId}/submit"
tags: ["Withdrawals"]
---

# Submit a Withdrawal

`POST /v1/withdraw/{withdrawalDetailId}/submit`

Submits a co-signed transaction for broadcast. Path param is the `withdrawalDetailId` from prepare (not the config id). No authentication required (rate-limited). Submit is idempotent for records already past `QUOTED`.

## Path parameters

- `withdrawalDetailId` string, required

## Request body

- SubmitWithdrawalDto
  - `token` string, required — JWT from the prepare response.
  - `signedTx` string, required — Signed payload for the lane returned by prepare. For `raw` on Solana: base64 co-signed VersionedTransaction. For `userop` on EVM: JSON with `signature` and optional `authorization`. For `hypercore`: EIP-712 signature over `typedData`.

## Response `200`

Withdrawal submitted successfully.

- SubmitWithdrawalEntity
  - `withdrawalDetailId` string
  - `txHash` string, nullable — On-chain transaction signature. Null only if broadcast was rejected.
  - `state` 'QUOTED' | 'SUBMITTING' | 'SUBMITTED' | 'BRIDGING' | 'COMPLETED' | 'FAILED' | 'FAILED_EXPIRED' | 'EXPIRED' | 'REFUNDED_BY_PROVIDER'
  - `broadcastAck` 'acknowledged' | 'unacknowledged' | 'rejected', nullable — `acknowledged` = confirmed; `unacknowledged` = sent, keep polling; `rejected` = terminal failure.

## Other responses

- `401` — Invalid or expired quote token, or signed transaction verification failed.
- `404` — Withdrawal detail not found.
- `409` — Quote has been refreshed (for example after a re-quote) or a concurrent submit race occurred. Re-fetch the quote, re-sign, and resubmit.

---

[API](https://skmtc.net/hel/apis/helio-open-api.md) · [All operations](https://skmtc.net/hel/apis/helio-open-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/hel/helio-open-api/revisions/5732beb2d39f/schema)
