Custodial Withdrawal
Custodial merchants only: manage saved BTC destination wallets and withdraw the Uphold balance to them, including the Uphold Travel Rule verification a held withdrawal may require.
Add destination wallet
https://api.gobtcpay.com/public/api/v1.2/merchant/custodial/wallet/createCustodial merchants only. Saves a BTC wallet the merchant can later withdraw to. Takes the address, an optional label, and a totpCode, adding a destination is a sensitive action and is gated by the merchant's TOTP. Returns the saved wallet: its id, merchantId, address, label, network, and createdAt. There is no asset field, a custodial merchant only ever holds bitcoin.
Authorization: merchantAuth
Body required
application/jsonaddressstringrequiredbc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdqlabelstringHuman-readable label for the POS terminal (optional).
Front desktotpCodestringrequiredstringResponses
idstringrequired3fa85f64-5717-4562-b3fc-2c963f66afa6resultobjectrequiredcurl -X POST "$BASE_URL/merchant/custodial/wallet/create" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d '{
"address": "bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq",
"label": "Front desk",
"totpCode": "string"
}'{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"result": {
"$case": "success",
"success": {
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"merchantId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"address": "bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq",
"label": "Front desk",
"network": "string",
"createdAt": 1718012345
}
}
}List destination wallets
https://api.gobtcpay.com/public/api/v1.2/merchant/custodial/wallet/listCustodial merchants only. Returns the merchant's saved BTC destination wallets as items, each with its id, merchantId, address, label, network, and createdAt. Takes no parameters, the merchant comes from the auth context.
Authorization: merchantAuth
Responses
idstringrequired3fa85f64-5717-4562-b3fc-2c963f66afa6resultobjectrequiredcurl -X POST "$BASE_URL/merchant/custodial/wallet/list" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN"{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"result": {
"$case": "success",
"success": {
"items": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"merchantId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"address": "bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq",
"label": "Front desk",
"network": "string",
"createdAt": 1718012345
}
]
}
}
}Create withdrawal
https://api.gobtcpay.com/public/api/v1.2/merchant/custodial/withdraw/createCustodial merchants only. Starts a withdrawal of amountSats (before fees, in satoshi) from the merchant's Uphold balance to a saved wallet (walletId), gated by totpCode. Returns the created withdrawal with the quote it was accepted under in feeSummary (amountSats, feeSats, receivedSats and Uphold's feeBreakdown line items, all in satoshi). status is pending, or awaiting_travel_rule when Uphold requires Travel Rule information first. Typed failures include insufficient_available_balance, amount_below_minimum, pending_withdrawal_exists, fee_exceeds_amount, wallet_not_found, the address checks (address_validation_failed, address_wrong_network, address_not_btc), the TOTP checks (totp_required, totp_invalid, totp_not_configured), and the eligibility checks (not_custodial_merchant, no_uphold_account, withdraw_not_configured).
Authorization: merchantAuth
Body required
application/jsonwalletIdstringrequired3fa85f64-5717-4562-b3fc-2c963f66afa6amountSatsstring | numberrequiredAmount in satoshis.
totpCodestringrequiredstringResponses
idstringrequired3fa85f64-5717-4562-b3fc-2c963f66afa6resultobjectrequiredcurl -X POST "$BASE_URL/merchant/custodial/withdraw/create" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d '{
"walletId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"amountSats": "string",
"totpCode": "string"
}'{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"result": {
"$case": "success",
"success": {
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"status": "pending",
"walletId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"address": "bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq",
"walletLabel": "Front desk",
"network": "string",
"amountSats": "string",
"feeSummary": {
"amountSats": "string",
"feeSats": "string",
"receivedSats": "string",
"feeBreakdown": [
{
"type": "withdraw",
"code": "string",
"asset": "string",
"amount": null,
"percentage": 0
}
]
},
"travelRuleRequired": true,
"createdAt": 1718012345
}
}
}List withdrawals
https://api.gobtcpay.com/public/api/v1.2/merchant/custodial/withdraw/listCustodial merchants only. Returns the merchant's withdrawals, newest first, as items with a totalCount. Every filter is optional: status narrows to one lifecycle state, from / to bound the creation time (inclusive unix seconds), and limit / skip page the result.
Authorization: merchantAuth
Body required
application/jsonstatusenumCurrent status. Payments: initiated / detected / paid / failed / expired / canceled / cleared. Payment transactions: success / failed / pending / cleared.
pendingawaiting_travel_rulesubmittingprocessingon_holdcompletedfailedcanceledpendingfromintegerUnixTime (seconds since epoch)
1718012345tointegerUnixTime (seconds since epoch)
1718012345limitinteger20skipinteger0Responses
idstringrequired3fa85f64-5717-4562-b3fc-2c963f66afa6resultobjectrequiredcurl -X POST "$BASE_URL/merchant/custodial/withdraw/list" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d '{
"status": "pending",
"from": 1718012345,
"to": 1718012345,
"limit": 20,
"skip": 0
}'{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"result": {
"$case": "success",
"success": {
"items": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"status": "pending",
"walletId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"amountSats": "string",
"quotedFeeSats": null,
"quotedReceivedSats": null,
"feeSats": null,
"receivedSats": null,
"feeBreakdown": [],
"address": "bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq",
"walletLabel": "Front desk",
"network": "string",
"onchainTxid": "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b",
"failureReason": "insufficient_balance",
"travelRuleRequired": true,
"createdAt": 1718012345,
"submittedAt": 1718012345,
"completedAt": 1718012345
}
],
"totalCount": 0
}
}
}Get withdrawal
https://api.gobtcpay.com/public/api/v1.2/merchant/custodial/withdraw/getCustodial merchants only. Fetches one withdrawal by withdrawalId. The withdrawal must belong to the authenticated merchant. Returns the full withdrawal item, including its quote (quotedFeeSats, quotedReceivedSats), the actual fee once settled (feeSats, receivedSats, feeBreakdown, null until then), onchainTxid, and the lifecycle timestamps.
Authorization: merchantAuth
Body required
application/jsonwithdrawalIdstringrequired3fa85f64-5717-4562-b3fc-2c963f66afa6Responses
idstringrequired3fa85f64-5717-4562-b3fc-2c963f66afa6resultobjectrequiredcurl -X POST "$BASE_URL/merchant/custodial/withdraw/get" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d '{
"withdrawalId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
}'{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"result": {
"$case": "success",
"success": {
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"status": "pending",
"walletId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"amountSats": "string",
"quotedFeeSats": "string",
"quotedReceivedSats": "string",
"feeSats": "string",
"receivedSats": "string",
"feeBreakdown": [
{
"type": "withdraw",
"code": "string",
"asset": "string",
"amount": null,
"percentage": 0
}
],
"address": "bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq",
"walletLabel": "Front desk",
"network": "string",
"onchainTxid": "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b",
"failureReason": "insufficient_balance",
"travelRuleRequired": true,
"createdAt": 1718012345,
"submittedAt": 1718012345,
"completedAt": 1718012345
}
}
}Cancel withdrawal
https://api.gobtcpay.com/public/api/v1.2/merchant/custodial/withdraw/cancelCustodial merchants only. Cancels a withdrawal that has not been handed to Uphold yet, releasing the reserved funds and moving it to canceled. Returns { ok: true }, the outcome is single-valued, so a failure arrives as a typed error rather than as a withdrawal in another state. An already submitted withdrawal returns withdrawal_already_submitted, and one past submission returns withdrawal_not_cancellable.
Authorization: merchantAuth
Body required
application/jsonwithdrawalIdstringrequired3fa85f64-5717-4562-b3fc-2c963f66afa6Responses
idstringrequired3fa85f64-5717-4562-b3fc-2c963f66afa6resultobjectrequiredcurl -X POST "$BASE_URL/merchant/custodial/withdraw/cancel" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d '{
"withdrawalId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
}'{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"result": {
"$case": "success",
"success": {
"ok": true
}
}
}Open Travel Rule session
https://api.gobtcpay.com/public/api/v1.2/merchant/custodial/withdraw/travel-rule/sessionCustodial merchants only. Opens an Uphold Travel Rule verification session for a withdrawal Uphold is holding (awaiting_travel_rule). Returns what Uphold's embedded widget needs to mount, relayed verbatim: flow, the widget url, a short-lived token, and provider-specific data. Safe to call repeatedly, nothing about the session is stored, and an expired one is replaced by asking again.
Authorization: merchantAuth
Body required
application/jsonwithdrawalIdstringrequired3fa85f64-5717-4562-b3fc-2c963f66afa6Responses
idstringrequired3fa85f64-5717-4562-b3fc-2c963f66afa6resultobjectrequiredcurl -X POST "$BASE_URL/merchant/custodial/withdraw/travel-rule/session" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d '{
"withdrawalId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
}'{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"result": {
"$case": "success",
"success": {
"flow": "withdrawal-form",
"url": "string",
"token": "eyJhbGciOiJFUzI1NiIsImtpZCI6ImFjY2VzcyJ9.eyJwa2giOiIwMmExNjMzYyIsImNpZCI6IjNmYTg1ZjY0IiwiaWF0IjoxNzE4MDEyMzQ1fQ.MEQCIE3aGoQk0vY9c5kq",
"data": "string"
}
}
}Submit Travel Rule info
https://api.gobtcpay.com/public/api/v1.2/merchant/custodial/withdraw/travel-rule/submitCustodial merchants only. Submits the Travel Rule information the merchant completed in Uphold's widget for a held withdrawal. payload is the widget's complete result whole, including its nested value, Uphold requires the envelope intact, so it is required and forwarded verbatim; its inner shape is Uphold's. On success the withdrawal leaves awaiting_travel_rule and returns to pending for re-evaluation, which is the item returned.
Authorization: merchantAuth
Body required
application/jsonwithdrawalIdstringrequired3fa85f64-5717-4562-b3fc-2c963f66afa6payloadobjectrequiredstringResponses
idstringrequired3fa85f64-5717-4562-b3fc-2c963f66afa6resultobjectrequiredcurl -X POST "$BASE_URL/merchant/custodial/withdraw/travel-rule/submit" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d '{
"withdrawalId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"payload": "string"
}'{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"result": {
"$case": "success",
"success": {
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"status": "pending",
"walletId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"amountSats": "string",
"quotedFeeSats": "string",
"quotedReceivedSats": "string",
"feeSats": "string",
"receivedSats": "string",
"feeBreakdown": [
{
"type": "withdraw",
"code": "string",
"asset": "string",
"amount": null,
"percentage": 0
}
],
"address": "bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq",
"walletLabel": "Front desk",
"network": "string",
"onchainTxid": "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b",
"failureReason": "insufficient_balance",
"travelRuleRequired": true,
"createdAt": 1718012345,
"submittedAt": 1718012345,
"completedAt": 1718012345
}
}
}