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
| Field | Type | Required | Description |
|---|---|---|---|
idempotencyKey | string | No | Max 128 chars. Same key returns the same wallet on retry |
wallet.solana | boolean | No | Create a Solana address alongside EVM. Requires enableSolana on your org |
apiKey | object | No | Auto-generate a wallet API key at creation. See below |
apiKey Fields
| Field | Type | Description |
|---|---|---|
apiKey.permissions.agentApiEnabled | boolean | Enable Agent API access. Requires org agentApi capability |
apiKey.permissions.llmGatewayEnabled | boolean | Enable LLM Gateway access. Requires org llmGatewayApi capability |
apiKey.permissions.tokenLaunchApiEnabled | boolean | Enable Token Launch access. Requires org tokenLaunchApi capability |
apiKey.permissions.readOnly | boolean | Restrict to read-only operations (balances, prices — no transactions). Defaults to true — set to false to enable writes |
apiKey.allowedIps | string[] | Restrict this wallet's API key to specific IPs or CIDR ranges (e.g., 10.0.0.0/24) |
apiKey.allowedRecipients.evm | string[] | Allowlist of EVM addresses this wallet can send to |
apiKey.allowedRecipients.solana | string[] | Allowlist of Solana addresses this wallet can send to |
Response 201
{
"id": "wlt_A1b2C3d4E5f6G7h8",
"evmAddress": "0x1234567890abcdef1234567890abcdef12345678",
"solAddress": "ABC123...xyz",
"apiKey": "bk_usr_aBcD1234_secretKeyValue1234567890abcdef"
}
| Field | Type | Description |
|---|---|---|
id | string | Public wallet ID (wlt_ prefix) — use this to look up or manage the wallet |
evmAddress | string | EVM address on Base/Ethereum/Polygon |
solAddress | string | Solana address. Only present if wallet.solana: true |
apiKey | string | Wallet-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 |
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. The key is scoped to your organization.
Errors
| Status | Error | Cause |
|---|---|---|
400 | Validation error | Invalid body — check details array for specifics |
403 | Wallet provisioning is not enabled for this organization | Org has no walletProvisioning config |
403 | Wallet API capability is not enabled for this organization | walletApi not enabled |
403 | Solana wallet provisioning is not enabled for this organization | wallet.solana: true but enableSolana is false |
403 | <capability> API capability is not enabled for this organization | Requested permission exceeds org capabilities |
403 | Wallet provisioning quota exceeded | Hit 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
| Param | Type | Default | Max | Description |
|---|---|---|---|---|
limit | number | 20 | 100 | Wallets per page |
skip | number | 0 | — | Offset for pagination |
Response 200
{
"wallets": [
{
"id": "wlt_A1b2C3d4E5f6G7h8",
"evmAddress": "0x1234...5678",
"solAddress": "ABC...xyz",
"status": "active",
"createdAt": "2025-01-15T10:30:00.000Z"
}
],
"total": 42
}
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
| Format | Lookup |
|---|---|
Starts with wlt_ | Public wallet ID |
Starts with 0x | EVM address |
| Otherwise | Solana 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",
"apiKey": {
"isActive": true,
"walletApiEnabled": true,
"agentApiEnabled": true,
"llmGatewayEnabled": false,
"tokenLaunchApiEnabled": false,
"readOnly": false,
"allowedIps": ["203.0.113.10"],
"allowedRecipients": {
"evm": ["0x5f8D...E508"],
"solana": []
},
"createdAt": "2025-01-15T10:30:00.000Z"
}
}
The apiKey field is present only if the wallet has an active API key. It never contains the secret — only metadata and permissions.
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"
}
The new secret is shown only once. Store it securely.
Errors
| Status | Error | Cause |
|---|---|---|
400 | Maximum of 20 active API keys per wallet… | Wallet already has 20 active keys; revoke one first |
403 | Wallet is permanently closed | Cannot create keys for a closed wallet |
403 | Wallet is suspended | Cannot create keys for a suspended wallet |
403 | <capability> API capability is not enabled | Requested permission exceeds org capabilities |
404 | Wallet not found | Identifier 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
| Status | Error | Cause |
|---|---|---|
403 | Wallet is permanently closed / suspended | Wallet is not active |
404 | API key not found or inactive | No active key with that keyId on this wallet |
404 | Wallet not found | Identifier 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.
Requires an org wallet to be configured for your partner organization. The org wallet must have sufficient balance for all requested tokens.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
tokens | array | Yes | 1–3 token transfers |
tokens[].tokenAddress | string | Yes | "native" for ETH, or 0x-prefixed ERC20 address |
tokens[].amount | string | Yes | Human-readable decimal amount (e.g. "0.01", "100") |
chain | string | No | "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
| Status | Error | Cause |
|---|---|---|
400 | Insufficient org wallet balance | One or more tokens have insufficient balance (details in response) |
400 | Invalid request body | Invalid token address, amount, >3 tokens, or duplicates |
403 | Wallet is suspended / closed | Target wallet is not active |
404 | No org wallet configured | Org does not have an org wallet set up |
404 | Wallet not found | Target 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
| Status | Error | Cause |
|---|---|---|
403 | Wallet is permanently closed | Cannot suspend a closed wallet |
404 | Wallet not found | Identifier 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.
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
| Status | Error | Cause |
|---|---|---|
403 | Wallet is permanently closed | Cannot resume a closed wallet |
404 | Wallet not found | Identifier 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.
Closing a wallet is permanent. Drain any remaining funds before closing. There is no fund recovery mechanism for closed wallets.
Errors
| Status | Error | Cause |
|---|---|---|
404 | Wallet not found | Identifier not found or wallet belongs to another partner |
Wallet Status
Wallets have a status field returned in List Wallets and Get Wallet Details:
| Status | Description | Can create API keys? | Can use APIs? |
|---|---|---|---|
active | Normal operation | Yes | Yes |
suspended | Temporarily frozen | No | No |
closed | Permanently shut down | No | No |
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.
| API | Header | Docs | Requires |
|---|---|---|---|
| Wallet API | X-API-Key | Wallet API | walletApi capability (always on) |
| Agent API | X-API-Key | Authentication | agentApi capability + agentApiEnabled permission |
| Token Launching | X-API-Key | Token Launching | tokenLaunchApi capability + tokenLaunchApiEnabled permission |
| LLM Gateway | Authorization: Bearer <apiKey> | LLM Gateway API | llmGatewayApi capability + llmGatewayEnabled permission |