> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.walletstech.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.walletstech.com/_mcp/server.

# Introduction

WalletsTech is a **custodial HD wallet service**. You create a user with one API call; the service derives a wallet on every supported chain from a single bip39 seed, encrypts and stores the keys, and returns the seed to you exactly once. From then on you check balances, send transfers, estimate fees and read history — all addressed by `userId` and `assetId`.

You never handle a private key and you never build a transaction. You ask for a transfer; the service signs it and broadcasts it.

## Supported chains

| Family | Chains                       | Native asset  |
| ------ | ---------------------------- | ------------- |
| UTXO   | Bitcoin                      | BTC           |
| EVM    | Ethereum, BNB Chain, Polygon | ETH, BNB, POL |
| TVM    | Tron                         | TRX           |
| SVM    | Solana                       | SOL           |

Plus USDT and USDC on every chain that has them. See [Asset IDs](/get-started/assets) for the full list and the integer that selects each one.

## Your endpoint

**The base URL is different for every client.** Your endpoint is issued to you along with your credentials — there is no shared public host, so there is no URL to copy from these pages. Wherever the examples say `$BASE_URL`, substitute the one you were given, and keep it in configuration rather than hard-coded in your source.

Only the host differs. Every path, body, header and response documented here is identical on every deployment.

## How a request works

Every endpoint is a **POST with a JSON body**, including the read-only ones. `/auth` is the only exception: it takes no body and carries its credentials in headers.

```bash
curl -X POST "$BASE_URL/balance" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "userId": "66b1f0c23d4e4a5b9c6d7e8f", "assetId": 21 }'
```

Every response uses the same envelope. Success puts the payload in `result`:

```json
{
  "result": "250.5",
  "requestId": "b7a1f0c2-3d4e-4a5b-9c6d-7e8f90a1b2c3"
}
```

Failure puts a safe, client-facing message in `message`:

```json
{
  "message": "Unknown assetId",
  "error": "400",
  "requestId": "b7a1f0c2-3d4e-4a5b-9c6d-7e8f90a1b2c3"
}
```

A `requestId` is on every response, success or failure. Send your own with an `X-Request-Id` header and we echo it back and write it to our audit log — quote it when you report a problem and we can find the exact request.

## Authentication

Every endpoint except `/auth` requires a bearer token:

```
Authorization: Bearer <token>
```

Call `/auth` with your client id and api key to get one. Tokens are valid for **15 minutes**. There is no refresh token and no refresh endpoint — when one expires you call `/auth` again. See [Authentication](/get-started/authentication) for the token lifecycle, and for the difference between your **API credentials** and a user's **wallet password** (they are unrelated, and confusing them is the most common integration mistake).

## Amounts

Amounts are **human-decimal strings** — never base units, never floats. Send `"0.5"`, not `500000000000000000` and not the JSON number `0.5`.

Balances, fees and transaction amounts all come back the same way, as decimal strings. This is deliberate. Floating-point numbers cannot represent most decimal values exactly, and a rounding error in an on-chain amount is money that is really gone. Keep amounts as strings end to end, and use a decimal library if you need to do arithmetic on them.

## What we never do

* **We never return your keys.** The seed phrase from `/create` is the one and only time key material leaves the service. There is no export endpoint — `/seed` exists and permanently returns `403`.
* **We never accept a private key from you.** The sender of a transfer is resolved from your `userId`, server-side.
* **We never log your secrets.** Passwords, seeds, mnemonics and private keys are stripped before anything is written to a log.

Your `password` encrypts the keystore and is **unrecoverable**. It is required to send funds. Store it, and store the seed phrase from `/create` — if you lose both, nobody can recover the funds, including us.