Overview
The Convert and Withdraw product allows a platform to get quote for an asset, execute a quote, and have the purchased crypto get automatically withdrawn on-chain to a specified address. There are just 2 API endpoints needed in order to initiate these movements: GET /convert_withdraw/rfq
and POST /convert_withdraw/execute
Use Cases
- Payment acquirers offering an on-ramp product to their merchant partners
- Crypto on-ramps offering a direct-to-consumer crypto purchasing product
Key Features
- Zero Hash will take in a quote request (ie, I would like $100 worth of BTC) accompanied by a specified withdrawal address, return a quote, accept an execution request on that quote, purchase the crypto and ledger it to the specified participant, and automatically move it on-chain it to the participant's address.
- The quote can be locked in for 5 or 30 seconds, which can be configurable by contacting settlements@zerohash.com.
- The response will include
expire_ts
, which shows the timestamp for when the quote will expire.
- We offer 1-1 USDC for USD liquidity, this is configurable.
- There is a new API key permission called Convert and Withdraw that will need to be enabled at the time of API key creation in order to use these new endpoints
Key Validations
- You must specify a withdrawal_address on the GET /convert_withdraw/rfq request
- Validation will happen on the GET /convert_withdraw/rfq endpoint. The resulting quantity of crypto must be above the Zero Hash-defined withdrawal minimum threshold and depending on the asset type, the purchased asset quantity must also be above the network fee amount. Please see the linked article for additional details.
- There are 2 Resulting Quantity scenarios:
- The platform specifies a
total
on the GET /convert_withdraw/rfq endpoint. For example, "give me $1 worth of BTC". We will take in that dollar amount, convert it to aquantity
, ie 0.00032162 BTC, and decide if that is above or below the UTXO minimum. In this example, the resulting quantity is above our minimums and we proceed with the request. If below, we will reject. - The platform specifies a
quantity
on the GET /convert/withdraw/rfq endpoint. For example, "give me 0.00032162 worth of BTC". There is no need to transpose anything and we will take that quantity, compare to our minimums, and act accordingly.
- The platform specifies a
API Flow
GET QUOTE
- A platform hits
GET /convert_withdraw/rfq
using the following query params:- participant_code: CUST01
- side: buy
- underlying: BTC
- quoted_currency: USD
- total: 20
- withdrawal_address (required): 2N8PYGKSQRpHa5VDNZ4iLwxi5crpRWb3TR1
- Response:
{
"message": {
"request_id": "64f34a8d-f5f5-4e37-b01d-7c6814aed4bc",
"participant_code": "CUST01",
"quoted_currency": "USD",
"side": "buy",
"quantity": "0.00087097",
"price": "22962.90
"quote_id": "5aaaa8af-5d0c-4d55-868b-b56ea19a5443",
"expire_ts": 1661449335103,
"account_group": "00SCXM",
"account_label": "general",
"obo_participant": {
"participant_code": "CUST01",
"account_group": "PLAT01",
"account_label": "general"
},
"network_fee_notional": "1.50",
"network_fee_quantity": "0.00001",
"total_notional": "21.5",
"underlying": "BTC",
"asset_cost_notional": "20",
}
}
bold:new fields compared to the /liquidity endpoints
EXECUTE QUOTE
- A platform hits POST /convert_withdraw/execute using the quote_id from the response above
- Response:
{
"message": {
"request_id": "945c41ba-c06e-4e69-aaf6-ea27cb7c75b2",
"quote": {
"request_id": "7a8a8526-3614-4373-9ab4-0069dc643109",
"participant_code": "PLAT01",
"quoted_currency": "USD",
"side": "buy",
"quantity": "0.00087097",
"price": "22962.90
"quote_id": "dc179192-5bdf-41f2-9ffa-badb1396a0a7",
"expire_ts": 1658512268578,
"account_group": "00SCXM",
"account_label": "general",
"obo_participant": {
"participant_code": "CUST01",
"account_group": "PLAT01",
"account_label": "general"
},
"network_fee_notional": "1.50",
"network_fee_quantity": "0.00001",
"total_notional": "21.5",
"underlying": "BTC",
"asset_cost_notional": "20",
“withdrawal_request_id”:”12345”,
"transaction_timestamp": 1658512266138
},
"trade_id": "9c4820e9-bf6d-4f59-ad4f-94ec9e5fc665",
"status": "Completed",
"trade_ids_list": [
"9c4820e9-bf6d-4f59-ad4f-94ec9e5fc665"
]
}
}
bold: see withdrawal_request_id field. this is the identifier of the withdrawal that Zero Hash has sent on-chain
MONITOR WITHDRAWAL
- Platform hits GET /withdrawals/requests/12345
- Reponse:
{
"id": 12345,
"withdrawal_account_id": 152089,
"participant_code": "CUST01",
"account_group": "PLAT01",
"account_label": null,
"requestor_participant_code": "PLAT01",
"asset": "BTC",
"requested_amount": "20",
"settled_amount": "20",
"gas_price": null,
"status": "SETTLED",
"on_chain_status": PENDING,
"client_withdrawal_request_id": "zh_withdrawal_17845eeffd5f71abaa85e9722e76c931a",
"requested_timestamp": 1659542191772,
"transaction_id": “3899526c5f986297d3b2ba29f2c4c8b0fb486bef2fc76f7c11aae2b1faf3fe76”
"input_data": null,
"fee_amount": 0.00001,
"quoted_fee_amount"0.00001
}
bold:
-
status:the zero hash internal settlement status
- PENDING: The request has been created and is pending approval from users. Not relevant for some use cases. If configured for 0 withdrawal approvals required, the withdrawal instantly goes into an APPROVED state.
- APPROVED: The request is approved but not settled
- REJECTED: The request is rejected and in a terminal state
- SETTLED: The funds have been deducted from the participant
-
on_chain_status:the blockchain status
- PENDING: The withdrawal has been broadcasted on-chain but is not yet confirmed
- CONFIRMED: The withdrawal has been sufficiently confirmed on-chain according to our confirmation thresholds, which can be viewed here in Confirms column here.
- transaction_id: the on-chain transaction hash, useful to display out to customers so that they can follow the transaction if they wish