Skip to main content

Wallet Provisioning

Create and manage wallets for your users via the Partner API. Each wallet gets an EVM address (and optionally a Solana address) with access to Bankr APIs based on your organization's capabilities.

All endpoints in this section authenticate with the X-Partner-Key header. See API Keys for setup.


Create a Wallet

POST /partner/wallets
curl -X POST https://api.bankr.bot/partner/wallets \
-H "Content-Type: application/json" \
-H "X-Partner-Key: bk_ptr_YOUR_KEY" \
-d '{
"idempotencyKey": "user-abc-123",
"wallet": {
"solana": true
},
"apiKey": {
"permissions": {
"agentApiEnabled": true,
"llmGatewayEnabled": false,
"tokenLaunchApiEnabled": false,
"readOnly": false
},
"allowedIps": ["203.0.113.10"],
"allowedRecipients": {
"evm": ["0x5f8DA8F88eC81e27f2E22fCB9CA5D926c595E508"]
}
}
}'

Request Body

FieldTypeRequiredDescription
idempotencyKeystringNoMax 128 chars. Same key returns the same wallet on retry
wallet.solanabooleanNoCreate a Solana address alongside EVM. Requires enableSolana on your org
apiKeyobjectNoAuto-generate a wallet API key at creation. See below

apiKey Fields

FieldTypeDescription
apiKey.permissions.agentApiEnabledbooleanEnable Agent API access. Requires org agentApi capability
apiKey.permissions.llmGatewayEnabledbooleanEnable LLM Gateway access. Requires org llmGatewayApi capability
apiKey.permissions.tokenLaunchApiEnabledbooleanEnable Token Launch access. Requires org tokenLaunchApi capability
apiKey.permissions.readOnlybooleanRestrict to read-only operations (balances, prices — no transactions). Defaults to true — set to false to enable writes
apiKey.allowedIpsstring[]Restrict this wallet's API key to specific IPs or CIDR ranges (e.g., 10.0.0.0/24). CIDR minimum prefix: /8 for IPv4, /16 for IPv6
apiKey.allowedRecipients.evmstring[]Allowlist of EVM addresses this wallet can send to. Stored lowercased
apiKey.allowedRecipients.solanastring[]Allowlist of Solana addresses this wallet can send to

Response 201

{
"id": "wlt_A1b2C3d4E5f6G7h8",
"evmAddress": "0x1234567890abcdef1234567890abcdef12345678",
"solAddress": "ABC123...xyz",
"idempotencyKey": "user-abc-123",
"apiKey": "bk_usr_aBcD1234_secretKeyValue1234567890abcdef"
}
FieldTypeDescription
idstringPublic wallet ID (wlt_ prefix) — use this to look up or manage the wallet
evmAddressstringEVM address on Base/Ethereum/Polygon
solAddressstringSolana address. Only present if wallet.solana: true
idempotencyKeystringEchoed back when supplied on the request. Use this to map the wallet to your internal record (e.g. user ID)
apiKeystringWallet-level API key (bk_usr_ prefix). Only present if apiKey was requested. This key can be used as X-API-Key for Agent API, Wallet API, and LLM Gateway calls
Idempotency

Always pass an idempotencyKey tied to your internal user ID. If the request is retried, the same wallet is returned (status 200) instead of creating a duplicate, and the key is echoed back on every wallet response (POST, GET list, GET detail). The key is scoped to your organization.

The 200 retry response only contains id, evmAddress, solAddress, and idempotencyKey — it does not re-issue apiKey or re-fund. If either was missed on the first call, use POST /partner/wallets/:identifier/api-keys or POST /partner/wallets/:identifier/fund separately.

Errors

StatusErrorCause
400Validation errorInvalid body — check details array for specifics
403Wallet provisioning is not enabled for this organizationOrg has no walletProvisioning config
403Wallet API capability is not enabled for this organizationwalletApi not enabled
403Solana wallet provisioning is not enabled for this organizationwallet.solana: true but enableSolana is false
403<capability> API capability is not enabled for this organizationRequested permission exceeds org capabilities
403Wallet provisioning quota exceededHit maxWallets limit

List Wallets

GET /partner/wallets
curl "https://api.bankr.bot/partner/wallets?limit=20&skip=0" \
-H "X-Partner-Key: bk_ptr_YOUR_KEY"

Query Parameters

ParamTypeDefaultMaxDescription
limitnumber20100Wallets per page
skipnumber0Offset for pagination

Response 200

{
"wallets": [
{
"id": "wlt_A1b2C3d4E5f6G7h8",
"evmAddress": "0x1234...5678",
"solAddress": "ABC...xyz",
"status": "active",
"createdAt": "2025-01-15T10:30:00.000Z",
"idempotencyKey": "user-abc-123"
}
],
"total": 42
}

Each wallet's idempotencyKey is the value supplied on the original POST /partner/wallets call (or null if none was provided). Use it to reconcile listed wallets with your internal records.

total is the lifetime count of wallets ever provisioned by your organization (including suspended and closed). Use it for quota tracking against maxWallets — not for paginating active wallets.


Get Wallet Details

GET /partner/wallets/:identifier

Look up a wallet by its public ID, EVM address, or Solana address:

# By public ID
curl https://api.bankr.bot/partner/wallets/wlt_A1b2C3d4E5f6G7h8 \
-H "X-Partner-Key: bk_ptr_YOUR_KEY"

# By EVM address
curl https://api.bankr.bot/partner/wallets/0x1234567890abcdef1234567890abcdef12345678 \
-H "X-Partner-Key: bk_ptr_YOUR_KEY"

# By Solana address
curl https://api.bankr.bot/partner/wallets/ABC123xyz \
-H "X-Partner-Key: bk_ptr_YOUR_KEY"

Identifier Resolution

FormatLookup
Starts with wlt_Public wallet ID
Starts with 0xEVM address
OtherwiseSolana address

The wallet must belong to your organization. Wallets provisioned by other partners return 404.

Response 200

{
"id": "wlt_A1b2C3d4E5f6G7h8",
"evmAddress": "0x1234...5678",
"solAddress": "ABC...xyz",
"status": "active",
"createdAt": "2025-01-15T10:30:00.000Z",
"idempotencyKey": "user-abc-123",
"apiKey": {
"id": "65f1a2b3c4d5e6f7a8b9c0d1",
"keyId": "aBcD1234",
"name": "",
"isActive": true,
"createdAt": "2025-01-15T10:30:00.000Z",
"lastUsedAt": "2025-02-01T08:12:34.000Z",
"usageCount": 1287,
"externalOrdersEnabled": false,
"walletApiEnabled": true,
"agentApiEnabled": true,
"tokenLaunchApiEnabled": false,
"llmGatewayEnabled": false,
"readOnly": false,
"allowedIps": ["203.0.113.10"],
"allowedRecipients": {
"evm": ["0x5f8D...E508"],
"solana": []
}
}
}

idempotencyKey is the value supplied on the original POST /partner/wallets call (or null if none was provided). The apiKey field is present only if the wallet has an active API key, and uses the same shape returned by Get API Key DetailkeyId is load-bearing for rotate/revoke calls, and lastUsedAt is null until the key authenticates at least once. The secret is never echoed back.


Generate a Wallet API Key

POST /partner/wallets/:identifier/api-keys

Appends a new API key to the wallet. Existing active keys are not deactivated — a wallet may have up to 20 active keys. Use Rotate for atomic replacement, or Revoke One to remove a specific key.

curl -X POST https://api.bankr.bot/partner/wallets/wlt_A1b2C3d4E5f6G7h8/api-keys \
-H "Content-Type: application/json" \
-H "X-Partner-Key: bk_ptr_YOUR_KEY" \
-d '{
"name": "production worker",
"permissions": {
"agentApiEnabled": true
},
"allowedIps": [],
"allowedRecipients": {
"evm": ["0x5f8DA8F88eC81e27f2E22fCB9CA5D926c595E508"]
}
}'

Request Body

Same schema as the apiKey field in Create a Wallet. All fields are optional. name is a 1–64 character human-readable label.

Response 201

{
"apiKey": "bk_usr_aBcD1234_secretKeyValue1234567890abcdef"
}
warning

The new secret is shown only once. Store it securely.

Errors

StatusErrorCause
400Maximum of 20 active API keys per wallet…Wallet already has 20 active keys; revoke one first
403Wallet is permanently closedCannot create keys for a closed wallet
403Wallet is suspendedCannot create keys for a suspended wallet
403<capability> API capability is not enabledRequested permission exceeds org capabilities
404Wallet not foundIdentifier not found or wallet belongs to another partner

List Wallet API Keys

GET /partner/wallets/:identifier/api-keys

Returns every API key ever created on the wallet — active and revoked — newest first. The list is capped at 100 entries; older revoked keys are not returned.

curl https://api.bankr.bot/partner/wallets/wlt_A1b2C3d4E5f6G7h8/api-keys \
-H "X-Partner-Key: bk_ptr_YOUR_KEY"

Response 200

{
"apiKeys": [
{
"id": "65f1a2b3c4d5e6f7a8b9c0d1",
"keyId": "aBcD1234",
"name": "production worker",
"isActive": true,
"createdAt": "2025-01-15T10:30:00.000Z",
"lastUsedAt": "2025-02-01T08:12:34.000Z",
"usageCount": 1287,
"externalOrdersEnabled": false,
"walletApiEnabled": true,
"agentApiEnabled": true,
"tokenLaunchApiEnabled": false,
"llmGatewayEnabled": false,
"readOnly": false,
"allowedIps": ["203.0.113.10"],
"allowedRecipients": {
"evm": ["0x5f8d...e508"],
"solana": []
}
}
]
}

keyId is the short identifier used to rotate, update, or revoke a specific key. id is the internal document ID — prefer keyId for all subsequent calls. Secrets are never returned by this endpoint; the secret is only shown once at creation.

Errors

StatusErrorCause
404Wallet not foundIdentifier not found or wallet belongs to another partner

Get API Key Detail

GET /partner/wallets/:identifier/api-keys/:keyId

Look up a single API key by its keyId. Useful for verifying current permissions and IP/recipient allowlists without listing every key.

curl https://api.bankr.bot/partner/wallets/wlt_A1b2C3d4E5f6G7h8/api-keys/aBcD1234 \
-H "X-Partner-Key: bk_ptr_YOUR_KEY"

Response 200

{
"apiKey": {
"id": "65f1a2b3c4d5e6f7a8b9c0d1",
"keyId": "aBcD1234",
"name": "production worker",
"isActive": true,
"createdAt": "2025-01-15T10:30:00.000Z",
"lastUsedAt": "2025-02-01T08:12:34.000Z",
"usageCount": 1287,
"externalOrdersEnabled": false,
"walletApiEnabled": true,
"agentApiEnabled": true,
"tokenLaunchApiEnabled": false,
"llmGatewayEnabled": false,
"readOnly": false,
"allowedIps": ["203.0.113.10"],
"allowedRecipients": {
"evm": ["0x5f8d...e508"],
"solana": []
}
}
}

Returns the same canonical shape used by List Wallet API Keys and the apiKey field on Get Wallet Details.

Errors

StatusErrorCause
404API key not found or inactiveNo active key with that keyId on this wallet
404Wallet not foundIdentifier not found or wallet belongs to another partner

Update a Wallet API Key

PATCH /partner/wallets/:identifier/api-keys/:keyId

Update a key's name, IP allowlist, recipient allowlist, or permission flags without rotating the secret. At least one field must be supplied — calling PATCH with an empty body returns 400.

curl -X PATCH https://api.bankr.bot/partner/wallets/wlt_A1b2C3d4E5f6G7h8/api-keys/aBcD1234 \
-H "Content-Type: application/json" \
-H "X-Partner-Key: bk_ptr_YOUR_KEY" \
-d '{
"name": "production worker (us-east)",
"allowedIps": ["203.0.113.10", "10.0.0.0/24"],
"permissions": {
"readOnly": false
}
}'

Request Body

FieldTypeDescription
namestringNew display name (1–64 chars)
allowedIpsstring[]Replaces the existing IP allowlist. Same CIDR rules as Create a Wallet
allowedRecipients.evmstring[]Replaces the EVM recipient allowlist (stored lowercased)
allowedRecipients.solanastring[]Replaces the Solana recipient allowlist
permissions.walletApiEnabledbooleanToggle Wallet API access
permissions.agentApiEnabledbooleanToggle Agent API access (subject to org agentApi capability)
permissions.llmGatewayEnabledbooleanToggle LLM Gateway access (subject to org llmGatewayApi capability)
permissions.tokenLaunchApiEnabledbooleanToggle Token Launch access (subject to org tokenLaunchApi capability)
permissions.readOnlybooleanToggle read-only restriction

Each top-level field is independently optional; omitted fields are left unchanged. Arrays are replaced wholesale — to keep an existing entry, include it in the new array.

Response 200

{
"apiKey": {
"id": "65f1a2b3c4d5e6f7a8b9c0d1",
"keyId": "aBcD1234",
"name": "production worker (us-east)",
"isActive": true,
"...": "<same shape as Get API Key Detail>"
}
}

Returns the full updated key in the canonical ApiKey shape.

Errors

StatusErrorCause
400Please change at least one setting before saving.All four fields were omitted or the permissions object is empty
400Validation errorInvalid CIDR, bad EVM/Solana address, or name outside 1–64 chars
403Wallet is permanently closed / suspendedWallet is not active
403<capability> API capability is not enabledRequested permission exceeds org capabilities
404API key not found or inactiveNo active key with that keyId on this wallet
404Wallet not foundIdentifier not found or wallet belongs to another partner

Rotate a Wallet API Key

POST /partner/wallets/:identifier/api-keys/:keyId/rotate

Atomically rotate a single key: a new key is created with the same name, permissions, IP allowlist, and recipient allowlist as the old one, then the old key is deactivated. The new secret is returned once.

curl -X POST https://api.bankr.bot/partner/wallets/wlt_A1b2C3d4E5f6G7h8/api-keys/aBcD1234/rotate \
-H "X-Partner-Key: bk_ptr_YOUR_KEY"

Response 201

{
"apiKey": "bk_usr_eFgH5678_newSecretValue1234567890abcdef"
}

For zero-downtime rotation with a migration window, use the manual flow instead: POST /api-keys to create a new key, migrate consumers, then DELETE /api-keys/:keyId to revoke the old one.

Errors

StatusErrorCause
403Wallet is permanently closed / suspendedWallet is not active
404API key not found or inactiveNo active key with that keyId on this wallet
404Wallet not foundIdentifier not found or wallet belongs to another partner

Revoke One Wallet API Key

DELETE /partner/wallets/:identifier/api-keys/:keyId

Deactivates a single API key by keyId. Other active keys on the same wallet are untouched.

curl -X DELETE https://api.bankr.bot/partner/wallets/wlt_A1b2C3d4E5f6G7h8/api-keys/aBcD1234 \
-H "X-Partner-Key: bk_ptr_YOUR_KEY"

Response 200

{
"success": true
}

To revoke every active key on the wallet at once, omit the keyId:

curl -X DELETE https://api.bankr.bot/partner/wallets/wlt_A1b2C3d4E5f6G7h8/api-keys \
-H "X-Partner-Key: bk_ptr_YOUR_KEY"

Fund a Wallet

POST /partner/wallets/:identifier/fund

Transfer native ETH and/or ERC20 tokens from the org wallet to a provisioned wallet. Supports up to 3 tokens per request. ERC20 tokens are batched into a single on-chain transaction via the Transfer Helper contract.

info

Requires an org wallet to be configured for your partner organization. The org wallet must have sufficient balance for all requested tokens.

Gas Sponsorship

Funding transactions are automatically gas-sponsored when your organization has gas sponsorship enabled with sufficient credit balance. If the sponsor balance is exhausted, the transaction falls back to using ETH from the org wallet for gas.

Dashboard Funding

Partner admins can also fund provisioned wallets directly from the partner dashboard without needing the partner API key. Open any provisioned wallet's detail panel and click Add Funds to transfer tokens from the org wallet via the browser. This uses your Bankr account session for authentication instead of the X-Partner-Key header.

Request Body

FieldTypeRequiredDescription
tokensarrayYes1–3 token transfers
tokens[].tokenAddressstringYes"native" for ETH, or 0x-prefixed ERC20 address
tokens[].amountstringYesHuman-readable decimal amount (e.g. "0.01", "100")
chainstringNo"base" (default), "polygon", "mainnet", or "unichain"
curl -X POST https://api.bankr.bot/partner/wallets/0xABC.../fund \
-H "X-Partner-Key: bk_ptr_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"tokens": [
{ "tokenAddress": "native", "amount": "0.001" },
{ "tokenAddress": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", "amount": "10" }
],
"chain": "base"
}'

Response 200

{
"success": true,
"results": [
{
"tokenAddress": "native",
"amount": "0.001",
"success": true,
"txHash": "0x..."
},
{
"tokenAddress": "0x833...",
"amount": "10",
"success": true,
"txHash": "0x..."
}
]
}

Errors

StatusErrorCause
400Insufficient org wallet balanceOne or more tokens have insufficient balance (details in response)
400Invalid request bodyInvalid token address, amount, >3 tokens, or duplicates
403Wallet is suspended / closedTarget wallet is not active
404No org wallet configuredOrg does not have an org wallet set up
404Wallet not foundTarget wallet does not exist or is not owned by this organization

Funding during provisioning

You can also fund a wallet at creation time by adding a fund field to the POST /partner/wallets request:

curl -X POST https://api.bankr.bot/partner/wallets \
-H "X-Partner-Key: bk_ptr_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"fund": {
"tokens": [{ "tokenAddress": "native", "amount": "0.001" }],
"chain": "base"
}
}'

The wallet is always created regardless of funding outcome. The response includes a fund field with per-token results.


Suspend a Wallet

POST /partner/wallets/:identifier/suspend

Temporarily suspends a wallet. All API keys are deactivated — the wallet can no longer authenticate to Bankr APIs. The wallet's on-chain funds are unaffected.

curl -X POST https://api.bankr.bot/partner/wallets/wlt_A1b2C3d4E5f6G7h8/suspend \
-H "X-Partner-Key: bk_ptr_YOUR_KEY"

Response 200

{
"status": "suspended"
}

Idempotent — calling suspend on an already-suspended wallet returns 200.

Errors

StatusErrorCause
403Wallet is permanently closedCannot suspend a closed wallet
404Wallet not foundIdentifier not found or wallet belongs to another partner

Resume a Wallet

POST /partner/wallets/:identifier/resume

Resumes a suspended wallet. The wallet status returns to active, but API keys are NOT reactivated — you must generate a new key after resuming.

curl -X POST https://api.bankr.bot/partner/wallets/wlt_A1b2C3d4E5f6G7h8/resume \
-H "X-Partner-Key: bk_ptr_YOUR_KEY"

Response 200

{
"status": "active"
}

Idempotent — calling resume on an already-active wallet returns 200.

warning

Resume does not reactivate previously revoked API keys. This is intentional — if a key was compromised before the suspend, it should not be automatically restored. Always create a new key after resuming.

Errors

StatusErrorCause
403Wallet is permanently closedCannot resume a closed wallet
404Wallet not foundIdentifier not found or wallet belongs to another partner

Close a Wallet

POST /partner/wallets/:identifier/close

Permanently closes a wallet. All API keys are deactivated. This action cannot be undone — there is no reopen path.

curl -X POST https://api.bankr.bot/partner/wallets/wlt_A1b2C3d4E5f6G7h8/close \
-H "X-Partner-Key: bk_ptr_YOUR_KEY"

Response 200

{
"status": "closed",
"closedAt": "2026-04-09T12:00:00.000Z"
}

Idempotent — calling close on an already-closed wallet returns 200.

danger

Closing a wallet is permanent. Drain any remaining funds before closing. There is no fund recovery mechanism for closed wallets.

Errors

StatusErrorCause
404Wallet not foundIdentifier not found or wallet belongs to another partner

Wallet Status

Wallets have a status field returned in List Wallets and Get Wallet Details:

StatusDescriptionCan create API keys?Can use APIs?
activeNormal operationYesYes
suspendedTemporarily frozenNoNo
closedPermanently shut downNoNo

Quotas

Your organization has a maximum number of wallets it can provision (maxWallets). The current count (walletsCreated) is incremented atomically on each creation. When the limit is reached, creation requests return 403.

Check your quota from the partner dashboard:

{
"walletProvisioning": {
"maxWallets": 1000,
"walletsCreated": 42,
"enableSolana": true,
"allowedCapabilities": {
"walletApi": true,
"agentApi": true,
"llmGatewayApi": true,
"tokenLaunchApi": false
}
}
}

Contact the Bankr team to increase your quota.


What Provisioned Wallets Can Do

Once a wallet is provisioned with an API key, it authenticates to Bankr APIs using the X-API-Key header — the same way any Bankr user would. The difference is that access is scoped by your org's capabilities and the key's permissions.

APIHeaderDocsRequires
Wallet APIX-API-KeyWallet APIwalletApi capability (always on)
Agent APIX-API-KeyAuthenticationagentApi capability + agentApiEnabled permission
Token LaunchingX-API-KeyToken LaunchingtokenLaunchApi capability + tokenLaunchApiEnabled permission
LLM GatewayAuthorization: Bearer <apiKey>LLM Gateway APIllmGatewayApi capability + llmGatewayEnabled permission