Skip to main content
This guide walks you through resolving a Travel Rule request for information on an on-hold crypto deposit using the Travel Rule Widget — from detecting the on-hold status to letting the widget collect and submit proof.
Want to collect and submit proof yourself instead of using a managed UI? See Travel Rule deposit via the REST API — it also documents the RFI’s context and proofOptions fields in detail.

Prerequisites

Walkthrough

Detect the on-hold transaction

When a crypto deposit is placed on hold due to a Travel Rule requirement, Uphold sends a core.transaction.status-changed webhook with status: on-hold and statusDetails.reason: pending-requests-for-information.
Abbreviated — the transaction object includes additional fields.
If you are using polling instead of webhooks, check for status: on-hold and statusDetails.reason: pending-requests-for-information on the transaction object.

Notify the user

Surface the on-hold status to the user out-of-band (email or push notification) — deposits can sit on-hold indefinitely until resolved.

Resolve the Travel Rule RFI

The Travel Rule Widget allows the user to resolve a Travel Rule RFI for a specific transaction.

Create a widget session

Create a session tied to the transaction by calling Create session with flow: deposit-form and the data property containing the referenceId — the transaction’s id. No prior call to list RFIs is needed; the widget resolves the pending RFI for that transaction on your behalf.
A successful response returns the session data needed to initialize the widget.
Widget sessions expire after 2 minutes. If the session expires before the user opens the widget — or while they are mid-form — the widget emits an error event. Create a new session and re-mount to let the user retry.

Set up the widget

Initialize the widget using the session returned from the API and mount it into your application. The widget does not unmount itself — always call unmount() after handling any event.
Both examples above are for web applications — either creating the iframe yourself or letting the SDK do it. For native apps using a WebView, see Native apps with the SDK for the SDK’s native-bundling pattern, or Setup with JavaScript for the no-SDK approach that loads the session url directly as the WebView’s top-level page.

Handle the complete event

Once the user finishes the form, the widget automatically resolves the RFI by calling Update request for information internally with the collected proof.
Calling Update request for information yourself is only needed if you’re not using the widget and are resolving the Travel Rule requirement directly — not part of this widget-based flow.
When complete fires, unmount the widget and confirm the RFI is resolved before proceeding — whether it is immediately ok or still pending depends on the proof type used:
  • Synchronous proofs (self-declaration, message signing) — the RFI is fully resolved as soon as complete fires. Proceed directly to Monitoring for settlement to listen for transaction status changes.
  • Asynchronous proofs (Satoshi test, a small on-chain test transaction) — complete firing does not mean the RFI is resolved yet; resolution depends on the microtransfer settling on-chain and confirmed by Uphold. Wait for it to settle, then proceed to Monitoring for settlement to listen for transaction status changes.
Use Get request for information to check which proof type was used and confirm the RFI’s status.

Handle cancellations

The cancel event fires when the user closes the widget without completing the form. The transaction remains on-hold until the RFI is resolved — create a new widget session for the same transaction to let the user retry. See cancel event for the event reference.

Handle errors

The error event fires when an unrecoverable error occurs. See error event for the full error shape and available properties.

Monitoring for settlement

After the RFI is resolved, the transaction will move from on-hold to processing and then to either completed or failed. Monitor the transaction status using webhooks (recommended) or polling (fallback):
  • Webhook events (recommended):
    • core.transaction.status-changed
      • status: processing → transaction is being processed
      • status: completed → necessary confirmations reached
      • status: failed → transaction failed
  • Polling (fallback): Get transaction
When the transaction reaches completed or failed, notify the user of the outcome.

Testing

To trigger a Travel Rule RFI on a deposit, use a GB user account and send 30 XRP from an unhosted (self-custodial) wallet to the user’s Uphold deposit address. Verify the following:
  1. A core.transaction.status-changed webhook is received with status: on-hold and statusDetails.reason: pending-requests-for-information.
  2. Creating a widget session with flow: deposit-form and the transaction id as referenceId succeeds.
  3. After completing the widget flow, the RFI status changes to ok and the transaction moves back to processing.
  4. The transaction status updates from processing to completed within a few minutes, assuming no other blockers.
For the equivalent withdrawal guide, see Travel Rule withdrawal via the Travel Rule Widget.