Use the Ripple Custody (Wallet) Wallets endpoints to create HSM and MPC wallets inside a vault, retrieve and filter them, update their details, settings, and tags, read a wallet's sequence number, and read fiat-denominated balances for your organization, a vault, or a wallet. To manage wallets in the console instead, see Manage wallets via the console.
| Action | Console role | Console procedure | API procedure |
|---|---|---|---|
| Create a wallet | Owner, Administrator, Proposer | Create a wallet | Create a wallet |
| View wallet details | All roles | General settings | Get a wallet |
| List wallets | All roles | List wallets | List wallets |
| Update wallet details | Owner, Administrator, Proposer | Details settings | Update a wallet |
| Enable outgoing transactions | Owner, Administrator, Proposer | Enable outgoing transactions from a wallet | Update wallet settings |
| Turn on raw signing | Owner, Administrator, Proposer | Raw signing | Update wallet settings |
| Freeze deposits by default | Owner, Administrator, Proposer | Freeze transactions by default | Update wallet settings |
| Enable sweeping | Owner, Administrator, Proposer | Sweeping settings | Update wallet settings |
| Get a wallet's sequence | - | - | Get a wallet's sequence |
| Tag a wallet | Owner, Administrator, Proposer | Tag a wallet | Tag a wallet |
| Check organization balances | All roles | List vaults | Get organization balances |
| Check vault balances | All roles | Viewing balances | Get vault balances |
| Check wallet balances | All roles | Viewing balances | Get wallet balances |
| Refresh wallet balances | Owner, Administrator, Proposer | Refreshing balances | Refresh wallet balances |
| Delete a failed wallet | Owner, Administrator | Delete a wallet | Delete a wallet |
Permissions: In the console, owners, administrators, and proposers can create wallets and update wallet settings, and every role can view wallets. See User roles and permissions. The API procedures need an API credential of type WALLETS. See Prerequisites.
- An API credential of type
WALLETS. Its grantable permissions cover vaults, wallets, balances, and tags. Create credentials in the console. See Manage API credentials and Credential types. - An access token. Exchange your credential's
clientIdandclientSecretfor a bearer token. See Getting started with the API. - A vault. Wallets live inside a vault. See Create a vault via the API.
- For MPC wallets, a confirmed MPC quorum. You pass its ID as
quorumId. You create quorums in the console. See MPC quorums. - For balance requests, at least one provisioned wallet. See Create a wallet.
For the base URLs, token lifetime, pagination, filtering, and error format that every endpoint shares, see API conventions.
API reference: Create a wallet
Send a POST request to /v2/vaults/{vaultId}/wallets. The request requires name, keystore, and blockchain.
| Field | Description |
|---|---|
name | Required. The wallet name. |
keystore | Required. MPC or HSM. HSM wallets are available in sandbox only. |
blockchain | Required. The network, for example ETHEREUM, XRP_LEDGER, or SOLANA. For the chains you can create wallets on, see Blockchains and tokens. |
quorumId | The ID of a confirmed MPC quorum. Required for MPC wallets; not used for HSM wallets. |
description | A description of the wallet's purpose. |
keyAlgorithm | SECP256K1 or ED25519. |
externalId | An identifier from your own systems. It must be unique within your organization. If it's already in use, the API returns the existing wallet with HTTP 200 instead of creating a new one. |
correlationId | An identifier you can use to correlate this request with related actions. |
recoveryPublicKey | Optional. A hex-encoded, PKCS #1-formatted public key of a 4096-bit RSA key pair. |
walletType | WALLET_TYPE_BLOCKCHAIN, the only value. You can omit it. Responses return walletType as WALLET_TYPE_UNSPECIFIED. |
curl -X POST https://api.sandbox.palisade.co/v2/vaults/$VAULT_ID/wallets \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "USD Issuing wallet",
"description": "Main USD issuing account used internally",
"keystore": "MPC",
"blockchain": "XRP_LEDGER",
"quorumId": "4f1c2b7e-8d3a-4e6b-9c51-0a2f7d9e3b18"
}'{
"id": "1fc5cd6b-cf4b-4d33-88ce-b6a45e6ba342",
"vaultId": "ce4918bf-a199-4ce2-85a3-d0d296855384",
"organizationId": "7c2d9e41-5b8a-4f3c-9d6e-2a1b0c8f4e73",
"quorumId": "4f1c2b7e-8d3a-4e6b-9c51-0a2f7d9e3b18",
"createdBy": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
"createdAt": "2026-07-23T10:22:22.420Z",
"updatedAt": "2026-07-23T10:22:22.420Z",
"name": "USD Issuing wallet",
"description": "Main USD issuing account used internally",
"address": "",
"publicKey": "",
"keystore": "MPC",
"blockchain": "XRP_LEDGER",
"settings": {
"enabled": false,
"rawSigningEnabled": false,
"sweepingEnabled": false,
"defaultFreezeEnabled": false
},
"status": "CREATED",
"reasons": [],
"keyAlgorithm": "SECP256K1",
"walletType": "WALLET_TYPE_UNSPECIFIED"
}For an MPC wallet, pass the ID of a quorum in the Confirmed state as quorumId. If you omit quorumId, the request fails with HTTP 400 and reason PAL009.108. Get the ID from the console's Controls section, where the quorum's status must be Confirmed. When you create the wallet, every device in the quorum must approve key generation within 5 minutes. If a device rejects it, Ripple Custody (Wallet) doesn't create the wallet. HSM wallets don't need a quorum, and they return quorumId as 00000000-0000-0000-0000-000000000000.
Provisioning is asynchronous. Poll the wallet until status is PROVISIONED. Until then, address and publicKey are empty strings. If status is PROVISIONING_FAILED, check the reasons array.
A new wallet has settings.enabled set to false, so it can receive funds but can't send them. Before a wallet can send, it needs a transaction policy, an address book entry for the destination, and outgoing transactions enabled. See Enable outgoing transactions from a wallet.
API reference: Get a wallet, Get a wallet by ID
Send a GET request to /v2/vaults/{vaultId}/wallets/{walletId}, or to /v2/wallets/{id} when you know only the wallet ID. Both return the wallet object.
curl https://api.sandbox.palisade.co/v2/vaults/$VAULT_ID/wallets/$WALLET_ID \
-H "Authorization: Bearer $ACCESS_TOKEN"API reference: List vault wallets, List vault wallets with a request body, List organization wallets, List organization wallets with a request body
Send a GET request to /v2/vaults/{vaultId}/wallets to list the wallets in a vault, or to /v2/wallets to list every wallet in your organization. Both accept these query parameters:
search: a case-insensitive match over wallet ID, name, address, alias, external ID, and correlation ID.- Field filters on
id,vaultId,name,address,alias,externalId, andcorrelationId, using the operatorseq,notEq,contains,startsWith,endsWith,in,notIn, andisNull. For example,filter.name.contains=issuing. filter.blockchain.eq,.notEq,.in, and.notIn, which take blockchain values such asXRP_LEDGER.filter.status, which takes a single wallet status such asPROVISIONED. It has no operators:filter.status.eqreturns HTTP400.- Timestamp filters on
createdAtandupdatedAt, such asfilter.createdAt.after. pagination.pageSize(default 50, maximum 1,000) andpagination.pageToken.pagination.orderBy(name,address,blockchain,status,created_at, orupdated_at) andpagination.order(SORT_ORDER_ASCorSORT_ORDER_DESC).
The filters you set are combined with AND.
curl "https://api.sandbox.palisade.co/v2/wallets?filter.blockchain.eq=XRP_LEDGER&filter.status=PROVISIONED" \
-H "Authorization: Bearer $ACCESS_TOKEN"{
"filter": { "total": 1 },
"wallets": [
{
"id": "1fc5cd6b-cf4b-4d33-88ce-b6a45e6ba342",
"vaultId": "ce4918bf-a199-4ce2-85a3-d0d296855384",
"organizationId": "7c2d9e41-5b8a-4f3c-9d6e-2a1b0c8f4e73",
"quorumId": "4f1c2b7e-8d3a-4e6b-9c51-0a2f7d9e3b18",
"createdBy": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
"createdAt": "2026-07-23T10:22:22.420Z",
"updatedAt": "2026-07-23T10:24:05.112Z",
"name": "USD Issuing wallet",
"description": "Main USD issuing account used internally",
"address": "rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH",
"publicKey": "025eb9c81a436bd69f5d8b79b52b82c4b2cdf21bdd68200a967559930fec60b929",
"keystore": "MPC",
"blockchain": "XRP_LEDGER",
"settings": {
"enabled": false,
"rawSigningEnabled": false,
"sweepingEnabled": false,
"defaultFreezeEnabled": false
},
"status": "PROVISIONED",
"reasons": [],
"keyAlgorithm": "SECP256K1",
"walletType": "WALLET_TYPE_UNSPECIFIED"
}
]
}To fetch the next page, pass the filter.nextPageToken value as pagination.pageToken. Pages after the first also include filter.previousPageToken. For complex filters, send the same search, filter, and pagination options as a JSON body in a POST request to /v2/vaults/{vaultId}/wallets:list or /v2/wallets:list.
API reference: Update a wallet
Send a PUT request to /v2/vaults/{vaultId}/wallets/{walletId} to change the wallet's name and description. The request requires name, even if you're only changing the description. The update replaces both fields: if you omit description, the update clears the wallet's existing description, so send the current description when you change only the name. You can also pass an optional correlationId; if you omit it, the wallet keeps its existing correlationId.
curl -X PUT https://api.sandbox.palisade.co/v2/vaults/$VAULT_ID/wallets/$WALLET_ID \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "USD Issuing wallet",
"description": "Primary USD issuing account"
}'The response is the updated wallet object.
API reference: Update a wallet's settings
Send a PUT request to /v2/vaults/{vaultId}/wallets/{walletId}/settings. The request replaces all four settings: any setting you omit from the settings object is set to false. Send the full settings object, with the current values of the settings you aren't changing, even when you change only one value.
| Setting | Controls |
|---|---|
enabled | Whether the wallet can send outgoing transactions. |
rawSigningEnabled | Whether the wallet can sign raw transactions. |
sweepingEnabled | Whether the wallet is a source for asset sweeping. |
defaultFreezeEnabled | Whether inbound transactions are frozen by default. |
curl -X PUT https://api.sandbox.palisade.co/v2/vaults/$VAULT_ID/wallets/$WALLET_ID/settings \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"settings": {
"enabled": true,
"rawSigningEnabled": true,
"sweepingEnabled": false,
"defaultFreezeEnabled": false
}
}'The response is the updated wallet object.
API reference: Get a wallet nonce/sequence
Send a GET request to /v2/vaults/{vaultId}/wallets/{walletId}/sequence to read the wallet's current blockchain nonce or sequence number. This is useful when you build raw transactions. The value is a string, and it's "0" for an account that has no on-chain history. For a wallet that isn't provisioned, the request fails with HTTP 400 and reason PAL009.106.
curl https://api.sandbox.palisade.co/v2/vaults/$VAULT_ID/wallets/$WALLET_ID/sequence \
-H "Authorization: Bearer $ACCESS_TOKEN"{ "sequence": "2" }API reference: Delete a wallet
Send a DELETE request to /v2/vaults/{vaultId}/wallets/{walletId}. You can delete only a wallet whose status is PROVISIONING_FAILED; you can't delete a provisioned wallet. A successful response is an empty JSON object.
curl -X DELETE https://api.sandbox.palisade.co/v2/vaults/$VAULT_ID/wallets/$WALLET_ID \
-H "Authorization: Bearer $ACCESS_TOKEN"API reference: Add a wallet tag, List wallet tags, List wallet tags in a vault, List all wallet tags, Delete a wallet tag
Tags are free-form labels for grouping and finding wallets. Adding a wallet tag needs key:update, listing needs key:read, and deleting one needs key:delete. A WALLETS credential without key:delete can add and list tags but gets 403 (PAL000.002) when it deletes one.
Add a tag with a POST request to /v2/vaults/{vaultId}/wallets/{walletId}/tags; the request requires tag. List a wallet's tags with a GET request to the same path, and remove a tag with a DELETE request that passes it in the required tag query parameter. To see the tags of every wallet in a vault, send a GET request to /v2/vaults/{vaultId}/wallets/tags, or to /v2/tags for every wallet tag in your organization.
curl -X POST https://api.sandbox.palisade.co/v2/vaults/$VAULT_ID/wallets/$WALLET_ID/tags \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "tag": "Issuing wallet" }'The response lists the wallet's tags after the change:
[
{
"walletId": "1fc5cd6b-cf4b-4d33-88ce-b6a45e6ba342",
"vaultId": "ce4918bf-a199-4ce2-85a3-d0d296855384",
"tags": ["Issuing wallet"]
}
]A successful DELETE returns an empty JSON object.
Use the Balances endpoints to read fiat-denominated balances at three levels: your whole organization, a single vault, or a single wallet with a per-asset breakdown. To learn how Ripple Custody (Wallet) calculates and displays balances, see Understanding balances.
All three endpoints accept an optional currencyCode query parameter that sets the fiat currency for the values. If you omit it, Ripple Custody (Wallet) uses USD. Currently USD is the only supported value.
Balances and fiat values are decimal strings. Fiat values can carry many decimal places, for example "28.4000000000000000000000000000000000000000000000000000000000000000000000000002", so round them before you display them.
API reference: Get organization balances
Send a GET request to /v2/balances for the aggregated fiat value of your organization, broken down by vault. Vaults with no value can appear with an aggregatedFiatValue of "0".
curl "https://api.sandbox.palisade.co/v2/balances?currencyCode=USD" \
-H "Authorization: Bearer $ACCESS_TOKEN"{
"currencyCode": "USD",
"aggregatedFiatValue": "100.00",
"balances": [
{
"vaultId": "ce4918bf-a199-4ce2-85a3-d0d296855384",
"aggregatedFiatValue": "100.00"
}
]
}API reference: Get vault balances
Send a GET request to /v2/vaults/{vaultId}/balances for the aggregated fiat value of one vault, broken down by wallet.
curl https://api.sandbox.palisade.co/v2/vaults/$VAULT_ID/balances \
-H "Authorization: Bearer $ACCESS_TOKEN"{
"currencyCode": "USD",
"aggregatedFiatValue": "100.00",
"balances": [
{
"walletId": "1fc5cd6b-cf4b-4d33-88ce-b6a45e6ba342",
"aggregatedFiatValue": "100.00"
}
]
}API reference: Get wallet balances
Send a GET request to /v2/vaults/{vaultId}/wallets/{walletId}/balances for a per-asset breakdown. Each entry shows:
balance: the total on-chain balance. When the breakdown fields are present, it equalsavailableBalance+pendingBalance+frozenBalance.availableBalance: the balance you can spend.pendingBalance: the balance tied up in pending transactions.frozenBalance: the balance frozen by policy actions.rate: the exchange rate between the asset andcurrencyCode.fiatValue: the asset's value incurrencyCode.
curl https://api.sandbox.palisade.co/v2/vaults/$VAULT_ID/wallets/$WALLET_ID/balances \
-H "Authorization: Bearer $ACCESS_TOKEN"{
"currencyCode": "USD",
"aggregatedFiatValue": "100.00",
"balances": [
{
"asset": {
"id": "3::XRP",
"standard": "NATIVE",
"symbol": "XRP",
"name": "XRP",
"blockchain": "XRP_LEDGER",
"decimals": 6,
"vetted": false,
"enabled": true,
"contract": "",
"createdAt": null,
"source": "ASSET_SOURCE_UNSPECIFIED",
"syncVersion": 0,
"iconUrl": "https://static.palisade.co/registry/assets/coingecko/ripple.png",
"displaySymbol": "XRP"
},
"balance": "200",
"rate": "0.5",
"fiatValue": "100",
"availableBalance": "150",
"pendingBalance": "30",
"frozenBalance": "20"
}
],
"pagination": null
}Use asset.displaySymbol when you show the symbol to users. It keeps the capitalization the asset's source uses, for example weETH.
The wallet balances endpoint also accepts these optional query parameters:
filter.blockchain,filter.standard, andfilter.source, each with the operatorseq,notEq,in, andnotIn. Standards areNATIVE,ERC20,ISSUED_CURRENCY,ERC721,SPL, andCUSTOM. Sources areASSET_SOURCE_LEGACY,ASSET_SOURCE_AUTO,ASSET_SOURCE_COINGECKO,ASSET_SOURCE_PALISADE, andASSET_SOURCE_CUSTOMER; for example,filter.source.eq=ASSET_SOURCE_CUSTOMERreturns only your organization's custom asset entries. The filter matches each asset's resolved source, so a balance can matchfilter.sourceeven when an unfiltered response shows itsasset.sourceasASSET_SOURCE_UNSPECIFIED.ASSET_SOURCE_UNSPECIFIEDisn't a valid filter value.filter.contractandfilter.symbol, with the operatorseq,notEq,in,notIn,contains,startsWith,endsWith, andisNull.eqis case-sensitive;contains,startsWith, andendsWitharen't. To return native assets only, setfilter.contract.isNull=trueorfilter.standard.in=NATIVE. Native assets matchfilter.contract.isNull=trueeven though the response showscontractas an empty string.search: a case-insensitive match over asset ID, symbol, name, contract address, blockchain value (such asXRP_LEDGER), source label (such ascoingecko), and standard label (such asnative).pagination.pageSize(default 50, maximum 1,000),pagination.pageToken,pagination.orderBy(symbol,name,blockchain,contract_address,source, orstandard), andpagination.order(SORT_ORDER_ASCorSORT_ORDER_DESC).refreshRegistryMetadata: whentrue, bypasses cached registry metadata for this wallet's assets. If registry resolution fails, the request fails. Use it only for a read immediately after you change the asset registry.
A balance must match every filter you set, and search if you set it. Setting any pagination parameter turns on paging, and the response then includes a pagination object with total and, when there are more pages, page tokens. Without paging, pagination is null. aggregatedFiatValue always covers every matching balance, not only the current page, and is "0" when nothing matches. For a full example, see Filter, search, and page balances.
curl "https://api.sandbox.palisade.co/v2/vaults/$VAULT_ID/wallets/$WALLET_ID/balances?filter.standard.eq=ERC20&pagination.pageSize=20&pagination.orderBy=symbol" \
-H "Authorization: Bearer $ACCESS_TOKEN"API reference: Sync wallet balances
Balances update automatically. To trigger a refresh, send a POST request to /v2/vaults/{vaultId}/wallets/{walletId}/balances/sync. The request takes no body, and a successful response is an empty JSON object.
curl -X POST https://api.sandbox.palisade.co/v2/vaults/$VAULT_ID/wallets/$WALLET_ID/balances/sync \
-H "Authorization: Bearer $ACCESS_TOKEN"A refresh syncs only assets that Ripple Custody (Wallet) already tracks for the wallet. It doesn't discover new tokens that the wallet received but Ripple Custody (Wallet) doesn't yet track.
Failed requests return an HTTP error status and an error object with code, message, and details fields. See Error codes. For the causes of and fixes for the errors these endpoints return, see Troubleshoot common errors.
- Understanding balances: balance types and how Ripple Custody (Wallet) calculates them.
- Ripple Custody (Wallet) API reference: the full request and response schemas.