Skip to main content
Every wallet address that interacts with Iron must be registered (linked) to a customer before it can be used in any Autoramp flow: onramp, offramp, or swap. This is a regulatory requirement under the Travel Rule, which obliges Virtual Asset Service Providers to exchange originator and beneficiary information for crypto transfers. Iron supports two wallet types:
  • Self-hosted wallets: the customer controls the private key. Register with a signed proof-of-ownership message. For customers in the US and Rest of World who cannot sign from their custody UI (e.g. Fireblocks), register with a self-attested declaration instead, with no signature.
  • Hosted wallets: the wallet is custodied by another VASP (e.g. Coinbase, Kraken). Registration requires the VASP’s DID so Iron can exchange travel-rule data with the custodian.
Autoramp creation will fail if the recipient wallet address has not been registered first.

Verify a self-hosted crypto address

Submit a signature proving ownership of your cryptocurrency wallet. The verification process requires signing a specific message with your wallet’s private key.
1

Format the proof message:

I am verifying ownership of the wallet address {wallet_address} as customer {customer_id}. This message was signed on {date} to confirm my control over this wallet.
Replace:
  • {customer_id} with your customer ID
  • {wallet_address} with your wallet address
  • {date} with today’s date in DD/MM/YYYY format using UTC timezone
Example:
I am verifying ownership of the wallet address 0x742d35Cc6634C0532925a3b844Bc454e4438f44e as customer 4b85d15e-f343-41c0-809c-85314cae2fa6. This message was signed on 23/05/2025 to confirm my control over this wallet.
2

Sign this message using your wallet's private key

3

Submit the proof:

curl -X POST https://api.sandbox.iron.xyz/api/addresses/crypto/selfhosted \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 123e4567-e89b-12d3-a456-426614174000" \
-H "X-API-Key: $API_KEY" \
-d '{
  "customer_id": "4b85d15e-f343-41c0-809c-85314cae2fa6",
  "address": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
  "message": "I am verifying ownership of the wallet address 0x742d35Cc6634C0532925a3b844Bc454e4438f44e as customer 4b85d15e-f343-41c0-809c-85314cae2fa6. This message was signed on 23/05/2025 to confirm my control over this wallet.",
  "signature": "0xa5f1751b75a28c12694f02590d29b8cdd68b4f5c783273a75823fc6cfeaa702f1a65fa7c1838ae799fe755c92443cb51631d000922329cdd2ce799eee75f42531b",
  "blockchain": "Ethereum"
}'
The date must be today in DD/MM/YYYY using the UTC timezone (not your local timezone, not a stale year from a template). If you sign before UTC midnight and submit after, re-sign.
The message must be byte-identical between sign-time and POST-time (no rewording, no trailing newline, no whitespace edits), and the customer_id inside the message must equal the customer_id in the request body. EVM signatures use standard EIP-191 personal_sign (the default for cast wallet sign, ethers signMessage, viem signMessage); smart-contract wallets verify via EIP-1271. You can add additional text before or after the required message and verification still succeeds.

Register a self-attested crypto address

For direct customers who cannot produce a signature from their custody UI (e.g. Fireblocks), register a self-hosted wallet by declaring ownership instead of signing a proof-of-ownership message. The wallet is still registered as self-hosted and carries the same Travel Rule obligations as the signed flow.
Self-attestation is available only to customers in the US and Rest of World jurisdictions. Customers in the UK, EEA, Canada, and Australia must use the signed self-hosted flow and will receive a 403 from this endpoint. The sandbox skips this region check, so the example below works for any sandbox customer.
curl -X POST https://api.sandbox.iron.xyz/api/addresses/crypto/attested \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 123e4567-e89b-12d3-a456-426614174002" \
-H "X-API-Key: $API_KEY" \
-d '{
  "customer_id": "4b85d15e-f343-41c0-809c-85314cae2fa6",
  "address": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
  "blockchain": "Ethereum",
  "name": "Fireblocks vault"
}'
The registration requires:
  • customer_id: The customer’s UUID
  • address: The wallet address the customer declares they control
  • blockchain: The blockchain the address is on (e.g. Ethereum, Solana, Polygon, Base, Arbitrum)
  • name: Optional display name for this wallet
The Idempotency-Key header is required so the address is only registered once on retries. Pass the optional X-Sub-Partner-Id header to register the wallet under a specific sub-partner.
A successful registration returns the verified address. Attested wallets come back with address_type: "SelfHosted" and the sentinel proof_signature: "SELF_ATTESTED", which marks them as declared rather than cryptographically signed:
{
  "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
  "wallet_address": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
  "address_type": "SelfHosted",
  "blockchain": "Ethereum",
  "created_at": "2025-06-19T10:30:00+00:00",
  "disabled": false,
  "is_self": true,
  "name": "Fireblocks vault",
  "proof_message": "Self-attested ownership (no signature provided)",
  "proof_signature": "SELF_ATTESTED",
  "vasp_did": null
}

Error response

A 409 is returned when the wallet address is already registered. These address endpoints return the error as a plain string body, not a structured object:
"A crypto address with this wallet address already exists"

Register a hosted wallet

When the recipient wallet is custodied by another institution (VASP), for example Coinbase, Kraken, or Binance, you need to register the wallet address along with the institution’s DID so Iron can exchange travel-rule data with the custodian.
1

Search for the VASP (wallet provider):

First, find the DID (Decentralized Identifier) of the institution that hosts the wallet:
curl -X GET "https://api.sandbox.iron.xyz/api/addresses/crypto/hosted/vasps?q=bitstamp&limit=10" \
-H "X-API-Key: $API_KEY"
Response:
[
  {
    "did": "did:ethr:0x367f004f1062f68c038ac8d3c3071fedc18fb689",
    "name": "Bitstamp",
    "country": "LU",
    "website": "https://www.bitstamp.net/"
  }
]
2

Register the hosted wallet address:

Submit the wallet address with the VASP’s DID:
curl -X POST https://api.sandbox.iron.xyz/api/addresses/crypto/hosted \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 123e4567-e89b-12d3-a456-426614174001" \
-H "X-API-Key: $API_KEY" \
-d '{
  "customer_id": "4b85d15e-f343-41c0-809c-85314cae2fa6",
  "wallet_address": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
  "vasp_did": "did:ethr:0x367f004f1062f68c038ac8d3c3071fedc18fb689",
  "blockchain": "Ethereum"
}'
The registration requires:
  • customer_id: The customer’s UUID
  • wallet_address: The wallet address at the institution
  • vasp_did: The DID (Decentralized Identifier) of the institution hosting the wallet (obtained from the VASP search)
  • blockchain: The blockchain the address is on (e.g. Ethereum, Solana, Polygon, Base, Arbitrum)
The wallet must be registered in your name at the hosting institution. Iron will use the VASP DID to exchange travel rule information with the institution.

List verified addresses

Retrieve all verified cryptocurrency addresses for a customer:
curl -X GET https://api.sandbox.iron.xyz/api/addresses/crypto/{customer_id} \
-H "X-API-Key: $API_KEY"
Optionally filter by address type using the filter query parameter:
  • ?filter=Hosted: Only hosted wallet addresses
  • ?filter=SelfHosted: Only self-hosted wallet addresses
  • ?filter=All or no filter: All addresses (default)
Example with filter:
curl -X GET "https://api.sandbox.iron.xyz/api/addresses/crypto/4b85d15e-f343-41c0-809c-85314cae2fa6?filter=SelfHosted" \
-H "X-API-Key: $API_KEY"
The response includes details about each verified address:
  • id: Address ID
  • wallet_address: The wallet address
  • address_type: “Hosted” or “SelfHosted”
  • blockchain: The blockchain (e.g. “Ethereum”, “Solana”)
  • created_at: Registration timestamp
  • disabled: Whether the address is disabled
  • vasp_did: (For hosted wallets only) The VASP’s DID
  • proof_message: (For self-hosted wallets only) The verification message
  • proof_signature: (For self-hosted wallets only) The signature
Self-attested wallets are returned with address_type: "SelfHosted", so ?filter=SelfHosted includes them. To tell them apart from cryptographically signed wallets, check proof_signature: attested wallets carry the sentinel value "SELF_ATTESTED" and a proof_message that marks the wallet as self-attested rather than signed.
Common error scenarios:
  • Invalid proof message format
  • Incorrect date in proof message (must be today’s date in DD/MM/YYYY format)
  • Invalid signature
  • Wallet address already registered
  • Invalid blockchain/address format mismatch
  • Customer ID does not belong to your partner

Disable or enable an address

You can disable or enable a verified crypto address. Disabled addresses cannot be used for transactions.
curl -X PUT https://api.sandbox.iron.xyz/api/addresses/crypto/{address_id}/disabled \
-H "Content-Type: application/json" \
-H "X-API-Key: $API_KEY" \
-d '{
  "customer_id": "4b85d15e-f343-41c0-809c-85314cae2fa6",
  "disabled": true
}'
Addresses that were automatically disabled due to high risk (e.g., flagged by Chainalysis) cannot be re-enabled.

Fiat Sources Verification

Travel Rule Compliance