Wallets

All routes require x-api-key. Mutation routes explicitly marked as session routes also require Authorization: Bearer <session> and the API key permission shown. Responses use the standard envelope documented in Responses and errors.

Common auth failures occur before route handling: 403 for an invalid API key or missing permission, 401 for a missing/invalid required session, and 429 when the API key rate limit is exceeded.

Endpoints#

MethodPathAdditional access
PATCH/v1/wallet/alias
GET/v1/wallet/default
POST/v1/wallet/default
GET/v1/wallet/list
POST/v1/wallet/externalTeam admin
GET/v1/wallet/portfolio
GET/v1/wallet/evm/check-gas-balance
GET/v1/wallet/evm/allowance/{action}
POST/v1/wallet/evm/allowance/{action}Session + WRITE
DELETE/v1/wallet/evm/allowance/{action}Session + WRITE
POST/v1/wallet/evm/gas-sponsorSession + WRITE

Wallet records#

PATCH /v1/wallet/alias#

Updates or clears an alias after confirming that the team belongs to the API-key application and the wallet belongs to that team.

Body:

FieldTypeRequiredConstraints
walletAddressstringYes1–64 characters
teamIdUUIDYes
aliasstring or nullYesNon-empty string, or null to clear

Success: 200 with data: { walletAddress, teamId, alias }.

Route errors: 400 invalid body; 404 application team or wallet not found; 500 lookup/update failure.

GET /v1/wallet/default#

Query:

FieldTypeRequiredBehavior
teamIdUUIDConditionalMay be omitted only when the API key itself supplies a team ID.

The requested team must belong to the API-key application. Success: 200 with data: { defaultWallet }; defaultWallet is the stored wallet record or null.

Route errors: 400 no team ID is available; 404 application team not found; 500 retrieval failure.

POST /v1/wallet/default#

The teamId query parameter is required for this method. Body:

{
	"walletAddress": "0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6"
}

Success: 200.

{
	"success": true,
	"data": {
		"message": "Default wallet updated successfully",
		"walletAddress": "0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6"
	}
}

Route errors: 400 missing teamId or invalid body; 404 application team or team wallet not found; 500 update failure.

GET /v1/wallet/list#

Exactly one scope query is required:

FieldTypeRequiredConstraints
profileIdUUIDOne of profileId/teamIdMutually exclusive with teamId
teamIdUUIDOne of profileId/teamIdMutually exclusive with profileId
includeCompliancestringNoOnly the literal true enables compliance records

Only valid EVM wallet records are returned. Success: 200 with data: { wallets: Wallet[], total: number }; total is the returned array length. There is no pagination.

Route errors: 400 invalid/missing scope; 500 retrieval failure.

POST /v1/wallet/external#

Creates an external wallet for an existing profile in an application-owned team. The profile’s membership must have the admin role.

FieldTypeRequiredConstraints
teamIdUUIDYes
profileIdUUIDYesMust belong to teamId
addressstringYesValid for walletType
walletTypeenumYesEVM, SVM, BTC, or FIAT
labelstringNo
metadataobjectNoString keys

Success: 201 with data: { address, walletType, profileId, teamId, alias, metadata, createdAt }.

Route errors: 400 invalid body/address; 403 profile is not a team admin; 404 team or profile not found; 409 wallet already exists in the team; 500 lookup/create failure.

GET /v1/wallet/portfolio#

wallets is a required comma-separated list of EVM addresses. Invalid entries are ignored if at least one valid address remains.

Success: 200 with an array of portfolio objects:

{
	"success": true,
	"data": [{
		"totalUsdBalance": 1500.5,
		"tokens": {
			"USDC": {
				"totalUsdBalance": 1000,
				"totalBalance": 1000,
				"tokenLogo": null,
				"chains": {
					"ethereum": {
						"address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
						"balance": 1000,
						"price": 1,
						"chainLogo": null,
						"chainId": 1
					}
				}
			}
		}
	}]
}

Route errors: 400 missing wallet list or no valid address; 500 supported-token configuration failure. Upstream balance failures for individual wallet/chain pairs are omitted rather than failing the request.

EVM gas and allowances#

GET /v1/wallet/evm/check-gas-balance#

QueryTypeRequiredConstraints
walletstringYesOne or more comma-separated EVM addresses
tokenAddressstringYesEVM token address
chainSlugstringYesSupported chain slug or positive numeric chain ID

Success: 200 with one result per wallet: { wallet, minimumGasWei, nativeBalance, sufficient, difference }. A result can additionally contain error: { code, message } when estimation or balance retrieval failed; these per-wallet failures still return HTTP 200.

Route errors: 400 missing/invalid address or unsupported chain.

Allowance action values#

action accepts send, request, otc, general, all, or multiple. general requires executorAddress. Executor availability is chain-dependent.

GET /v1/wallet/evm/allowance/{action}#

QueryTypeRequiredConstraints
chainIdstringYesPositive supported numeric chain ID
userWalletstringYesEVM address
tokenAddressstringYesEVM address
executorAddressstringConditionalRequired by general
amountstringNoNon-negative decimal token amount

For one executor, data is { executorAddress, executorName, allowance, allowanceOk } and also includes difference when amount is supplied. For multiple executors, data is { executors: [...] }. Allowance and difference are decimal strings. Success is 200.

Route errors: 400 invalid action/query or unavailable executor; 500 client/allowance failure.

POST /v1/wallet/evm/allowance/{action}#

action must be send, request, otc, or general; all and multiple are rejected.

BodyTypeRequiredConstraints
chainIdstringYesPositive supported numeric chain ID
userWalletstringYesEVM address
tokenAddressstringYesEVM address
amountnumber or stringYesPositive decimal amount, or "max"
executorAddressstringConditionalRequired by general

Success is 200. If backend signing is available, data is { txHash, signed: true }. Otherwise it is { to, data, value: "0", chainId, signed: false } for client signing.

Route errors: 400 invalid action/body/executor; 401 missing profile/team context; 403 API key lacks WRITE; 500 signing/broadcast failure.

DELETE /v1/wallet/evm/allowance/{action}#

No body. Query:

FieldTypeRequiredConstraints
chainIdstringYesPositive supported numeric chain ID
userWalletstringYesEVM address
tokenAddressstringYesNon-native EVM token address
executorAddressstringConditionalRequired by general

Success is 200. data is { transactions, signed }; each transaction corresponds to an executor. Signed results contain executorAddress, txHash and success; unsigned results contain to, encoded data, value, chainId, and executorAddress.

Route errors: 400 invalid action/query/executor; 401 missing profile/team context; 403 API key lacks WRITE.

POST /v1/wallet/evm/gas-sponsor#

Uses the current session profile/team and only accepts a wallet owned by that profile.

BodyTypeRequiredConstraints
walletAddressstringYesEVM address owned by current profile
actionenumYessend or otc
tokenAddressstringYesAccepted EVM token
chainSlugstringYesSupported chain slug or numeric chain ID encoded as a string
executeWithOwnGasbooleanNoDefaults to false

There is a five-minute cooldown per session user. Success is 200 and has one of three stable forms:

  • no sponsorship needed: { message, walletBalance, requiredGas, gasPrice, executeWithOwnGas: false, gasSponsored: false };
  • backend-signed approval: { transferTxHash, approveTxHash, gasEstimated, gasTransferred, gasPrice, gasSponsored, tokenAddress, chainSlug, action };
  • external-wallet flow: { transferTxHash, unsignedApproveTx, gasPrice, gasSponsored, tokenAddress, chainSlug, action, message }.

Route errors: 400 invalid body, wallet/token/chain/action, sponsorship disabled, or sponsorship limit exceeded; 401 missing session profile/team; 403 API key lacks WRITE; 409 existing/sufficient allowance or another unfulfilled sponsorship; 429 cooldown active; 500 chain, pricing, signing, transfer, or transaction preparation failure.