Introduction

A developer-managed multi-chain wallet API. One user, one seed, six chains.

View as MarkdownOpen in Claude

WalletsTech is a developer-managed HD wallet service built on a zero-knowledge keystore. You create a user with one API call; the service derives a wallet on every supported chain from a single bip39 seed, encrypts the keys under a password only you hold, 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.

On Custody & Risk

WalletsTech operates a semi-custodial architecture built on a client-side encrypted, zero-knowledge keystore. While encrypted key materials are hosted on our infrastructure to enable automated signing, WalletsTech does not store or have access to your passwords or raw private keys.Your password is required for every /send request, is processed strictly in-memory, and cannot be recovered. Backing up the initial mnemonic seed and managing password security—including encryption in transit—is your sole operational and legal responsibility.The service is provided on an “as-is” and “as-available” basis. WalletsTech expressly disclaims any liability for financial losses resulting from credential exposure on your infrastructure, client-side data breaches, or missing system backups.

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

FamilyChainsNative asset
UTXOBitcoinBTC
EVMEthereum, BNB Smart Chain (BSC), PolygonETH, BNB, POL
TVMTronTRX
SVMSolanaSOL

Plus USDT and USDC on every chain that has them. See Asset IDs for the full list and the integer that selects each one.

Environments

Base URLFor
Sandboxhttps://api-demo.walletstech.comDevelopment and testing. Start here.
Productionhttps://api.walletstech.comReal funds. Transfers cannot be reversed.

Neither is usable until you have credentials. Every endpoint requires a token, and a token requires a client id and api key issued by your service operator — so getting those is step one. Ask for sandbox credentials first, and build against sandbox.

Credentials are per environment: a sandbox client id and api key will not authenticate against production. Wherever the examples say $BASE_URL, substitute the environment you are targeting, 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 both.

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.

$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:

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

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

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

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.

On /send that header is required, and it doubles as the idempotency key: retry a transfer with the same id and it will not go out twice. See Reliability.

Authentication

Every endpoint except /auth and /refresh requires a bearer token:

Authorization: Bearer <token>

Call /auth with your client id and api key to get one. It returns a pair: an access token valid for 15 minutes, and a 7-day refresh token. When the access token expires, post the refresh token to /refresh for a fresh pair instead of calling /auth again — refresh tokens are single-use and rotate on every call.

See 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. /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.