Prerequisites
- The user has completed onboarding and has the required capabilities enabled.
Walkthrough
Detect the on-hold transaction
When a crypto deposit is placed on hold due to a Travel Rule requirement, Uphold sends acore.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.List transaction RFIs
Call List request for information endpoint to retrieve all RFIs byreferenceId (transaction or quote ID), then filter the results to keep only entries where type is “travel-rule”. From that filtered set, check whether any RFI has a status of “pending” — if so, the transaction is still awaiting resolution. The deprecated transaction-nested endpoint still works but should not be used for new integrations.
If all travel-rule RFIs have a status of “ok”, the transaction may have already been moved out of on-hold status automatically. Make sure to re-fetch the transaction and check its current status before taking further action.
Resolve the 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 RFI by calling Create session withflow: deposit-form and the data property containing the requestForInformationId. Each session is single-use and bound to a specific RFI.
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 callunmount() 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 data.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.
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, cryptographic signature) — the RFI is fully resolved as soon as
completefires. Proceed directly to Monitoring for settlement to listen for transaction status changes. - Asynchronous proofs (micro-transfer, e.g. a small on-chain test transaction) —
completefiring does not mean the RFI is resolved yet; resolution depends on the micro-transfer settling on-chain and confirmed by Uphold. Wait for it to settle, then proceed to Monitoring for settlement to listen for transaction status changes.
Handle cancellations
Thecancel 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 RFI to let the user retry. See cancel event for the event reference.
Handle errors
Theerror 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 fromon-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 processedstatus: completed→ necessary confirmations reachedstatus: failed→ transaction failed
- core.transaction.status-changed
- Polling (fallback): Get transaction
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:- A
core.transaction.status-changedwebhook is received withstatus: on-holdandstatusDetails.reason: pending-requests-for-information. - List requests for information returns an RFI with
type: travel-ruleandstatus: pending. - After completing the widget flow, the RFI status changes to
okand the transaction moves back toprocessing. - The transaction status updates from
processingtocompletedwithin a few minutes, assuming no other blockers.