Documentation Index Fetch the complete documentation index at: https://developer.uphold.com/llms.txt
Use this file to discover all available pages before exploring further.
This guide walks you through supporting card withdrawals using the REST API.
Prerequisites
The user has completed onboarding and has the required capabilities enabled.
A funded account to debit the funds from.
Walkthrough
Check available rails
Call List Rails to verify card withdrawal is available.
GET /core/rails?type=card
{
"rails" : [
{
"type" : "card" ,
"network" : "visa" ,
"method" : "debit-card" ,
"asset" : "GBP" ,
"decimals" : 2 ,
"features" : [
"deposit" ,
"withdraw"
]
}
]
}
Select source account
Card withdrawals can be sourced from any account. If the selected account is not in the card’s currency, the balance will be converted at the time of the transaction using Uphold’s prevailing rate. Make sure the origin asset has the necessary features enabled .
Call List accounts to retrieve the user’s accounts and let them pick the one to withdraw from.
{
"accounts" : [
{
"id" : "a00507fe-628c-4f27-ae81-e1c40b2a8fb8" ,
"ownerId" : "e4ce04dc-67b7-4e9f-af91-482cb6f9fc4a" ,
"label" : "My GBP account" ,
"asset" : "GBP" ,
"balance" : {
"total" : "500.00" ,
"available" : "500.00"
}
}
]
}
Select a card account
Let the user pick an existing card or add a new one.
Find an existing card account
Call List external accounts to fetch the user’s saved cards.
GET /core/external-accounts
Make sure the selected card has status: "ok" and in features.
{
"externalAccounts" : [
{
"id" : "7d5928c5-8ac4-4b0d-8b45-f332ba6a9de7" ,
"ownerId" : "e4ce04dc-67b7-4e9f-af91-482cb6f9fc4a" ,
"type" : "card" ,
"status" : "ok" ,
"label" : "My Visa Card" ,
"asset" : "GBP" ,
"network" : "visa" ,
"features" : [
"deposit" ,
"withdraw"
],
"details" : {
"type" : "debit" ,
"last4Digits" : "5119" ,
"expiryDate" : {
"month" : 12 ,
"year" : 2028
},
"octSupport" : "supported"
}
}
]
}
Link a new card account
If the user wants to use a card not yet on file, call Create external account with the card details.
POST /core/external-accounts
{
"type" : "card" ,
"label" : "My Visa Card" ,
"number" : "4921817844445119" ,
"securityCode" : "123" ,
"expiryDate" : {
"month" : 12 ,
"year" : 2028
}
}
The response initially returns status: "processing" while the card is validated.
{
"externalAccount" : {
"id" : "7d5928c5-8ac4-4b0d-8b45-f332ba6a9de7" ,
"type" : "card" ,
"status" : "processing" ,
"label" : "My Visa Card"
}
}
Once validated, the status transitions to ok and the full details are available.
{
"externalAccount" : {
"id" : "7d5928c5-8ac4-4b0d-8b45-f332ba6a9de7" ,
"ownerId" : "e4ce04dc-67b7-4e9f-af91-482cb6f9fc4a" ,
"type" : "card" ,
"status" : "ok" ,
"label" : "My Visa Card" ,
"asset" : "GBP" ,
"network" : "visa" ,
"features" : [
"deposit" ,
"withdraw"
],
"details" : {
"type" : "debit" ,
"last4Digits" : "5119" ,
"expiryDate" : {
"month" : 12 ,
"year" : 2028
},
"octSupport" : "supported"
}
}
}
Monitor the external account status via
Get external account or the
external-account.status-changed webhook until
status is
ok before proceeding.
EMD disclaimer
This disclaimer is required to comply with FCA regulations. Display it to users based in GB, the first time they link a credit/debit card or generate bank deposit details — it only needs to be shown once:
Uphold Europe Limited is an EMD Agent of Optimus Cards UK Limited (FRN: 902034). All received funds are held in a designated safekeeping account with a regulated bank and kept separate from Uphold’s own assets. These funds are not protected by the UK Financial Services Compensation Scheme.
Create a quote
Call Create quote with the origin account and the card external account as destination.
POST /core/transactions/quote
{
"origin" : {
"type" : "account" ,
"id" : "a00507fe-628c-4f27-ae81-e1c40b2a8fb8"
},
"destination" : {
"type" : "external-account" ,
"id" : "7d5928c5-8ac4-4b0d-8b45-f332ba6a9de7"
},
"denomination" : {
"asset" : "GBP" ,
"amount" : "250.00" ,
"target" : "origin"
}
}
{
"quote" : {
"id" : "a91f3c72-1e4b-4c8a-b3e9-9f2d8e4b7c1a" ,
"origin" : {
"amount" : "250.00" ,
"asset" : "GBP" ,
"node" : {
"type" : "account" ,
"id" : "a00507fe-628c-4f27-ae81-e1c40b2a8fb8" ,
"ownerId" : "e4ce04dc-67b7-4e9f-af91-482cb6f9fc4a"
},
"rate" : "1"
},
"destination" : {
"amount" : "250.00" ,
"asset" : "GBP" ,
"node" : {
"type" : "external-account" ,
"id" : "7d5928c5-8ac4-4b0d-8b45-f332ba6a9de7" ,
"ownerId" : "e4ce04dc-67b7-4e9f-af91-482cb6f9fc4a"
},
"rate" : "1"
},
"denomination" : {
"asset" : "GBP" ,
"amount" : "250.00" ,
"target" : "origin" ,
"rate" : "1"
},
"fees" : [],
"expiresAt" : "2024-07-24T15:22:39Z"
}
}
See all 33 lines
Quotes typically expire quickly. Prompt for user confirmation within the expiry window and requote if needed.
Confirm and create transaction
Once the user confirms, call Create transaction with the quote ID.
POST /core/transactions
{
"quoteId" : "a91f3c72-1e4b-4c8a-b3e9-9f2d8e4b7c1a"
}
In a successful card withdrawal, the origin is the user’s account and the destination is the external-account representing the card. The transaction status is initially processing and updates to completed once the transfer settles.
{
"transaction" : {
"id" : "a1b2c3d4-5e6f-4a8b-9c0d-1e2f3a4b5c6d" ,
"origin" : {
"asset" : "GBP" ,
"amount" : "250.00" ,
"node" : {
"type" : "account" ,
"id" : "a00507fe-628c-4f27-ae81-e1c40b2a8fb8" ,
"ownerId" : "e4ce04dc-67b7-4e9f-af91-482cb6f9fc4a"
}
},
"destination" : {
"asset" : "GBP" ,
"amount" : "250.00" ,
"node" : {
"type" : "external-account" ,
"id" : "7d5928c5-8ac4-4b0d-8b45-f332ba6a9de7" ,
"ownerId" : "e4ce04dc-67b7-4e9f-af91-482cb6f9fc4a"
}
},
"status" : "completed" ,
"quotedAt" : "2025-01-10T14:22:15Z" ,
"createdAt" : "2025-01-10T14:22:45Z" ,
"updatedAt" : "2025-01-10T14:22:45Z" ,
"denomination" : {
"asset" : "GBP" ,
"amount" : "250.00" ,
"target" : "origin"
}
}
}
See all 32 lines
Notify the user
Display an in-app confirmation when the transaction is completed, and send an email if applicable.
You now support card withdrawals via the REST API.