Send crypto payouts and manage referral programs with PayRam. Self-hosted payout infrastructure — no KYC, no intermediary, no fund holds. Create payouts to any wallet across Ethereum, Base, Polygon, Tron, Bitcoin. Built-in affiliate program with automated reward distribution. Use when sending crypto payouts to users, building referral/affiliate programs, or needing integrated payment and payout infrastructure.
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.
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:
Payouts progress through these states:
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: '[email protected]',
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
});
| 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.
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;
}
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;
}
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()
);
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' });
}
});
Same chains as deposits: Ethereum, Base, Polygon, Tron, Bitcoin.
Recommendation: Use Polygon or Tron for high-volume, low-value payouts (lowest fees).
| Tool | Purpose |
|---|---|
generate_payout_sdk_snippet | Payout creation code |
generate_payout_status_snippet | Status polling code |
PayRam includes native referral tracking and reward automation.
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 }
| 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 |
Check merchant balance, deposit funds, account for gas fees.
ETH/Polygon: 0x + 40 hex chars. BTC: starts with 1/3 (legacy) or bc1 (Bech32), 26-62 chars.