declared- or verified-level Travel Rule verification for a saved crypto address — see Address Book overview for how verification levels work.
Prerequisites
- The user has completed onboarding and has the required capabilities enabled.
- The user already has a
cryptoexternal account — see Create external account. - For the
verifiedlevel, the user also needs thecrypto-depositscapability.
Declared level
Set up the verification
Call Set up crypto external account verification withlevel: "declared".
201 response means a new verification was initiated. Its requestForInformation.proofOptions.selfDeclaration.schema describes exactly which fields to collect from the user.
Calling this endpoint again is safe: a new request for information is initiated (
201) only when there is no declared verification yet or the last one failed. While it’s pending, or once it’s completed, the same verification is returned unchanged (200) — it’s never redone or regressed.Resolve the Travel Rule RFI
For acrypto-address-travel-rule RFI, selfDeclaration is the only mechanism listed under proofOptions — see Address Book overview for why.
Self-declaration
Present the fields fromproofOptions.selfDeclaration.schema to the user, then submit their answers with Update request for information.
When
isVASP is true, also include a vaspDid identifying the VASP that owns the address. If it can’t be resolved by the Travel Rule provider, the request returns 404 entity_not_found (details.entity: "vasp") — ask the user to double-check the VASP they selected.Confirm the verification
Call Get external account verification to confirm the verification iscompleted.
The address now carries a completed
declared verification, reflected in the account’s compact verifications array on Get external account.Testing
Verify the following:- Set up crypto external account verification returns
201with apendingverification and acrypto-address-travel-ruleRFI. - Update request for information with a valid self-declaration proof returns
200withstatus: "ok". - Get external account verification now returns
status: "completed". - Calling Set up crypto external account verification again returns
200with the same, unchanged verification.
Verified level
After setup, therequestForInformation.proofOptions offers two independent proof options for a verified-level verification — the user (or your backend) resolves whichever is more convenient: signing a message, or sending an exact on-chain amount. Either one resolves the same verification.
Set up the verification
Call Set up crypto external account verification withlevel: "verified".
201 response means a new verification was initiated, returning both proof options.
Calling this endpoint again is safe: a new request for information is initiated (
201) only when there is no verified verification yet or the last one failed (e.g. it expired). While it’s pending, or once it’s completed, the same verification is returned unchanged (200) — it’s never redone or regressed.Setting up and getting a
verified verification both return 409 user_capability_failure with details.capability.code: "crypto-deposits" when the user lacks that capability. The declared level isn’t affected.To receive the Satoshi test, Uphold uses the user’s default account for the external account’s asset, creating one if there is none, and creates a crypto deposit address for the network if needed. A new account or deposit address may therefore appear in the user’s accounts after the first
verified set up.Submit a proof
- Message signing
- Satoshi test
Have the user sign The proof’s
proofOptions.messageSigning.message verbatim with their wallet, producing a proof that validates against the returned proofOptions.messageSigning.schema. Then submit it with Update request for information.type is the signing scheme used by the wallet — one of the values in proofOptions.messageSigning.schema.properties.proof.properties.type.enum (e.g. bip-137, eip-191).Confirm the verification
Call Get external account verification to confirm the verification iscompleted. The normalized public proof shape is the same regardless of which option was used to resolve it.
The address now carries a completed
verified verification, reflected in the account’s compact verifications array on Get external account.Testing
Verify the following:- Set up crypto external account verification with
level: "verified"returns201with apendingverification and acrypto-address-verificationRFI exposing bothmessageSigningandsatoshiTestproof options. - Update request for information with a valid message signing proof returns
200withstatus: "ok", and with an invalid signature returns409 proof_invalid. - Sending the exact Satoshi test amount makes Get request for information return
status: "ok", without needing to update the RFI directly. - Get external account verification now returns
status: "completed"with the normalized proof. - Calling Set up crypto external account verification again while
pendingor oncecompletedreturns200with the same, unchanged verification. - Without the
crypto-depositscapability, set up and get forverifiedreturn409 user_capability_failure.