Skip to main content

Migrate User Without Wallet (Single)

Creates one user and asks the custody provider for a wallet on the default network of the chain named by chain_id. The user is stored synchronously; the wallet (custody: true) is created asynchronously and appears in List User Wallets once custody answers. Unless kyc_sent is true, the platform then sends its KYC token(s) to the new wallet on every network of the chain. See the overview for the identity, KYC and duplicate rules.

The chain is resolved after the user is stored: if chain_id does not resolve, the request answers 400 but the user already exists without a wallet. Add the wallet with Create User Wallet rather than repeating the migration (it would now be refused as a duplicate).

Required permission: user:create

Request​

POST /v2/users/migrate/without-wallet

Headers​

NameDescription
AuthorizationRequired. Bearer <access_token>
Content-TypeRequired. application/json

Body​

FieldTypeRequiredDescription
chain_idstringYesChain (chains id) to create the custody wallet on. Must have a default network
emailstringNoEmail. Required when external_id is absent; must be a valid email when given
external_idstringNoOpaque identifier for KVKK-anonymized migration. Required when email is absent
namestringNoFirst name; not stored when empty
surnamestringNoLast name; not stored when empty
kyc_sentbooleanNoDefault false. true means KYC was already done: nothing is sent and the new wallet is recorded as KYC-verified on the chain's default network

Example​

curl --request POST \
--url '{{baseUrl}}/v2/users/migrate/without-wallet' \
--header 'Authorization: Bearer <access_token>' \
--header 'Content-Type: application/json' \
--data '{
"email": "auto@example.com",
"name": "Auto",
"surname": "Wallet",
"chain_id": "6740e0a10000000000000101",
"kyc_sent": false
}'

KVKK mode (identifier only):

curl --request POST \
--url '{{baseUrl}}/v2/users/migrate/without-wallet' \
--header 'Authorization: Bearer <access_token>' \
--header 'Content-Type: application/json' \
--data '{
"external_id": "EXT-9001",
"chain_id": "6740e0a10000000000000101",
"kyc_sent": true
}'

Response​

Status Code: 201 Created

{
"id": "6913872755654191dede37da",
"external_id": "EXT-9001",
"name": "",
"surname": "",
"email": "",
"identity_number": "",
"status": 0,
"created_at": "2026-08-21T09:14:02.511Z",
"kyc": null
}

The created user, in the shape of Get User by ID. The wallet does not exist yet at this point; poll List User Wallets.

Errors​

StatusCodeDescription
40010015Validation failed (chain_id missing, malformed email) — see details
40010015Row skipped; message is the reason: missing_email_and_external_id, duplicate_email or duplicate_external_id
40010015chain not found / chain has no default network configured. The user has already been created
40010016chain_id is not a valid id. The user has already been created

For imports where one bad row must not stop the rest, use Bulk or CSV. See Errors for the error format and common codes.