> ## Documentation Index
> Fetch the complete documentation index at: https://developers.circle.com/llms.txt
> Use this file to discover all available pages before exploring further.

# How-to: Use self-hosted wallets

> Register and verify an end user's self-hosted wallet, then transfer funds to it from a Digital Asset Account

A self-hosted wallet is a blockchain wallet an end user controls directly,
outside any custodian. Before a Digital Asset Account (DAA) can send funds to
one, the end user must prove they own it. You register the wallet as a recipient
address with its ownership details, then complete a satoshi-test verification:
Circle asks the end user to send a small deposit from the self-hosted wallet,
which confirms control of the private key. Once verified, the address becomes
eligible for transfers.

<Note>
  The Digital Asset Accounts API base URL is `https://api-sandbox.circle.com` for
  sandbox and `https://api.circle.com` for production. Set your API key in the
  `Authorization` header using the format `Bearer YOUR_API_KEY`. See
  [Sandbox environment](/digital-asset-accounts/references/testing-in-sandbox) and
  [Going to production](/digital-asset-accounts/references/going-to-production)
  for environment details.
</Note>

## Prerequisites

Before you begin, ensure that you've:

* Onboarded the end user and retrieved an active account. See
  [Onboard customers](/digital-asset-accounts/quickstarts/onboard-customers).
* Collected the end user's device risk signals with the
  [`@circle-fin/device-checks`](/end-user-onboarding/howtos/collect-device-risk-signals)
  SDK. You pass the resulting `deviceId` on the request.
* For end users in the EEA, prepared a Strong Customer Authentication (SCA)
  assertion. Registering a recipient address is an SCA-gated operation. See
  [Implement SCA](/digital-asset-accounts/howtos/strong-customer-authentication).

## Steps

### Step 1. Register the self-hosted wallet as a recipient address

Call `POST /v1/addresses/recipient` with the wallet's `address` and `chain`, the
end user's `riskSignals`, and an `ownership` object. For a self-hosted wallet,
set `type` to `first_party`, set `custody.type` to `self_hosted`, and omit
`vaspId`.

<Note>
  Self-hosted wallets support first-party ownership only. The wallet must belong
  to the end user; you can't register a `third_party` self-hosted wallet.
</Note>

For end users in the EEA, pass the SCA headers (`X-Sca-Challenge-Id` and
`X-Sca-Assertion`).

```bash theme={null}
curl -X POST "https://api-sandbox.circle.com/v1/addresses/recipient" \
  -H "Authorization: Bearer $API_KEY" \
  -H "X-Sca-Challenge-Id: $SCA_CHALLENGE_ID" \
  -H "X-Sca-Assertion: $SCA_ASSERTION" \
  -H "Content-Type: application/json" \
  -d '{
    "idempotencyKey": "b7e8f1a2-3c4d-4e5f-8a9b-0c1d2e3f4a5b",
    "address": "0x8f3b2c1a9d4e4f6ab7c81e2d3f4a5b6c7d8e9f01",
    "chain": "ETH",
    "currency": "USDC",
    "description": "End user self-hosted wallet",
    "riskSignals": {
      "ipAddress": "203.0.113.42",
      "sessionId": "8f3b2c1a-9d4e-4f6a-b7c8-1e2d3f4a5b6c",
      "deviceId": "device-id-from-checkDevice"
    },
    "ownership": {
      "type": "first_party",
      "custody": { "type": "self_hosted" }
    }
  }'
```

The address is created in `pending_verification` and the response includes a
`verificationChallenge` with the satoshi-test details:

```json theme={null}
{
  "data": {
    "id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
    "address": "0x8f3b2c1a9d4e4f6ab7c81e2d3f4a5b6c7d8e9f01",
    "chain": "ETH",
    "currency": "USDC",
    "description": "End user self-hosted wallet",
    "status": "pending_verification",
    "verificationChallenge": {
      "destinationAddress": "0x1234567890abcdef1234567890abcdef12345678",
      "paymentId": "9f8e7d6c-5b4a-3210-fedc-ba9876543210",
      "amount": { "amount": "0.42", "currency": "USDC" },
      "status": "active"
    }
  }
}
```

### Step 2. Complete the satoshi-test verification

Have the end user send exactly the challenge `amount` of the challenge
`currency` from their self-hosted wallet to the `destinationAddress`. If the
chain requires a memo or tag, include the `paymentId`.

Poll the address until Circle confirms the deposit and the `status` moves to
`verification_succeeded`, then `active`:

```bash theme={null}
curl "https://api-sandbox.circle.com/v1/addresses/recipient/a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d" \
  -H "Authorization: Bearer $API_KEY"
```

If the challenge `status` becomes `expired` before the deposit arrives, request
a fresh one with `POST /v1/addresses/recipient/{id}/verification/resend`, then
repeat the deposit against the new `destinationAddress` and `amount`.

### Step 3. Send funds to the verified wallet

Once the recipient address is `active`, it's eligible for transfers. Create a
transfer to it with `POST /v1/accounts/transfers`, using the recipient address
`id` as the destination. See
[Send crypto transfers](/digital-asset-accounts/howtos/crypto-transfers) for the
full transfer request and response.
