is_ownership_verified: true, which lets a linked Travel Rule transfer advance out of UNCONFIRMED_OWNERSHIP.
When Didit mints it for you
You rarely need to mint a session yourself. Whenauto_wallet_verification is on in your Travel Rule settings (the default), Didit auto-mints a widget session at transaction creation whenever a transfer needs end-user proof of wallet control:
- The transfer is in
UNCONFIRMED_OWNERSHIP- the counterparty wallet was declared self-hosted at submission, or an inbound transfer hit an unverified address-book entry. - The transfer is outbound and in
COUNTERPARTY_VASP_NOT_FOUNDorON_HOLD- no counterparty VASP could be reached, so ownership proof is the remaining path to completion.
action_required block (type: "wallet_ownership", with the url to open), and the SDKs launch it automatically on client-side submission.
Mint manually with POST /v3/travel-rule/widget-session/ when you want to pre-verify a wallet before any transfer exists, or when you have auto_wallet_verification turned off.
What it proves
The widget offers up to four proof methods. Which ones appear depends on how you minted the session and your Travel Rule settings:Satoshi test verify contract
Verifying a Satoshi test deposit is asynchronous, because the transaction has to be seen on-chain and then reach enough confirmations. Submitting the deposit’stxid returns 200 with status: "PENDING" the moment the deposit is seen on-chain but before it has enough confirmations - the txid is retained, not discarded.
It returns 200 with status: "VERIFIED" once the deposit confirms.
It returns 400 only for a genuinely wrong deposit: absent, sent from an unexpected address, or the wrong amount.
It returns 410 if the test window expires before a valid deposit is seen.
A background job automatically rechecks pending deposits and completes the proof the moment the transaction confirms, so the customer is never stranded after sending funds - they do not need to resubmit the txid.
When SATOSHI_TEST is offered, the widget session’s own expires_at is extended to cover the Satoshi test window, giving the deposit time to confirm before the session itself expires.
Flow
1
Mint a widget session
Call
POST /v3/travel-rule/widget-session/ with the wallet you need verified. Optionally link it to a transfer so the transfer advances automatically once ownership is proven.2
Open the returned URL
Send your customer to the
url from the response. They complete a proof there - no Didit account or API key needed; the token in the URL is the authentication.3
Detect completion
When a proof is verified, the widget marks the address-book entry verified and, if the session is linked to a transfer, advances it. Watch for
travel_rule.status.updated (linked transfers) or poll the widget context.Mint a widget session
url returned in the response verbatim - do not construct it yourself.
Open the returned URL
Detect completion
The widget exposes a public read endpoint keyed by the token - poll it to see progress, or rely on webhooks when the session is linked to a transfer:completed_atbecomes non-null once a proof is verified.- Each entry in
proofscarries the fields its method needs: aSATOSHI_TESTproof addsdeposit_address,expected_amount, and its ownexpires_at; aMESSAGE_SIGNINGproof addschallenge, the string the customer signs. - A
SATOSHI_TESTproof can sit atstatus: "PENDING"while its deposit is seen on-chain but unconfirmed, with no action needed from you or the customer - see Satoshi test verify contract above. - When the session was minted with a
transaction_id, verifying the proof advances the linked transfer (out ofUNCONFIRMED_OWNERSHIP, or resolving an inboundTRPtransfer), and atravel_rule.status.updatedwebhook fires. Prefer the webhook over polling. - The context endpoint returns
404for an unknown token and410once the session has expired without completing.
There are no one-shot dependencies here: the widget and your backend both converge on the same durable state (the verified address-book entry and the transfer status), so a dropped webhook or a closed tab is always recoverable by re-reading the transfer or the widget context.
Localization and branding
The widget renders in 54 languages, following the language path of the link (or the browser default). When whitelabel is enabled for your application, the widget inherits your verification-flow branding automatically: logo, brand colors, button and panel styling, custom font, favicon, and your app’s public name in the title. No separate configuration - the same customization you set up for KYC sessions applies here. A user who returns to an already-completed link sees the completion screen again; if you passed acallback_url, the widget returns them there.
Expired links show a branded expiry screen prompting them to request a new link (mint a new session or use action: "resend" flows as appropriate).
Next steps
Travel Rule
The full exchange lifecycle, rails, settings, and receiving flows.
Wallet address book
Register the wallets you control so inbound transfers resolve against them.
Webhooks
Subscribe to travel_rule.status.updated to react when a proof advances a transfer.
Native SDKs
Open the widget URL with the system browser, not the SDK webview.