Create wallet
Provisions a new wallet under exactly one provider account: the project's Managed config for provider, or the Custody Connection named by connectionId.
POST/Run in dashboard
A body naming both, or neither, is rejected with 400.
With an Idempotency-Key, SDP never records a second wallet for one key: a retry returns the wallet an earlier attempt recorded, even after the 24-hour key window. A provider that accepts a request id also receives one derived from the key.
On a provider that dedupes on the request id, a 5xx is not stored: a same-key retry runs again and gets back the wallet the first attempt made, even when SDP failed to record it, for as long as the provider keeps the request id (permanently, or for 24 hours; the Idempotency guide lists each provider). On any other provider a failure is stored as a 503, and a new key is a new provider request. A 503 can mean the provider created the wallet before the error. With a provider that accepts no request id, a failure that left no SDP wallet row makes even the same key a new provider request after 24 hours. Before any retry after an ambiguous failure, whatever the key, check GET /v1/wallets and, if the wallet is not there, the provider account.
The provider request id and the recorded-wallet lookup both include the credential. After an API key rotation, once the key's 24-hour record has expired, the same key under the new credential is a new provider request and can create a second wallet: list wallets with GET /v1/wallets and check the provider account before retrying a create.
Requires an API key with the wallets.manage action.
Headers
-
x-project-id·string· min length 1 · exampleprj_exampleRequired for dashboard sessions. API keys use their assigned project.
-
Idempotency-Key·stringUse a unique 1–255 printable ASCII key per operation. Reuse it with the same request on retries. An in-flight attempt returns
409; a changed request returns422. Retry and recovery rules.
Request body
application/json · required
Create wallet request body. Names exactly one owner: provider (Managed config) or connectionId (Custody Connection); a body naming both, or neither, is rejected with 400.
Any of:
-
Create a wallet under the project's Managed config for provider. · must not include
connectionId-
provider·string· required · one offireblocks,privy,coinbase_cdp,para,turnkey,dfns,ibm_haven,anchorage,utila· exampleprivyProvider whose Managed config owns the new wallet. A project holds one active config per provider.
-
label·string· max length 100 · exampleMint authority walletOptional label for the new wallet.
-
purpose·string· one oftransfer,fee_payer· defaulttransferWhat the wallet is for. Defaults to
transfer, the only purpose a payment, transfer batch or recurring payment can send from.
-
-
Create a wallet under a Custody Connection. · must not include
provider-
connectionId·string· required · min length 1 · examplecconn_123Custody Connection (BYOK) that owns the new wallet.
-
label·string· max length 100 · exampleMint authority walletOptional label for the new wallet.
-
purpose·string· one oftransfer,fee_payer· defaulttransferWhat the wallet is for. Defaults to
transfer, the only purpose a payment, transfer batch or recurring payment can send from.
-
Responses
-
201Wallet created-
data·object· requiredCreated wallet response payload.
-
wallet·object· requiredWallet details.
-
id·string· required · examplecwlt_exampleWallet record ID.
-
custodyConfigId·string· examplecfg_exampleOwning custody configuration ID.
-
custodyConnectionId·string· examplecconn_exampleOwning Custody Connection ID.
-
provider·string· exampleprivyWallet signing provider.
-
isRuntimeExecutionAllowed·boolean· required · exampletrueWhether SDP currently permits attempting runtime execution through this wallet's owner. This is request-time admission, not Provider health or a success guarantee.
-
walletId·string· required · min length 1 · exampleprivy_wallet_123Provider wallet ID.
-
publicKey·string· required · min length 32 · max length 44 · exampleSo11111111111111111111111111111111111111112Base58-encoded Solana address.
-
label·string | null· required · exampleTreasury walletOptional wallet label.
-
purpose·string | null· required · exampletransferOptional wallet purpose.
-
status·string· required · one ofactive,inactive· exampleactiveWallet status.
-
createdAt·string· required · formatdate-time· example2025-01-01T00:00:00.000ZISO 8601 timestamp.
-
balances·object[]Tracked token balances when requested and successfully observed. Omitted when the balance lookup is unavailable; an empty array is a successful zero-token result.
-
token·string· required · exampleUSDCTracked token symbol.
-
mint·string· required · min length 32 · max length 44 · example4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDUTracked token mint address.
-
amount·string· required · example1250000Raw token amount as a string.
-
uiAmount·string· required · example1.25Human-readable token balance.
-
decimals·integer· required · min 0 · example6Token decimals.
-
usdPrice·number· example1Resolved USD price per token when available.
-
usdValue·number· example125.5Resolved USD value of this balance when pricing is available.
-
One of:
-
Owned by a Managed config. · must include
custodyConfigId· must not includecustodyConnectionId -
Owned by a Custody Connection. · must include
custodyConnectionId· must not includecustodyConfigId
-
-
-
meta·object· requiredResponse metadata.
-
requestId·string· required · min length 1 · examplereq_exampleRequest identifier for tracing.
-
timestamp·string· required · formatdate-time· example2025-01-01T00:00:00.000ZISO 8601 timestamp.
-
-
-
400Bad Request-
error·object· requiredStandard error payload.
-
code·string· requiredMachine-readable error code.
-
message·string· requiredHuman-readable error message.
-
details·objectOptional error details for debugging.
*·any
-
-
meta·object-
requestId·string· min length 1 · examplereq_exampleRequest identifier for tracing.
-
-
-
401UnauthorizedSame fields as
400. -
403Forbidden. Requires thewallets.manageaction: an API key must hold it (a module'smanageorexecutealso covers itsread), and a signed-in member's organization role must include it. Without it the error is INSUFFICIENT_PERMISSIONS anderror.details.actionnames the action. Any other 403 names its own reason. Forbidden: the caller lacks the route's action or the API key is wallet-scoped, or the provider account was refused. A refusal's details.reason names the failed check: custody_mode_not_allowed when provider names a Managed config in a Production project (Production is BYOK only: create the wallet in a Custody Connection with connectionId), custody_provider_not_in_release_channel, or provider_not_entitled.Same fields as
400. -
404Not FoundSame fields as
400. -
409ConflictSame fields as
400. -
422Unprocessable EntitySame fields as
400. -
500Internal Server ErrorSame fields as
400. -
503Service UnavailableSame fields as
400.