#Users
End-users and their Static Wallet Address — one permanent address per user, reused for every payment
3 endpoints. Generated from docs/openapi.yaml v1.0.0.
| Endpoint | Summary |
|---|---|
GET /v1/users | List your users |
POST /v1/users | Create a user and derive its address |
GET /v1/users/{externalId}/addresses | Read a user's Static Wallet Address |
#GET/v1/users
List your users · Auth: bearer API key · operationId: listUsers
Your users, newest first (by creation time). Scoped to your tenant — nobody else's users are ever visible.
total is counted through the SAME filter as the rows, so it is the size of the filtered set, not of your whole user base: page with offset until you have total rows. The page is ordered on figures the database cannot compute (a USD total needs the price feed), so at most 2000 matching users are read; total counts no further than that, and truncated: true says the cap was hit — narrow the filter.
balance_usd, balances[].usd and card_balance are price-feed estimates for display, with no _base twin; read exact balances from GET /v1/users/{externalId}/balances.
Reserved internal accounts (the card-programme float pot) are excluded, so this list agrees with the user counts your dashboard shows.
from/to accept either a bare IST calendar day (YYYY-MM-DD, the whole day INCLUDED on both ends) or a full RFC 3339 instant with an offset. Anything else is a 400 rather than a silently ignored filter.
#Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
search | query | string | no | Case-insensitive substring match on external_user_id. |
from | query | string | no | Only users created on/after this IST day (or instant). |
to | query | string | no | Only users created on/before this IST day (or before this instant). |
limit | query | integer | no | — (default 50; min 1; max 200) |
offset | query | integer | no | — (default 0; min 0) |
sort | query | string | no | What orders the page — when the user was created, what they hold (USD estimate), or when they last moved money. A user who never moved money sorts last either way. (one of created, balance, last_active; default "created") |
dir | query | string | no | — (one of asc, desc; default "desc") |
#Responses
| Status | Body | Meaning |
|---|---|---|
200 | object | One page of users, plus the total matching the same filter. |
400 | Error | Body/params failed validation, or a domain rule was violated. error is one of: validationerror, unknownasset, assetdisabled, invalidamount, amountbelowminimum, badamount, invalidaddress, invalid_request. |
401 | Error | Missing, malformed or unknown API key. |
200 response body
| Field | Type | Description |
|---|---|---|
users required | object[] | — |
users[].user_id required | string | Your external_user_id for this user. |
users[].account_kind required | string | end_user is one of YOUR customers; merchant_own is an account that holds your own money (e.g. your treasury). (one of end_user, merchant_own) |
users[].created_at required | string<date-time> | — |
users[].balance_usd required | string | USD estimate of everything the user holds, two decimals. Display only. |
users[].balances required | object[] | Per-asset holdings, largest USD value first. |
users[].balances[].asset_id required | string | — |
users[].balances[].symbol required | string | — |
users[].balances[].amount required | string | A monetary value as a decimal string. Always paired with a *_base field that carries the exact integer base-unit value; compute with the _base string. |
users[].balances[].usd required | string | Price-feed estimate; no _base twin. |
users[].card_balance required | string | null | Sum on the user's cards (available + pending); null when the user has no card. |
users[].last_active_at required | string<date-time> | null | The user's most recent ledger movement; null when none. |
total required | integer | Users matching the filter, ignoring limit/offset — counted no further than 2000. |
truncated required | boolean | true when more than 2000 users matched and total stopped there. Narrow the filter. |
limit required | integer | — |
offset required | integer | — |
{
"users": [
{
"user_id": "user-42",
"account_kind": "end_user",
"created_at": "2026-08-31T09:15:00.000Z",
"balance_usd": "125.40",
"balances": [
{
"asset_id": "usdt_trc20",
"symbol": "USDT",
"amount": "1.5",
"usd": null
}
],
"card_balance": "string",
"last_active_at": "2026-08-31T09:15:00.000Z"
}
],
"total": 1,
"truncated": true,
"limit": 1,
"offset": 1
}#Example request
curl -X GET 'https://api.cryptoinfra.build/v1/users?from=2026-08-01&to=2026-08-31' \
-H 'Authorization: Bearer ck_live_your_key'#POST/v1/users
Create a user and derive its address · Auth: bearer API key · operationId: createUser
Creates a user under your tenant and derives their Static Wallet Address — one permanent TRON address. Every asset in GET /v1/assets lands on that one address; addresses is a list so a client reads it the same way whatever it holds. Idempotent on external_user_id: replaying returns the existing user and address (still 201).
#Request body
application/json · required
| Field | Type | Description |
|---|---|---|
external_user_id required | string | A number of 5 to 10 digits — the ID this user has in your own system. Letters are refused. (minLength 5; maxLength 10; pattern ^[0-9]{5,10}$) |
#Responses
| Status | Body | Meaning |
|---|---|---|
201 | UserAddresses | User created (or already existed). |
400 | Error | Body/params failed validation, or a domain rule was violated. error is one of: validationerror, unknownasset, assetdisabled, invalidamount, amountbelowminimum, badamount, invalidaddress, invalid_request. |
401 | Error | Missing, malformed or unknown API key. |
201 response body — UserAddresses
| Field | Type | Description |
|---|---|---|
user_id required | string | Your externaluserid. |
addresses required | object[] | — |
addresses[].chain required | string | The chain an address or asset is on. TRON is the only network the platform serves: btc, eth, bsc and sol were retired — historical addresses on them are never handed out again and nothing scans them. Read the value as an open string rather than a closed list, so a chain added later does not break your client. (one of tron) |
addresses[].address required | string | The Static Wallet Address — permanent |
{
"user_id": "string",
"addresses": [
{
"chain": "tron",
"address": "string"
}
]
}#Example request
curl -X POST 'https://api.cryptoinfra.build/v1/users' \
-H 'Authorization: Bearer ck_live_your_key' \
-H 'Content-Type: application/json' \
-d '{
"external_user_id": "10482"
}'#GET/v1/users/{externalId}/addresses
Read a user's Static Wallet Address · Auth: bearer API key · operationId: getUserAddresses
#Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
externalId | path | string | yes | Your external_user_id for the user. |
#Responses
| Status | Body | Meaning |
|---|---|---|
200 | UserAddresses | The user's Static Wallet Address, as a one-entry list keyed by chain. |
401 | Error | Missing, malformed or unknown API key. |
404 | Error | Unknown externaluserid for this tenant. |
200 response body — UserAddresses
| Field | Type | Description |
|---|---|---|
user_id required | string | Your externaluserid. |
addresses required | object[] | — |
addresses[].chain required | string | The chain an address or asset is on. TRON is the only network the platform serves: btc, eth, bsc and sol were retired — historical addresses on them are never handed out again and nothing scans them. Read the value as an open string rather than a closed list, so a chain added later does not break your client. (one of tron) |
addresses[].address required | string | The Static Wallet Address — permanent |
{
"user_id": "string",
"addresses": [
{
"chain": "tron",
"address": "string"
}
]
}#Example request
curl -X GET 'https://api.cryptoinfra.build/v1/users/string/addresses' \
-H 'Authorization: Bearer ck_live_your_key'