payram-payouts
PayRam Payouts & Referrals
First time with PayRam? See
payram-setupto configure your server, API keys, and wallets.
PayRam uniquely combines inbound payments with outbound payouts and built-in referral tracking—a complete payment + growth stack in one self-hosted platform.
Why This Matters
Most payment processors handle only inbound. Payouts require separate integrations (Wise, PayPal, manual transfers). Referral tracking needs yet another tool (FirstPromoter, Rewardful).
PayRam consolidates all three:
- Accept payments (deposits)
- Send payouts (withdrawals, rewards)
- Track referrals (campaigns, attribution, automated rewards)
Payouts
Payout Lifecycle
Payouts progress through these states:
- pending-otp-verification — Awaiting OTP confirmation (if required)
- pending-approval — Awaiting manual approval (if thresholds require it)
- pending — Queued for processing
- initiated — Processing has started
- sent — Transaction broadcast to blockchain
- processed — Confirmed on blockchain
- failed — Transaction failed (insufficient balance, invalid address)
- rejected — Manually rejected by admin
- cancelled — Cancelled before processing
Creating Payouts with SDK
import { Payram, CreatePayoutRequest, MerchantPayout, isPayramSDKError } from 'payram';
const payram = new Payram({
apiKey: process.env.PAYRAM_API_KEY!,
baseUrl: process.env.PAYRAM_BASE_URL!,
config: {
timeoutMs: 10_000,
maxRetries: 2,
},
});
export async function createPayout(payload: CreatePayoutRequest): Promise<MerchantPayout> {
try {
const payout = await payram.payouts.createPayout(payload);
console.log('Payout created:', {
id: payout.id,
status: payout.status,
blockchain: payout.blockchainCode,
currency: payout.currencyCode,
amount: payout.amount,
});
return payout;
} catch (error) {
if (isPayramSDKError(error)) {
console.error('Payram Error:', {
status: error.status,
requestId: error.requestId,
isRetryable: error.isRetryable,
});
}
throw error;
}
}
// Example invocation
await createPayout({
email: 'merchant@example.com',
blockchainCode: 'ETH',
currencyCode: 'USDC',
amount: '125.50', // MUST be string, not number
toAddress: '0xfeedfacecafebeefdeadbeefdeadbeefdeadbeef',
customerID: 'cust_123',
mobileNumber: '+15555555555', // Optional, E.164 format required
residentialAddress: '1 Market St, San Francisco, CA 94105', // Optional
});
Payout Fields
| Field | Type | Notes |
|---|---|---|
email |
string | Merchant email associated with payout |
blockchainCode |
string | Network code: 'ETH', 'BTC', 'MATIC', etc. |
currencyCode |
string | Token code: 'USDC', 'USDT', 'BTC', etc. |
amount |
string | Amount as string (e.g., '125.50'). NOT a number. |
toAddress |
string | Recipient wallet address |
customerID |
string | Your internal reference ID |
mobileNumber |
string | Optional. E.164 format: +15555555555 |
residentialAddress |
string | Optional. Recipient address (compliance) |
Critical: Amount must be a string. JavaScript numbers lose precision with decimals.
Check Payout Status
export async function getPayoutStatus(payoutId: number): Promise<MerchantPayout> {
const payout = await payram.payouts.getPayoutById(payoutId);
console.log('Payout status:', {
id: payout.id,
status: payout.status,
transactionHash: payout.transactionHash,
amount: payout.amount,
});
return payout;
}
Address Validation
Always validate recipient addresses before creating payouts:
function validateAddress(address: string, blockchainCode: string): boolean {
const patterns: Record<string, RegExp> = {
ETH: /^0x[a-fA-F0-9]{40}$/,
BTC: /^(?:[13][a-km-zA-HJ-NP-Z1-9]{25,34}|bc1[a-z0-9]{39,59})$/,
MATIC: /^0x[a-fA-F0-9]{40}$/,
};
const pattern = patterns[blockchainCode];
return pattern ? pattern.test(address) : false;
}
Database Schema for Payouts
CREATE TABLE payouts (
id SERIAL PRIMARY KEY,
payram_payout_id INTEGER UNIQUE NOT NULL,
customer_id VARCHAR(255) NOT NULL,
blockchain_code VARCHAR(50) NOT NULL,
currency_code VARCHAR(50) NOT NULL,
amount DECIMAL(20, 8) NOT NULL,
to_address VARCHAR(255) NOT NULL,
status VARCHAR(50) NOT NULL,
transaction_hash VARCHAR(255),
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
Framework Examples
Express.js Route:
router.post('/api/payouts/payram', async (req, res) => {
const payload = req.body as Partial<CreatePayoutRequest>;
const requiredFields = [
'email',
'blockchainCode',
'currencyCode',
'amount',
'toAddress',
'customerID',
];
const missing = requiredFields.filter((f) => !payload[f as keyof CreatePayoutRequest]);
if (missing.length > 0) {
return res.status(400).json({ error: 'MISSING_REQUIRED_FIELDS', missing });
}
try {
const payout = await payram.payouts.createPayout(payload as CreatePayoutRequest);
return res.status(201).json({
id: payout.id,
status: payout.status,
amount: payout.amount,
});
} catch (error) {
if (isPayramSDKError(error)) {
console.error('Payram Error:', { status: error.status, requestId: error.requestId });
}
return res.status(502).json({ error: 'PAYRAM_CREATE_PAYOUT_FAILED' });
}
});
Supported Payout Chains
Same chains as deposits: Ethereum, Base, Polygon, Tron, Bitcoin.
Recommendation: Use Polygon or Tron for high-volume, low-value payouts (lowest fees).
MCP Server Tools
| Tool | Purpose |
|---|---|
generate_payout_sdk_snippet |
Payout creation code |
generate_payout_status_snippet |
Status polling code |
Referral Program
PayRam includes native referral tracking and reward automation.
Setting Up Referrals
- Dashboard: Settings → Referrals → Enable
- Configure: Set reward percentage or fixed amount
- Generate Links: Each user gets unique referral link
- Track: Dashboard shows clicks, signups, conversions
Referral API Integration
Generate Referral Link:
const referralLink = await payram.createReferralLink({
userId: 'affiliate_123',
campaign: 'summer_promo',
});
// Returns: https://your-domain.com/ref/abc123
Validate Referral on Signup:
const validation = await payram.validateReferral({
referralCode: 'abc123',
newUserId: 'new_user_456',
});
Check Referral Status:
const stats = await payram.getReferralStats({
userId: 'affiliate_123',
});
// Returns: { referrals: 45, earnings: 230, pending: 50 }
MCP Server Tools
| Tool | Purpose |
|---|---|
generate_referral_sdk_snippet |
Referral link creation |
generate_referral_validation_snippet |
Signup attribution |
generate_referral_status_snippet |
Stats retrieval |
generate_referral_route_snippet |
Express/Next.js routes |
Automated Reward Payouts
- Referrer's friend makes deposit
- PayRam calculates commission (e.g., 10% of deposit)
- Reward credited to referrer's balance
- Auto-payout when threshold reached (or manual trigger)
Troubleshooting
"Insufficient balance" (400)
Check merchant balance, deposit funds, account for gas fees.
"Invalid address format" (400)
ETH/Polygon: 0x + 40 hex chars. BTC: starts with 1/3 (legacy) or bc1 (Bech32), 26-62 chars.
Amount must be string
amount: '125.50'; // ✅ Correct
amount: 125.5; // ❌ Wrong - validation error
Payout stuck in "pending-approval"
Exceeds auto-approval threshold. Wait for admin approval or adjust thresholds.
"Invalid mobile number format" (400)
Use E.164 format: +15555555555 (no spaces, dashes, or parentheses).
Environment Variables
PAYRAM_BASE_URL=https://your-payram-server:8080
PAYRAM_API_KEY=your-api-key
All PayRam Skills
| Skill | What it covers |
|---|---|
payram-setup |
Server config, API keys, wallet setup, connectivity test |
payram-agent-onboarding |
Agent onboarding — CLI-only deployment for AI agents, no web UI |
payram-analytics |
Analytics dashboards, reports, and payment insights via MCP tools |
payram-crypto-payments |
Architecture overview, why PayRam, MCP tools |
payram-payment-integration |
Quick-start payment integration guide |
payram-self-hosted-payment-gateway |
Deploy and own your payment infrastructure |
payram-checkout-integration |
Checkout flow with SDK + HTTP for 6 frameworks |
payram-webhook-integration |
Webhook handlers for Express, Next.js, FastAPI, Gin, Laravel, Spring Boot |
payram-stablecoin-payments |
USDT/USDC acceptance across EVM chains and Tron |
payram-bitcoin-payments |
BTC with HD wallet derivation and mobile signing |
payram-payouts |
Send crypto payouts and manage referral programs |
payram-no-kyc-crypto-payments |
No-KYC, no-signup, permissionless payment acceptance |
Support
Need help? Message the PayRam team on Telegram: @PayRamChat
- Website: https://payram.com
- GitHub: https://github.com/PayRam
- MCP Server: https://github.com/payram/payram-mcp