Skip to main content

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.

The Payment Widget handles card selection for withdrawals. Your backend then creates the quote and the transaction directly via the REST API.
The Payment Widget handles card selection only. Your backend must create the transaction via the REST API.

Prerequisites

Walkthrough


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.
GET /core/accounts
{
  "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

The widget session lets the user pick an existing card or add a new one.

Create a payment session

Call Create payment session to start the select-for-withdrawal flow.
POST /widgets/payment/sessions
{
  "flow": "select-for-withdrawal"
}
{
  "session": {
    "flow": "select-for-withdrawal",
    "url": "https://payment.enterprise.uphold.com/",
    "token": "GEbRxBN...edjnXbL"
  }
}

Set up the widget

import { PaymentWidget } from '@uphold/enterprise-payment-widget-web-sdk';

const initializeWithdrawalWidget = async (session) => {
  const widget = new PaymentWidget<'select-for-withdrawal'>(session, { debug: true });

  widget.on('complete', (event) => {
    console.log('Complete', JSON.stringify(event.detail.value));
  });

  widget.on('cancel', () => {
    console.log('Cancelled');
    widget.unmount();
  });

  widget.on('error', (event) => {
    console.error('Error', event.detail.error);
    widget.unmount();
  });

  widget.mountIframe(document.getElementById('payment-container'));
};
For native apps using a WebView, you’ll need a bridge for events as outlined in Installation & setup.

Handle the complete event

The complete event fires after the user selects a card. The event payload includes the selected card external account.
widget.on('complete', (event) => {
  const { via, selection } = event.detail.value;

  if (via === 'external-account') {
    // selection is the selected card external account
    // use selection.id as the destination in the quote
    handleCardSelected(selection);
  }

  widget.unmount();
});
Once you have the selected card, prompt the user to select a source account, then create a quote.

Handle cancellations

widget.on('cancel', () => {
  widget.unmount();
  // Return the user to the previous screen
});

Handle errors

The error event fires for critical unrecoverable errors. Card-specific errors (duplicate card, country mismatch, card limits) are handled by the widget internally.
widget.on('error', (event) => {
  console.error('Widget error:', event.detail.error);
  widget.unmount();
  // Show a user-friendly error message
});
The Payment Widget handles most errors internally. For unrecoverable errors, the widget fires an error event. It is the host application’s responsibility to handle these events, present an error message to the user, and unmount the widget.

Create a quote

Call Create quote with the origin account and the selected 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"
  }
}
A successful response includes the quote details. Present the quote to the user for confirmation before proceeding.
{
  "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"
  }
}
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"
    }
  }
}

Monitor for settlement

Card withdrawal transactions may remain in processing while the payment settles. Monitor until the transaction reaches a terminal state.

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 Payment Widget.