Withdraw Directly to EVM
One request that redeems from Native Core Pool and pays out to an EVM wallet, authorized by two signatures.
Withdraw ends at the address's Native Core balance. Getting from there to a wallet on an EVM chain is a second, separate step.
This endpoint does both in one request. The user signs twice — once for the Pool redemption, once for the Native Core withdrawal — and the two run as a single tracked operation.
Ends at
Native Core balance
The destination address on the EVM chain
Signatures
1
2
One in flight per
Asset
Address
Types
scheduled and instant
instant, or a claim of a ready scheduled
Read Withdraw and the Native Core withdraw action first. This page only covers what the combined request adds.
1. Choose the source
source selects which Pool authorization you are sending. It is explicit; nothing is inferred from which fields you fill in.
source
What it does
Pool fee
instant
Redeems immediately
instant_fee_bps
scheduled_claim
Claims a scheduled withdrawal that has reached claimable_at_unix_ms
None
You cannot create a scheduled withdrawal here. Create it with createWithdrawal, wait out its window, then send scheduled_claim instead of claimWithdrawal.
2. Size the amount
The one number to get right is net_amount. It is what leaves the Native Core balance, and it is what core_withdraw.amount has to be.
instant charges the Pool fee on the gross, rounded up:
At 5 bps, a gross of 1000000001 pays a fee of 500001, not 500000.
The destination chain also takes the asset's flat withdrawal fee when the payout is released, exactly as it does for a standalone Core withdrawal — see Validate the amount. It changes what the user receives, not anything you sign.
So: for scheduled_claim, net_amount is the gross of the withdrawal you are claiming, unchanged. For instant, subtract the Pool fee from the gross.
core_withdraw.amount must equal net_amount exactly. Sending the gross, rounding the Pool fee down, or subtracting the withdrawal fee each return earn net amount or asset does not match Core withdraw authorization.
3. Sign the Pool redemption
Identical to the standalone action, same domain and same typed data:
source
Sign
instant
CreateWithdrawal with withdrawType: '2'
scheduled_claim
ClaimWithdrawal over the operationId hash
The result goes in user_signature.
4. Sign the Core withdrawal
The Native Core withdraw action, signed under the EIP-712 v4 scheme — domain {name:"Native Core", version:"1", verifyingContract:0x0000…0000}, no chainId, authKind 1, authScope 0.
Send it as core_withdraw:
nonce
Transaction nonce. Current Unix milliseconds
expires_after_unix_ms
When the authorization stops being valid
asset_id
Same asset as the redemption
amount
net_amount, in atoms
dst_chain_id
The EVM chain to pay out on
dst_address
The receiving address on that chain
withdraw_nonce
Business nonce. Current Unix milliseconds; increment locally within the same millisecond
cloid
0x + 32 hex, exactly 16 bytes. Required
signature
0x + 130 hex
expires_after_unix_ms needs at least 10 minutes left when the request arrives, not when the user signs. A user who signs with exactly ten minutes and then pauses over the wallet prompt is rejected with Core withdraw authorization has less than 10m0s remaining. Sign 30 minutes out.
withdraw_nonce becomes the payout's operation id and carries Native Core's usual 3-day duplicate window. Reusing one returns a duplicate-nonce rejection.
5. Submit
For scheduled_claim, replace user_nonce / asset_id / amount with the operation_id of the withdrawal you are claiming.
One is accepted per address at a time. The next is refused with user already has active wallet withdrawal <id> until the current one finishes.
6. Follow the status
{"type":"walletWithdrawals"} returns the same record in a keyset page, filterable by asset_id and status, paged with before_id.
Both reads take user_address and serve only that address's records. A wallet_withdrawal_id belonging to someone else returns the same wallet withdrawal not found as one that does not exist.
The redemption typically settles in seconds; the EVM leg follows destination-chain confirmation and usually takes a few minutes.
ACCEPTED
Both signatures verified, work not started
REDEEM_SUBMITTED
Pool redemption submitted
REDEEM_SETTLED
net_amount is in the Native Core balance
WITHDRAW_SUBMITTED
The Core withdrawal is submitted, awaiting the EVM payout
DONE
Terminal. Paid out on the destination chain
REDEEM_FAILED
Terminal. The redemption failed; nothing moved
NEEDS_RESUBMIT
Terminal. The redemption succeeded, the payout did not
WITHDRAW_STUCK
Terminal. The payout exhausted its attempts
These eight are also the accepted values for the status filter.
suggested_action
What to tell the user
WAIT
Still running
NONE
Finished, or failed with nothing owed
RESUBMIT_CORE_WITHDRAW
The net_amount is in their Native Core balance. Retrying here cannot work; withdraw it with a plain Core withdraw
CONTACT_SUPPORT
Held for an operator. This is the one terminal state that keeps the address's slot occupied, so no new wallet withdrawal is accepted until it is resolved
Fields
wallet_withdrawal_id
The handle for both reads
source
instant or scheduled_claim, as created
gross_amount / net_amount
Before and after the Pool fee. net_amount is what left the Native Core balance, not what arrived on the destination chain
earn_fee_bps_snapshot
The rate at creation, so a later config change does not restate history
earn_withdraw_operation_id
The Pool withdrawal backing this one
core_tx_hash
The Native Core withdrawal transaction
accounting_withdraw_operation_id
Join key into POST /api/v3/accounting {"type":"withdrawOrder"}, where dst_chain_id and the payout's own state live
evm_tx_hash
The destination-chain payout
failure_code
Present once an attempt has failed, on non-terminal records too
failure_message
Best effort. Branch on failure_code; this field is omitted whenever the underlying text is not fit to publish
Timestamps are null until reached. Hashes and ids are absent as keys until they exist.
Rate limits
Metered per user_address, like every other Pool request.
createWalletWithdrawal
1 per second
walletWithdrawal, walletWithdrawals
3 per second
What can go wrong
earn net amount or asset does not match Core withdraw authorization
core_withdraw.amount is not net_amount
Round the fee up, then subtract
Core withdraw authorization has less than 10m0s remaining
expires_after_unix_ms is too close
Sign 30 minutes out
Core withdraw signer does not match Earn user
The Core typed data does not match what you sent
Check authKind/authScope, that no chainId reached the domain, and that both signatures came from one object
withdrawal signer does not match user
The redemption's typed data does not match
Same checks as Withdraw
Core withdraw cloid must be 16-byte 0x hex
cloid is missing or the wrong length
0x + 32 hex characters
user already has active wallet withdrawal <id>
One is already in flight for this address
Poll it to a terminal state first; the limit is per address, not per asset
wallet withdrawal not found
No such record, or it belongs to another address
Both cases return the same response
Next steps
WithdrawReferenceLast updated