Wallet
The Wallet endpoints allow you to create and manage encrypted wallets for secure credential storage with Ed25519 keypair management.
Create a Wallet
Section titled “Create a Wallet”Creates a new encrypted wallet with an Ed25519 keypair and DID.
POST /v1/walletsAuthentication
Section titled “Authentication”Requires BearerAuth or ApiKeyAuth.
Request Body
Section titled “Request Body”| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Name for the wallet |
password | string | Yes | Password for encrypting the wallet |
description | string | No | Optional description |
Request Example
Section titled “Request Example”curl -X POST "https://api.veriglob.com/v1/wallets" \ -H "Authorization: Bearer your-api-key" \ -H "Content-Type: application/json" \ -d '{ "name": "My Identity Wallet", "password": "secure-wallet-password", "description": "Personal credentials wallet" }'interface CreateWalletRequest { name: string; password: string; description?: string;}
interface CreateWalletResponse {status: string;message: string;data: {wallet_id: string;name: string;did: string;public_key: string;created_at: string;};}
async function createWallet(apiKey: string,name: string,password: string,description?: string): Promise<CreateWalletResponse> {const response = await fetch('https://api.veriglob.com/v1/wallets', {method: 'POST',headers: {'Authorization': `Bearer ${apiKey}`,'Content-Type': 'application/json'},body: JSON.stringify({ name, password, description })});
if (!response.ok) {throw new Error(`HTTP error! status: ${response.status}`);}
return response.json();}
// Usageconst wallet = await createWallet('your-api-key','My Identity Wallet','secure-wallet-password','Personal credentials wallet');console.log('Wallet ID:', wallet.data.wallet_id);console.log('DID:', wallet.data.did);package main
import ( "bytes" "encoding/json" "fmt" "net/http")
type CreateWalletRequest struct { Name string `json:"name"` Password string `json:"password"` Description string `json:"description,omitempty"`}
type CreateWalletResponse struct { Status string `json:"status"` Message string `json:"message"` Data struct { WalletID string `json:"wallet_id"` Name string `json:"name"` DID string `json:"did"` PublicKey string `json:"public_key"` CreatedAt string `json:"created_at"` } `json:"data"`}
func CreateWallet(apiKey, name, password, description string) (*CreateWalletResponse, error) { reqBody := CreateWalletRequest{ Name: name, Password: password, Description: description, } jsonData, _ := json.Marshal(reqBody)
req, err := http.NewRequest("POST", "https://api.veriglob.com/v1/wallets", bytes.NewBuffer(jsonData)) if err != nil { return nil, err }
req.Header.Set("Authorization", "Bearer "+apiKey) req.Header.Set("Content-Type", "application/json")
client := &http.Client{} resp, err := client.Do(req) if err != nil { return nil, err } defer resp.Body.Close()
var result CreateWalletResponse json.NewDecoder(resp.Body).Decode(&result) return &result, nil}
func main() { result, _ := CreateWallet("your-api-key", "My Identity Wallet", "secure-password", "Personal wallet") fmt.Printf("Wallet ID: %s\n", result.Data.WalletID) fmt.Printf("DID: %s\n", result.Data.DID)}import requestsfrom typing import Optional
def create_wallet(api_key: str,name: str,password: str,description: Optional[str] = None) -> dict:"""Create a new encrypted wallet."""payload = {'name': name,'password': password}if description:payload['description'] = description
response = requests.post( 'https://api.veriglob.com/v1/wallets', headers={ 'Authorization': f'Bearer {api_key}', 'Content-Type': 'application/json' }, json=payload ) response.raise_for_status() return response.json()
# Usage
result = create_wallet('your-api-key','My Identity Wallet','secure-wallet-password','Personal credentials wallet')print(f"Wallet ID: {result['data']['wallet_id']}")print(f"DID: {result['data']['did']}")Response
Section titled “Response”201 Created
{ "status": "success", "message": "Wallet created successfully", "data": { "wallet_id": "wallet_abc123def456", "name": "My Identity Wallet", "did": "did:key:z6MkhsiKBzbNixeXD7mzEzEiuRDFJEKpofi62adE1ZpauNeh", "public_key": "base64-encoded-public-key", "created_at": "2024-01-15T10:30:00Z" }}Error Responses
Section titled “Error Responses”| Status | Description |
|---|---|
| 400 | Invalid request body or missing required fields |
| 401 | Invalid or missing API key |
| 429 | Rate limit exceeded |
| 500 | Internal server error |
Open a Wallet
Section titled “Open a Wallet”Decrypts and opens an existing wallet, returning its contents.
POST /v1/wallets/openAuthentication
Section titled “Authentication”Requires BearerAuth or ApiKeyAuth.
Request Body
Section titled “Request Body”| Field | Type | Required | Description |
|---|---|---|---|
wallet_id | string | Yes | The wallet ID to open |
password | string | Yes | The wallet password |
Request Example
Section titled “Request Example”curl -X POST "https://api.veriglob.com/v1/wallets/open" \ -H "Authorization: Bearer your-api-key" \ -H "Content-Type: application/json" \ -d '{ "wallet_id": "wallet_abc123def456", "password": "secure-wallet-password" }'interface OpenWalletResponse { status: string; message: string; data: { wallet_id: string; name: string; did: string; public_key: string; private_key: string; credentials: Array<{ credential_id: string; credential: string; credential_type: string; issuer: string; stored_at: string; }>; created_at: string; };}
async function openWallet(apiKey: string,walletId: string,password: string): Promise<OpenWalletResponse> {const response = await fetch('https://api.veriglob.com/v1/wallets/open', {method: 'POST',headers: {'Authorization': `Bearer ${apiKey}`,'Content-Type': 'application/json'},body: JSON.stringify({ wallet_id: walletId, password })});
if (!response.ok) {throw new Error(`HTTP error! status: ${response.status}`);}
return response.json();}
// Usageconst wallet = await openWallet('your-api-key', 'wallet_abc123def456', 'secure-password');console.log('DID:', wallet.data.did);console.log('Credentials:', wallet.data.credentials.length);type OpenWalletRequest struct { WalletID string `json:"wallet_id"` Password string `json:"password"`}
type StoredCredential struct { CredentialID string `json:"credential_id"` Credential string `json:"credential"` CredentialType string `json:"credential_type"` Issuer string `json:"issuer"` StoredAt string `json:"stored_at"`}
type OpenWalletResponse struct { Status string `json:"status"` Message string `json:"message"` Data struct { WalletID string `json:"wallet_id"` Name string `json:"name"` DID string `json:"did"` PublicKey string `json:"public_key"` PrivateKey string `json:"private_key"` Credentials []StoredCredential `json:"credentials"` CreatedAt string `json:"created_at"` } `json:"data"`}
func OpenWallet(apiKey, walletId, password string) (*OpenWalletResponse, error) { reqBody := OpenWalletRequest{ WalletID: walletId, Password: password, } jsonData, _ := json.Marshal(reqBody)
req, _ := http.NewRequest("POST", "https://api.veriglob.com/v1/wallets/open", bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer "+apiKey) req.Header.Set("Content-Type", "application/json")
client := &http.Client{} resp, err := client.Do(req) if err != nil { return nil, err } defer resp.Body.Close()
var result OpenWalletResponse json.NewDecoder(resp.Body).Decode(&result) return &result, nil}def open_wallet(api_key: str, wallet_id: str, password: str) -> dict: """Open an encrypted wallet and return its contents.""" response = requests.post( 'https://api.veriglob.com/v1/wallets/open', headers={ 'Authorization': f'Bearer {api_key}', 'Content-Type': 'application/json' }, json={ 'wallet_id': wallet_id, 'password': password } ) response.raise_for_status() return response.json()
# Usage
wallet = open_wallet('your-api-key', 'wallet_abc123def456', 'secure-password')print(f"DID: {wallet['data']['did']}")print(f"Credentials: {len(wallet['data']['credentials'])}")Response
Section titled “Response”200 OK
{ "status": "success", "message": "Wallet opened successfully", "data": { "wallet_id": "wallet_abc123def456", "name": "My Identity Wallet", "did": "did:key:z6MkhsiKBzbNixeXD7mzEzEiuRDFJEKpofi62adE1ZpauNeh", "public_key": "base64-encoded-public-key", "private_key": "base64-encoded-private-key", "credentials": [ { "credential_id": "urn:uuid:3978344f-8596-4c3a-a978-8fcaba3903c5", "credential": "v4.public.eyJpc3MiOi...", "credential_type": "EmploymentCredential", "issuer": "did:key:z6MkissuerDID...", "stored_at": "2024-01-20T14:00:00Z" } ], "created_at": "2024-01-15T10:30:00Z" }}Error Responses
Section titled “Error Responses”| Status | Description |
|---|---|
| 400 | Invalid request body or missing fields |
| 401 | Invalid password or API key |
| 404 | Wallet not found |
| 429 | Rate limit exceeded |
Store a Credential
Section titled “Store a Credential”Stores a credential in an open wallet.
POST /v1/wallets/{wallet_id}/credentialsAuthentication
Section titled “Authentication”Requires BearerAuth or ApiKeyAuth.
Path Parameters
Section titled “Path Parameters”| Parameter | Type | Required | Description |
|---|---|---|---|
wallet_id | string | Yes | The wallet ID |
Request Body
Section titled “Request Body”| Field | Type | Required | Description |
|---|---|---|---|
password | string | Yes | The wallet password |
credential | string | Yes | The PASETO v4 credential token |
metadata | object | No | Optional metadata for the credential |
Request Example
Section titled “Request Example”curl -X POST "https://api.veriglob.com/v1/wallets/wallet_abc123def456/credentials" \ -H "Authorization: Bearer your-api-key" \ -H "Content-Type: application/json" \ -d '{ "password": "secure-wallet-password", "credential": "v4.public.eyJpc3MiOi...", "metadata": { "label": "Employment at Acme Corp", "tags": ["employment", "acme"] } }'interface StoreCredentialRequest { password: string; credential: string; metadata?: Record<string, any>;}
interface StoreCredentialResponse {status: string;message: string;data: {credential_id: string;wallet_id: string;credential_type: string;issuer: string;stored_at: string;};}
async function storeCredential(apiKey: string,walletId: string,password: string,credential: string,metadata?: Record<string, any>): Promise<StoreCredentialResponse> {const response = await fetch(`https://api.veriglob.com/v1/wallets/${walletId}/credentials`,{method: 'POST',headers: {'Authorization': `Bearer ${apiKey}`,'Content-Type': 'application/json'},body: JSON.stringify({ password, credential, metadata })});
if (!response.ok) {throw new Error(`HTTP error! status: ${response.status}`);}
return response.json();}
// Usageconst result = await storeCredential('your-api-key','wallet_abc123def456','secure-password','v4.public.eyJpc3MiOi...',{ label: 'Employment at Acme Corp', tags: ['employment'] });console.log('Stored credential ID:', result.data.credential_id);type StoreCredentialRequest struct { Password string `json:"password"` Credential string `json:"credential"` Metadata map[string]interface{} `json:"metadata,omitempty"`}
type StoreCredentialResponse struct { Status string `json:"status"` Message string `json:"message"` Data struct { CredentialID string `json:"credential_id"` WalletID string `json:"wallet_id"` CredentialType string `json:"credential_type"` Issuer string `json:"issuer"` StoredAt string `json:"stored_at"` } `json:"data"`}
func StoreCredential(apiKey, walletId, password, credential string, metadata map[string]interface{}) (*StoreCredentialResponse, error) { reqBody := StoreCredentialRequest{ Password: password, Credential: credential, Metadata: metadata, } jsonData, _ := json.Marshal(reqBody)
url := fmt.Sprintf("https://api.veriglob.com/v1/wallets/%s/credentials", walletId) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer "+apiKey) req.Header.Set("Content-Type", "application/json")
client := &http.Client{} resp, err := client.Do(req) if err != nil { return nil, err } defer resp.Body.Close()
var result StoreCredentialResponse json.NewDecoder(resp.Body).Decode(&result) return &result, nil}from typing import Optional, Dict, Any
def store_credential(api_key: str,wallet_id: str,password: str,credential: str,metadata: Optional[Dict[str, Any]] = None) -> dict:"""Store a credential in a wallet."""payload = {'password': password,'credential': credential}if metadata:payload['metadata'] = metadata
response = requests.post( f'https://api.veriglob.com/v1/wallets/{wallet_id}/credentials', headers={ 'Authorization': f'Bearer {api_key}', 'Content-Type': 'application/json' }, json=payload ) response.raise_for_status() return response.json()
# Usage
result = store_credential('your-api-key','wallet_abc123def456','secure-password','v4.public.eyJpc3MiOi...',{'label': 'Employment at Acme Corp', 'tags': ['employment']})print(f"Stored credential ID: {result['data']['credential_id']}")Response
Section titled “Response”201 Created
{ "status": "success", "message": "Credential stored successfully", "data": { "credential_id": "urn:uuid:3978344f-8596-4c3a-a978-8fcaba3903c5", "wallet_id": "wallet_abc123def456", "credential_type": "EmploymentCredential", "issuer": "did:key:z6MkissuerDID...", "stored_at": "2024-01-20T14:00:00Z" }}Error Responses
Section titled “Error Responses”| Status | Description |
|---|---|
| 400 | Invalid credential or missing fields |
| 401 | Invalid password or API key |
| 404 | Wallet not found |
| 429 | Rate limit exceeded |
List Wallet Credentials
Section titled “List Wallet Credentials”Lists all credentials stored in a wallet.
GET /v1/wallets/{wallet_id}/credentialsAuthentication
Section titled “Authentication”Requires BearerAuth or ApiKeyAuth.
Path Parameters
Section titled “Path Parameters”| Parameter | Type | Required | Description |
|---|---|---|---|
wallet_id | string | Yes | The wallet ID |
Query Parameters
Section titled “Query Parameters”| Parameter | Type | Required | Description |
|---|---|---|---|
password | string | Yes | The wallet password |
Request Example
Section titled “Request Example”curl -X GET "https://api.veriglob.com/v1/wallets/wallet_abc123def456/credentials?password=secure-wallet-password" \ -H "Authorization: Bearer your-api-key"interface ListCredentialsResponse { status: string; message: string; data: { credentials: Array<{ credential_id: string; credential_type: string; issuer: string; stored_at: string; metadata?: Record<string, any>; }>; total: number; };}
async function listWalletCredentials(apiKey: string,walletId: string,password: string): Promise<ListCredentialsResponse> {const params = new URLSearchParams({ password });const response = await fetch(`https://api.veriglob.com/v1/wallets/${walletId}/credentials?${params}`,{headers: { 'Authorization': `Bearer ${apiKey}` }});
if (!response.ok) {throw new Error(`HTTP error! status: ${response.status}`);}
return response.json();}
// Usageconst credentials = await listWalletCredentials('your-api-key','wallet_abc123def456','secure-password');console.log('Total credentials:', credentials.data.total);credentials.data.credentials.forEach(cred => {console.log(`- ${cred.credential_type} from ${cred.issuer}`);});type ListCredentialsResponse struct { Status string `json:"status"` Message string `json:"message"` Data struct { Credentials []struct { CredentialID string `json:"credential_id"` CredentialType string `json:"credential_type"` Issuer string `json:"issuer"` StoredAt string `json:"stored_at"` Metadata map[string]interface{} `json:"metadata,omitempty"` } `json:"credentials"` Total int `json:"total"` } `json:"data"`}
func ListWalletCredentials(apiKey, walletId, password string) (*ListCredentialsResponse, error) { url := fmt.Sprintf("https://api.veriglob.com/v1/wallets/%s/credentials?password=%s", walletId, url.QueryEscape(password))
req, _ := http.NewRequest("GET", url, nil) req.Header.Set("Authorization", "Bearer "+apiKey)
client := &http.Client{} resp, err := client.Do(req) if err != nil { return nil, err } defer resp.Body.Close()
var result ListCredentialsResponse json.NewDecoder(resp.Body).Decode(&result) return &result, nil}from urllib.parse import urlencode
def list_wallet_credentials(api_key: str, wallet_id: str, password: str) -> dict:"""List all credentials stored in a wallet."""params = urlencode({'password': password})response = requests.get(f'https://api.veriglob.com/v1/wallets/{wallet_id}/credentials?{params}',headers={'Authorization': f'Bearer {api_key}'})response.raise_for_status()return response.json()
# Usage
result = list_wallet_credentials('your-api-key', 'wallet_abc123def456', 'secure-password')print(f"Total credentials: {result['data']['total']}")for cred in result['data']['credentials']:print(f"- {cred['credential_type']} from {cred['issuer']}")Response
Section titled “Response”200 OK
{ "status": "success", "message": "Credentials retrieved successfully", "data": { "credentials": [ { "credential_id": "urn:uuid:3978344f-8596-4c3a-a978-8fcaba3903c5", "credential_type": "EmploymentCredential", "issuer": "did:key:z6MkissuerDID1...", "stored_at": "2024-01-20T14:00:00Z", "metadata": { "label": "Employment at Acme Corp", "tags": ["employment", "acme"] } }, { "credential_id": "urn:uuid:4567890a-bcde-4f01-2345-67890abcdef0", "credential_type": "EducationCredential", "issuer": "did:key:z6MkissuerDID2...", "stored_at": "2024-01-25T09:15:00Z", "metadata": { "label": "BS Computer Science", "tags": ["education", "degree"] } } ], "total": 2 }}Delete a Credential from Wallet
Section titled “Delete a Credential from Wallet”Removes a credential from a wallet.
DELETE /v1/wallets/{wallet_id}/credentials/{credential_id}Authentication
Section titled “Authentication”Requires BearerAuth or ApiKeyAuth.
Path Parameters
Section titled “Path Parameters”| Parameter | Type | Required | Description |
|---|---|---|---|
wallet_id | string | Yes | The wallet ID |
credential_id | string | Yes | The credential ID to remove |
Request Body
Section titled “Request Body”| Field | Type | Required | Description |
|---|---|---|---|
password | string | Yes | The wallet password |
Request Example
Section titled “Request Example”curl -X DELETE "https://api.veriglob.com/v1/wallets/wallet_abc123def456/credentials/urn:uuid:3978344f-8596-4c3a-a978-8fcaba3903c5" \ -H "Authorization: Bearer your-api-key" \ -H "Content-Type: application/json" \ -d '{ "password": "secure-wallet-password" }'interface DeleteCredentialResponse { status: string; message: string; data: { credential_id: string; deleted_at: string; };}
async function deleteCredentialFromWallet(apiKey: string,walletId: string,credentialId: string,password: string): Promise<DeleteCredentialResponse> {const response = await fetch(`https://api.veriglob.com/v1/wallets/${walletId}/credentials/${encodeURIComponent(credentialId)}`,{method: 'DELETE',headers: {'Authorization': `Bearer ${apiKey}`,'Content-Type': 'application/json'},body: JSON.stringify({ password })});
if (!response.ok) {throw new Error(`HTTP error! status: ${response.status}`);}
return response.json();}
// Usageconst result = await deleteCredentialFromWallet('your-api-key','wallet_abc123def456','urn:uuid:3978344f-8596-4c3a-a978-8fcaba3903c5','secure-password');console.log('Deleted at:', result.data.deleted_at);type DeleteCredentialResponse struct { Status string `json:"status"` Message string `json:"message"` Data struct { CredentialID string `json:"credential_id"` DeletedAt string `json:"deleted_at"` } `json:"data"`}
func DeleteCredentialFromWallet(apiKey, walletId, credentialId, password string) (*DeleteCredentialResponse, error) { reqBody := map[string]string{"password": password} jsonData, _ := json.Marshal(reqBody)
encodedCredID := url.PathEscape(credentialId) url := fmt.Sprintf("https://api.veriglob.com/v1/wallets/%s/credentials/%s", walletId, encodedCredID)
req, _ := http.NewRequest("DELETE", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer "+apiKey) req.Header.Set("Content-Type", "application/json")
client := &http.Client{} resp, err := client.Do(req) if err != nil { return nil, err } defer resp.Body.Close()
var result DeleteCredentialResponse json.NewDecoder(resp.Body).Decode(&result) return &result, nil}from urllib.parse import quote
def delete_credential_from_wallet(api_key: str,wallet_id: str,credential_id: str,password: str) -> dict:"""Remove a credential from a wallet."""encoded_cred_id = quote(credential_id, safe='')response = requests.delete(f'https://api.veriglob.com/v1/wallets/{wallet_id}/credentials/{encoded_cred_id}',headers={'Authorization': f'Bearer {api_key}','Content-Type': 'application/json'},json={'password': password})response.raise_for_status()return response.json()
# Usage
result = delete_credential_from_wallet('your-api-key','wallet_abc123def456','urn:uuid:3978344f-8596-4c3a-a978-8fcaba3903c5','secure-password')print(f"Deleted at: {result['data']['deleted_at']}")Response
Section titled “Response”200 OK
{ "status": "success", "message": "Credential removed successfully", "data": { "credential_id": "urn:uuid:3978344f-8596-4c3a-a978-8fcaba3903c5", "deleted_at": "2024-02-01T10:00:00Z" }}Wallet Security
Section titled “Wallet Security”Encryption
Section titled “Encryption”Wallets are encrypted using industry-standard encryption:
- Key Derivation: Argon2id from the user’s password
- Encryption: AES-256-GCM for wallet contents
- Key Storage: Only encrypted data is stored; passwords are never persisted
Best Practices
Section titled “Best Practices”- Use strong passwords - Minimum 12 characters with mixed case, numbers, and symbols
- Never share passwords - Each user should have their own wallet
- Backup wallet IDs - Store wallet IDs securely for recovery
- Use separate wallets - Consider separate wallets for different purposes (personal, business)
- Regular audits - Periodically review stored credentials