This guide is for customers with existing custody infrastructure who want full programmatic control over yield operations. If you have your own custody solution (HSM, MPC, homegrown infrastructure) and want to integrate with RebelFi APIs, this is your path.
Who This Is For
Crypto-native companies with existing custody infrastructure
Institutional investors with security policies requiring custom signing
Wallet providers integrating yield into their existing platform
Payment processors with operational wallet infrastructure
Key Characteristic : You want to run your own agent that polls RebelFi for unsigned transactions, signs them with your custody, and reports back execution status.
Alternative Approaches : If you prefer RebelFi to manage the agent, see Custody Adapters . If you use Fireblocks/BitGo directly, consider Direct API Integration.
Architecture Overview
The Complete Flow
1. Customer Funds → Your Custody Wallet
2. RebelFi Detects Idle Funds → Creates Operation
3. You Query Pending Operations
4. You Approve Operation
5. Your Agent Polls for Unsigned Transaction
6. Your Custody Signs Transaction
7. Your Agent Reports Execution
8. RebelFi Monitors Blockchain Confirmation
9. Allocation Active, Earning Yield
Key Integration Points
Step API Endpoint Your Responsibility
Account Setup POST /api/core/auth/*One-time registration Custody Config POST /api/core/custody/setup/third-partyConfigure platform API Keys POST /api/core/apikeys/generateGenerate and store securely Wallet Import POST /api/core/org-walletsProvide wallet address Enable Monitoring POST /api/core/wallets/add-and-monitorSet buffer amount Approve Operations POST /api/core/operations/:id/approveProgrammatic approval Poll for Work POST /api/agent/transactions/pollYour agent calls every 10-30s Sign Transaction Your Custody API Your signing infrastructure Report Execution POST /api/agent/transactions/:id/reportYour agent reports txHash
The three bolded rows are where your custom agent integrates. Everything else is standard API usage.
Phase 1: Account Setup (One-Time)
Step 1.1: Register Email
POST / api / core / auth / register - email
Content - Type : application / json
{
"email" : "treasury@yourcompany.com"
}
Response :
{
"success" : true ,
"message" : "Verification code sent to email"
}
You’ll receive a 6-digit verification code via email.
Step 1.2: Verify Email
POST / api / core / auth / verify - email
Content - Type : application / json
{
"email" : "treasury@yourcompany.com" ,
"code" : "123456" // From email
}
Response :
{
"success" : true ,
"verified" : true
}
Step 1.3: Complete Registration
POST / api / core / auth / register
Content - Type : application / json
{
"firstName" : "Treasury" ,
"lastName" : "Team" ,
"email" : "treasury@yourcompany.com" ,
"password" : "SecurePassword123!" ,
"clientType" : "WEB"
}
Response :
{
"success" : true ,
"data" : {
"user" : { "id" : 1 , "email" : "..." },
"session" : { "accessToken" : "..." , "refreshToken" : "..." }
}
}
Store the accessToken securely. You’ll need it for subsequent API calls that require JWT authentication (dashboard-style endpoints).
Tell RebelFi you’re using a third-party custody solution:
POST / api / core / custody / setup / third - party
Authorization : Bearer YOUR_ACCESS_TOKEN
Content - Type : application / json
{
"custodyPlatform" : "REBELFI_AGENT" , // For custom agents
"supportedChains" : [ "SOLANA" ] // Blockchains you support
}
Response :
{
"success" : true ,
"data" : {
"platform" : "REBELFI_AGENT" ,
"chains" : [ "SOLANA" ]
}
}
Use "REBELFI_AGENT" as the platform name when you’re running your own custom polling agent.
Phase 2: Generate API Keys
API keys are required for agent polling endpoints.
POST / api / core / apikeys / generate
Authorization : Bearer YOUR_ACCESS_TOKEN
Content - Type : application / json
{
"name" : "Production Agent"
}
Response :
{
"success" : true ,
"data" : {
"id" : 1 ,
"key" : "rfk_live_xxxxxxxxxxxxxxxxxxxxx" ,
"name" : "Production Agent" ,
"createdAt" : "2025-01-30T10:00:00Z"
}
}
Critical : Save the key value immediately. It will only be shown once. This is your X-API-Key for agent polling.export REBELFI_API_KEY = "rfk_live_xxxxxxxxxxxxxxxxxxxxx"
Phase 3: Import and Monitor Wallets
Step 3.1: Import Wallet
Import your custody wallet address into RebelFi:
POST / api / core / org - wallets
Authorization : Bearer YOUR_ACCESS_TOKEN
Content - Type : application / json
{
"chainName" : "SOLANA" ,
"name" : "Treasury Wallet" ,
"address" : "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"
}
Response :
{
"success" : true ,
"data" : {
"id" : 123 , // This is your orgWalletId
"address" : "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU" ,
"chainName" : "SOLANA" ,
"name" : "Treasury Wallet"
}
}
Step 3.2: Enable Yield Monitoring
Enable RebelFi to monitor this wallet for yield opportunities:
POST / api / core / wallets / add - and - monitor
Authorization : Bearer YOUR_ACCESS_TOKEN
Content - Type : application / json
{
"orgWalletId" : 123 ,
"enableYield" : true ,
"bufferAmount" : "100000" // Base units: 0.1 USDC buffer
}
Response :
{
"success" : true ,
"data" : {
"managedWallet" : {
"id" : 456 , // This is your opWalletId
"orgWalletId" : 123 ,
"enableYield" : true ,
"bufferAmountBase" : "100000"
},
"wallet" : {
"id" : 789 ,
"address" : "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"
}
}
}
Buffer Amount : Funds kept liquid (not deployed to yield). Set to your minimum operational liquidity requirement.
bufferAmount is in base units (e.g., 100000 = 0.1 USDC for 6 decimals)
Funds above buffer are automatically eligible for yield deployment
Phase 4: Auto-Supply Flow (When Funds Arrive)
What Happens Automatically
When funds arrive in your wallet:
RebelFi Monitoring detects the inflow
Operation Auto-Created (type: SUPPLY, status: PENDING_APPROVAL)
Your workflow takes over
RebelFi only creates operations for funds above your buffer amount . If you have a 0.1 USDC buffer and receive 1.0 USDC, a SUPPLY operation will be created for ~0.9 USDC.
Step 4.1: Query Pending Operations
Check for operations needing approval:
GET / api / core / operations / queue
Authorization : Bearer YOUR_ACCESS_TOKEN
Response :
{
"success" : true ,
"data" : {
"intents" : [
{
"id" : 789 ,
"type" : "SUPPLY" ,
"status" : "PENDING_APPROVAL" ,
"managedWalletId" : 456 ,
"amount" : "900000" , // Base units: 0.9 USDC
"token" : "USDC" ,
"estimatedAPY" : "6.5%" ,
"createdAt" : "2025-01-30T14:00:00Z"
}
]
}
}
Authentication Note : This endpoint currently requires JWT (Authorization: Bearer) authentication, not API key (X-API-Key). Planned enhancement: API key support coming soon.
Step 4.2: Approve Operation
Programmatically approve the operation:
POST / api / core / operations / 789 / approve
Authorization : Bearer YOUR_ACCESS_TOKEN
Response :
{
"success" : true ,
"data" : {
"id" : 789 ,
"status" : "EXECUTING" ,
"approvedAt" : "2025-01-30T14:01:00Z"
}
}
Once approved, the operation enters the EXECUTING state and is ready for your agent to pick up.
Policy Configuration : You can configure your organization to auto-approve certain operations (below threshold, specific wallets, etc.). Contact support or configure in Settings → Operation Policies.
Phase 5: Agent Polling & Execution (Your Custom Agent)
This is where your custom agent takes control.
Step 5.1: Poll for Unsigned Transactions
Your agent should poll every 10-30 seconds:
POST / api / agent / transactions / poll
X - API - Key : rfk_live_xxxxxxxxxxxxxxxxxxxxx
Content - Type : application / json
{
"leaseDurationMs" : 30000 // 30 seconds
}
Response (Transaction Available) :
{
"success" : true ,
"data" : {
"transaction" : {
"id" : 4001 ,
"attemptId" : 5001 ,
"operationId" : 789 ,
"unsignedTx" : "AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAHEAoMCg..." ,
"metadata" : {
"blockchain" : "SOLANA" ,
"walletId" : 456 ,
"amount" : "900000" ,
"token" : "USDC" ,
"type" : "SUPPLY"
},
"claimedAt" : "2025-01-30T14:01:00Z" ,
"leaseExpiresAt" : "2025-01-30T14:01:30Z"
}
}
}
Response (No Work Available) :
{
"success" : true ,
"data" : {
"transaction" : null
}
}
Lease Mechanism : When you poll and receive a transaction, it’s “claimed” for leaseDurationMs milliseconds. If you don’t report within that time, the lease expires and another agent can claim it.Set leaseDurationMs longer than your signing + submission time. Typical values: 30-60 seconds.
Step 5.2: Sign Transaction with Your Custody
This is your custom custody integration . Examples:
Custom HSM
MPC Wallet
Smart Contract Wallet
// Your custom HSM signing
const signedTx = await yourHSM . sign ({
unsignedTransaction: transaction . unsignedTx ,
walletAddress: transaction . metadata . walletAddress ,
keyId: 'your-key-id'
});
Step 5.3: Submit to Blockchain
After signing, submit to the blockchain:
import { Connection } from '@solana/web3.js' ;
const connection = new Connection ( 'https://api.mainnet-beta.solana.com' );
const txHash = await connection . sendRawTransaction (
Buffer . from ( signedTx , 'base64' )
);
console . log ( 'Transaction submitted:' , txHash );
Step 5.4: Report Execution to RebelFi
Report the transaction hash back to RebelFi:
POST / api / agent / transactions / 5001 / report
X - API - Key : rfk_live_xxxxxxxxxxxxxxxxxxxxx
Content - Type : application / json
{
"attemptId" : 5001 ,
"status" : "SUCCESS" ,
"result" : {
"txHash" : "5aApzp1XxiNzFotAiZt6z7BaTTYCS7964ycpxwYp4eVyxentgDcevD12pKoT7qHUakoBnp3nZPqrXz4479FZs59J" ,
"submissionMode" : "AGENT"
}
}
Response :
{
"success" : true ,
"data" : {
"attemptId" : 5001 ,
"status" : "SUBMITTED" ,
"txHash" : "5aApzp..." ,
"reportedAt" : "2025-01-30T14:01:15Z"
}
}
Reporting Failures : If signing or submission fails, report with status: "FAILED" and include an error message:{
"attemptId" : 5001 ,
"status" : "FAILED" ,
"result" : {
"error" : "Insufficient SOL for transaction fees"
}
}
Phase 6: RebelFi Monitors Completion
After you report the transaction:
RebelFi monitors blockchain for confirmation
Operation completes when transaction confirms
Allocation created (funds now earning yield)
Available balance updated (funds moved from available → allocated)
You can query the operation status:
GET / api / core / operations / 789
Authorization : Bearer YOUR_ACCESS_TOKEN
Response (Completed) :
{
"success" : true ,
"data" : {
"id" : 789 ,
"type" : "SUPPLY" ,
"status" : "COMPLETED" ,
"completedAt" : "2025-01-30T14:02:30Z" ,
"txHash" : "5aApzp..."
}
}
Phase 7: Query Yield Metrics (Roadmap)
Current Status : Yield metrics APIs are planned but not yet available with API key authentication. Use the dashboard for now.
Planned Endpoints :
// Token positions with yield breakdown
GET / api / token - positions / op - wallet / : id
X - API - Key : rfk_live_xxxxxxxxxxxxxxxxxxxxx
// Would return:
{
"balances" : {
"total" : { "amount" : "1.11" , "currency" : "USDC" },
"principal" : { "amount" : "1.10" , "currency" : "USDC" },
"yield" : { "amount" : "0.01" , "currency" : "USDC" }
},
"performance" : {
"currentAPY" : "6.0" ,
"lifetimeYield" : { "amount" : "0.01" , "currency" : "USDC" }
}
}
See Yield Metrics API for planned features.
Phase 8: Disburse Flow (Withdraw Funds)
To withdraw funds from yield back to your wallet:
Step 8.1: Create Disburse Operation
POST / api / core / wallets / transfer - out
Authorization : Bearer YOUR_ACCESS_TOKEN
Content - Type : application / json
{
"walletId" : 789 ,
"tokenMint" : "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" , // USDC
"amount" : "0.5" , // Decimal format
"destinationAddress" : "YourDestinationWalletAddress..."
}
Response :
{
"success" : true ,
"data" : {
"operationId" : 790 ,
"type" : "DISBURSE" ,
"status" : "PENDING_APPROVAL"
}
}
Step 8.2: Follow Same Flow
The disburse operation follows the exact same flow as supply:
Query operations queue → See DISBURSE operation
Approve operation → POST /api/core/operations/790/approve
Agent polls → Receives UNWIND + TRANSFER transaction
Sign with your custody → Same signing process
Report execution → POST /api/agent/transactions/:id/report
RebelFi monitors completion
Disburse operations often have two steps in a single transaction:
UNWIND - Withdraw from yield protocol
TRANSFER_OUT - Send to destination address
Your agent receives these as a single atomic transaction to sign.
Complete Agent Implementation Example
Here’s a complete polling agent implementation:
import axios from 'axios' ;
import { Connection } from '@solana/web3.js' ;
import { yourCustodySolution } from './custody' ;
const agent = axios . create ({
baseURL: process . env . REBELFI_BASE_URL ,
headers: { 'X-API-Key' : process . env . REBELFI_API_KEY }
});
const solanaConnection = new Connection ( process . env . SOLANA_RPC_URL );
async function pollAndExecute () {
try {
// 1. Poll for transaction
const { data } = await agent . post ( '/api/agent/transactions/poll' , {
leaseDurationMs: 30000
});
if ( data . data . transaction ) {
const tx = data . data . transaction ;
console . log ( `Claimed transaction ${ tx . id } for operation ${ tx . operationId } ` );
try {
// 2. Sign with your custody
const signedTx = await yourCustodySolution . sign ({
unsignedTx: tx . unsignedTx ,
metadata: tx . metadata
});
// 3. Submit to blockchain
const txHash = await solanaConnection . sendRawTransaction (
Buffer . from ( signedTx , 'base64' )
);
console . log ( `Transaction submitted: ${ txHash } ` );
// 4. Report success
await agent . post ( `/api/agent/transactions/ ${ tx . id } /report` , {
attemptId: tx . attemptId ,
status: 'SUCCESS' ,
result: {
txHash: txHash ,
submissionMode: 'AGENT'
}
});
console . log ( `Transaction ${ tx . id } reported successfully` );
} catch ( error ) {
// Report failure
console . error ( 'Execution error:' , error );
await agent . post ( `/api/agent/transactions/ ${ tx . id } /report` , {
attemptId: tx . attemptId ,
status: 'FAILED' ,
result: {
error: error . message
}
});
}
} else {
console . log ( 'No transactions available' );
}
} catch ( error ) {
console . error ( 'Polling error:' , error );
}
}
// Main loop
async function main () {
console . log ( 'Starting RebelFi custom agent...' );
while ( true ) {
await pollAndExecute ();
await new Promise ( resolve => setTimeout ( resolve , 10000 )); // Poll every 10 seconds
}
}
main ();
Error Handling & Best Practices
Handling Lease Expiry
If your agent crashes or takes too long, the lease expires:
// Best practice: Set lease longer than signing time
const AVERAGE_SIGNING_TIME = 5000 ; // 5 seconds
const NETWORK_LATENCY = 2000 ; // 2 seconds
const LEASE_DURATION = ( AVERAGE_SIGNING_TIME + NETWORK_LATENCY ) * 3 ; // 21 seconds buffer
await agent . post ( '/api/agent/transactions/poll' , {
leaseDurationMs: LEASE_DURATION
});
Retry Logic
async function pollWithRetry ( maxRetries = 3 ) {
for ( let attempt = 0 ; attempt < maxRetries ; attempt ++ ) {
try {
return await pollAndExecute ();
} catch ( error ) {
if ( attempt === maxRetries - 1 ) throw error ;
const delay = Math . pow ( 2 , attempt ) * 1000 ; // Exponential backoff
await new Promise ( resolve => setTimeout ( resolve , delay ));
}
}
}
Monitoring Agent Health
const metrics = {
lastPollAt: null ,
lastExecutionAt: null ,
successCount: 0 ,
failureCount: 0
};
// Expose health endpoint
app . get ( '/health' , ( req , res ) => {
const isHealthy =
metrics . lastPollAt &&
( Date . now () - metrics . lastPollAt . getTime ()) < 60000 ;
res . json ({
status: isHealthy ? 'healthy' : 'unhealthy' ,
metrics: {
lastPollAt: metrics . lastPollAt ,
lastExecutionAt: metrics . lastExecutionAt ,
successRate: ( metrics . successCount / ( metrics . successCount + metrics . failureCount ) * 100 ). toFixed ( 2 ) + '%'
}
});
});
Deployment Considerations
Infrastructure Requirements
Compute : Lightweight (polling loop, signing, API calls)
Network : Outbound HTTPS to api.rebelfi.io and blockchain RPC
Secrets : Secure storage for API keys and custody credentials
Uptime : High availability recommended (operations wait for your agent)
Deployment Options
Docker
Kubernetes
Systemd
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --production
COPY . .
CMD [ "node" , "agent.js" ]
docker run -d \
--name rebelfi-agent \
--env-file .env \
--restart unless-stopped \
your-agent-image:latest
Security Best Practices
Store API keys in secrets manager (AWS Secrets Manager, HashiCorp Vault)
Never log API keys in plain text
Rotate API keys periodically (every 90 days recommended)
Use different API keys for dev/staging/production
Store custody credentials encrypted at rest
Use hardware security modules (HSM) where possible
Implement least-privilege access for agent service accounts
Audit all signing operations
Run agent in private network segment
Restrict outbound traffic to RebelFi API and blockchain RPC only
Use TLS for all communications
Consider VPN or private link for additional security
Run agent with automatic restart (Docker, systemd, K8s)
Monitor agent health and alert on failures
The lease mechanism prevents duplicate execution even with multiple agents
Implement dead letter queue for failed transactions
Troubleshooting
Symptoms : No logs showing poll attemptsCheck :
Agent process is running
Network connectivity to api.rebelfi.io
API key is valid (X-API-Key header)
Environment variables loaded correctly
Solution :# Test API connectivity
curl https://api.rebelfi.io/api/agent/transactions/poll \
-X POST \
-H "X-API-Key: $REBELFI_API_KEY " \
-H "Content-Type: application/json" \
-d '{"leaseDurationMs": 30000}'
Symptoms : Funds in wallet but no operations createdCheck :
Funds are above buffer amount
Wallet monitoring is enabled
No other operation is currently in progress (wallet-level locking)
Solution :
Query wallet status:GET / api / core / wallets / monitored
Symptoms : Agent reports “FAILED” status repeatedlyCheck :
Custody credentials are valid
Custody service is reachable
Transaction format is correct for your custody solution
Sufficient gas/fees in wallet
Solution : Review custody logs for specific error messages
Symptoms : Transactions repeatedly claimed but never completedCheck :
leaseDurationMs is longer than signing + submission time
Network latency to custody provider
Agent isn’t crashing during execution
Solution : Increase lease duration to 60000ms (60 seconds) or monitor signing performance
Next Steps
Support
Need help with your custom custody integration?