Authentication
Guardian API uses wallet-based authentication via message signing.
Overview
Most Guardian endpoints are public (read-only). Write operations require authentication via Solana wallet signature.
Public Endpoints
These endpoints don't require authentication:
GET /api/health- Health checkGET /api/vaults- List vaults (paginated)GET /api/vaults/:id- Get vault detailsGET /api/transactions- List transactionsGET /api/analytics- Get analyticsGET /api/actions/:vault/:nonce- Get Blink metadata
Protected Endpoints
These endpoints require wallet signature:
POST /api/vaults- Create vaultPATCH /api/vaults/:id- Update vaultPOST /api/actions/:vault/:nonce/approve- Approve overridePOST /api/webhooks- Create webhook subscription
Authentication Flow
1. Generate Message
Create a message to sign:
const message = `Sign this message to authenticate with Aegis Guardian.\n\nTimestamp: ${Date.now()}`;2. Sign with Wallet
Sign the message with your Solana wallet:
import { Keypair } from '@solana/web3.js';
import bs58 from 'bs58';
const keypair = Keypair.fromSecretKey(secretKey);
const messageBytes = new TextEncoder().encode(message);
const signature = await keypair.sign(messageBytes);
const signatureBase58 = bs58.encode(signature);3. Include in Request
Add signature to request headers:
const response = await fetch('https://aegis-guardian-production.up.railway.app/api/vaults', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Wallet-Address': keypair.publicKey.toBase58(),
'X-Signature': signatureBase58,
'X-Message': message,
},
body: JSON.stringify({
name: 'My Vault',
agentSigner: '...',
dailyLimit: 1000000000,
}),
});Example: Complete Authentication
import { Keypair } from '@solana/web3.js';
import bs58 from 'bs58';
async function authenticatedRequest(
endpoint: string,
method: string = 'GET',
body?: any
) {
const keypair = Keypair.fromSecretKey(/* your secret key */);
// Generate message
const message = `Sign this message to authenticate with Aegis Guardian.\n\nTimestamp: ${Date.now()}`;
// Sign message
const messageBytes = new TextEncoder().encode(message);
const signature = keypair.sign(messageBytes);
const signatureBase58 = bs58.encode(signature);
// Make request
const response = await fetch(`https://aegis-guardian-production.up.railway.app${endpoint}`, {
method,
headers: {
'Content-Type': 'application/json',
'X-Wallet-Address': keypair.publicKey.toBase58(),
'X-Signature': signatureBase58,
'X-Message': message,
},
body: body ? JSON.stringify(body) : undefined,
});
if (!response.ok) {
throw new Error(`Request failed: ${response.statusText}`);
}
return await response.json();
}
// Usage
const vault = await authenticatedRequest('/api/vaults', 'POST', {
name: 'My Vault',
agentSigner: agentPublicKey.toBase58(),
dailyLimit: 1_000_000_000,
});SDK Integration
The Aegis SDK handles authentication automatically:
import { AegisClient } from '@aegis-vaults/sdk';
const client = new AegisClient({
cluster: 'devnet',
guardianApiUrl: 'https://aegis-guardian-production.up.railway.app',
});
// SDK handles authentication
client.setWallet(keypair);
await client.createVault({...}); // Automatically signedSecurity Best Practices
- Use HTTPS - Always use HTTPS for API requests
- Timestamp Messages - Include timestamp to prevent replay attacks
- Short-Lived Signatures - Generate new signatures for each request
- Secure Key Storage - Never expose private keys in client-side code
- Verify Signatures - Guardian verifies all signatures server-side
Next Steps
- API Endpoints - Complete API reference
- Webhooks - Configure notifications