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 FPS 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 FPS 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 FPS depositMethod.details contains:
{
  "type": "bank",
  "status": "ok",
  "details": {
    "network": "fps",
    "asset": "GBP",
    "sortCode": "123456",
    "accountNumber": "12345678",
    "reference": "UH12345678",
    "beneficiary": "John Doe",
    "bankName": "Example Bank",
    "bankAddress": {
      "line1": "123 Bank Street",
      "line2": "London, United Kingdom"
    }
  }
}

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 FPS deposit, the origin is represented as an external-account node. This is because the origin bank details are automatically registered as an external account. The destination is the account selected when the deposit instructions were generated, or the user’s default GBP account if the transfer was sent without a reference, or the selected account doesn’t exist anymore.
{
  "transaction": {
    "id": "b1bbbc0f-dae2-4e94-9e6d-4b9d5a1f3c1f",
    "origin": {
      "asset": "GBP",
      "amount": "250.00",
      "node": {
        "type": "external-account",
        "id": "aa6e6efa-8d73-497c-8278-0347f459bd68",
        "ownerId": "e4ce04dc-67b7-4e9f-af91-482cb6f9fc4a"
      }
    },
    "destination": {
      "asset": "GBP",
      "amount": "250.00",
      "node": {
        "type": "account",
        "id": "a00507fe-628c-4f27-ae81-e1c40b2a8fb8",
        "ownerId": "e4ce04dc-67b7-4e9f-af91-482cb6f9fc4a"
      }
    },
    "status": "completed",
    "quotedAt": "2025-01-10T11:02:39Z",
    "createdAt": "2025-01-10T11:12:39Z",
    "updatedAt": "2025-01-10T11:13:08Z",
    "denomination": {
      "asset": "GBP",
      "amount": "250.00",
      "target": "origin"
    }
  }
}
The new external account can be then retrieved with Get external account to show the sender’s bank details alongside the transaction, or to withdraw funds to the same account in the future.
{
  "externalAccount": {
    "id": "aa6e6efa-8d73-497c-8278-0347f459bd68",
    "ownerId": "e4ce04dc-67b7-4e9f-af91-482cb6f9fc4a",
    "type": "bank",
    "status": "ok",
    "label": "GBP Bank Account",
    "asset": "GBP",
    "network": "fps",
    "features": [
      "withdraw"
    ],
    "details": {
      "accountNumber": "12345678",
      "sortCode": "123456"
    },
    "createdAt": "2025-01-10T11:12:39Z",
    "updatedAt": "2025-01-10T11:13:08Z"
  }
}

Notify the user

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