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 ACH deposit method selection and displays the necessary transfer instructions to the user. Your backend only needs to create the session and monitor for the incoming transfer.
The Payment Widget does not create any transaction. Monitoring and processing the incoming transfer must be handled by your backend via webhooks or polling.

Prerequisites

Walkthrough


Select deposit method

The widget lets the user select an ACH deposit method and view the transfer instructions.

Create a payment session

Call the Create payment session endpoint to create a session for the select-for-deposit flow.
POST /widgets/payment/sessions
{
  "flow": "select-for-deposit"
}
A successful response returns a session object with a token and url to initialize the widget.
{
  "session": {
    "flow": "select-for-deposit",
    "url": "https://payment.enterprise.uphold.com/",
    "token": "GEbRxBN...edjnXbL"
  }
}

Set up the widget

Initialize the widget for the select-for-deposit flow using the session data returned from the API.
import { PaymentWidget } from '@uphold/enterprise-payment-widget-web-sdk';

const initializeDepositWidget = async (session) => {
  // Initialize the widget
  const widget = new PaymentWidget<'select-for-deposit'>(session, { debug: true });

  // Set up event handlers
  widget.on('ready', () => {
    console.log('Ready');
  });

  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();
  });

  // Mount the widget
  widget.mountIframe(document.getElementById('payment-container'));
};
The example above is for web applications. 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 when the user selects a deposit method and completes the flow.
widget.on('complete', (event) => {
  const { via, selection } = event.detail.value;

  if (via === 'deposit-method') {
    const { depositMethod, account } = selection;
    handleBankDeposit(depositMethod, account);
  }

  widget.unmount();
});
The event payload contains two primary properties:
  • via — is set to deposit-method when the user selects a deposit method and completes the flow.
  • selection — contains the account that will receive the funds and the depositMethod configuration with transfer instructions.
The widget presents these details directly to the user, so you don’t need to display them separately. The ACH depositMethod.details contains:
{
  "type": "bank",
  "status": "ok",
  "details": {
    "network": "ach",
    "asset": "USD",
    "routingNumber": "021000021",
    "accountNumber": "123456789",
    "beneficiary": "John Doe",
    "bankName": "Example Bank",
    "bankAddress": {
      "line1": "456 Bank Avenue",
      "line2": "Fort Lee, NJ 07024"
    },
    "secondaryNetworks": [
      "fednow",
      "wire"
    ]
  }
}

Handle cancellations

The cancel event fires when the user closes the widget without selecting a deposit method.
widget.on('cancel', () => {
  widget.unmount();
  // Redirect back or show a cancellation message
});

Handle errors

The error event fires when an error occurs during the deposit method selection process.
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.

Monitor for the incoming transfer

The widget presents the deposit instructions to the user but does not monitor for the incoming transfer. Your application must do this via webhooks or polling.

Sample transaction

In a successful ACH bank deposit, the origin is represented as a bank-address node. The destination is the user’s default USD account.
{
  "transaction": {
    "id": "a2b3c4d5-e6f7-8a9b-c0d1-e2f3a4b5c6d7",
    "origin": {
      "asset": "USD",
      "amount": "500.00",
      "node": {
        "type": "bank-address",
        "network": "ach"
      }
    },
    "destination": {
      "asset": "USD",
      "amount": "500.00",
      "node": {
        "type": "account",
        "id": "a00507fe-628c-4f27-ae81-e1c40b2a8fb8",
        "ownerId": "e4ce04dc-67b7-4e9f-af91-482cb6f9fc4a"
      }
    },
    "status": "completed",
    "quotedAt": "2025-06-15T14:00:00Z",
    "createdAt": "2025-06-15T14:10:00Z",
    "updatedAt": "2025-06-15T14:30:00Z",
    "denomination": {
      "asset": "USD",
      "amount": "500.00",
      "target": "origin"
    }
  }
}

Notify the user

Display an in-app confirmation when the transaction is completed, and send an email if applicable.
You now support ACH bank transfer deposits via the Payment Widget.