@moneygraph/sdk
v2.0.4
Published
AI-native SDK for global payouts powered by StratosPay
Readme
@moneygraph/sdk
AI-native SDK for global payouts powered by StratosPay. Send money to 107+ countries with automatic FX, KYC enforcement, and developer-friendly APIs.
Features
- 🌍 Global Payouts - Send to 107+ countries via local rails
- 💳 Accept Payments - Cards, embedded widget, popup checkout
- 💱 Quote & Confirm FX - Lock rates for 2 minutes before executing
- 🔐 KYC Enforcement - Automatic verification before payouts
- 🧪 Sandbox Mode - Full mock data for rapid development
- 📦 Zero Dependencies - Uses native fetch API
- 🤖 AI-Native - Optimized for Cursor, Lovable, Claude.ai, and AI coding assistants
Installation
npm install @moneygraph/sdk
# or
yarn add @moneygraph/sdk
# or
pnpm add @moneygraph/sdkQuick Start
import { MoneyGraph } from '@moneygraph/sdk';
// Initialize with your API key
// sk_test_* = sandbox mode (mock data)
// sk_live_* = live mode (real transactions)
const mg = new MoneyGraph({ apiKey: 'sk_test_your_key' });
// Check mode
console.log(mg.mode); // 'sandbox' or 'live'Complete Payout Flow
1. Create a Customer
// Personal account
const customer = await mg.onboard.createCustomer({
account_type: 'personal',
first_name: 'John',
last_name: 'Doe',
email: '[email protected]',
phone: '2025551234',
phone_iso2: 'US',
country: 'US',
});
// Business account
const business = await mg.onboard.createCustomer({
account_type: 'business',
first_name: 'Jane',
last_name: 'Smith',
email: '[email protected]',
phone: '2025555678',
phone_iso2: 'US',
country: 'US',
business_details: {
business_name: 'Acme Corp',
address: {
country: 'US',
state: 'CA',
city: 'San Francisco',
street: '123 Main St',
postal_code: '94105',
},
},
});2. Complete KYC
// Update with KYC information
await mg.onboard.updateCustomer(customer.id, {
birthday: '15-06-1990', // DD-MM-YYYY format
gender: 'male',
id_type: 'PASSPORT',
id_number: 'P123456789',
source_of_fund_id: '22bc46b1-6a5a-493b-96cd-61b986ab698d',
state: 'CA',
city: 'San Francisco',
street: '123 Main Street',
postal_code: '94105',
});
// Upload documents
await mg.onboard.uploadDocument(customer.id, 'document', documentFile, 'passport.jpg');
await mg.onboard.uploadDocument(customer.id, 'selfie', selfieFile, 'selfie.jpg');
// Submit for review
await mg.onboard.submitKyc(customer.id);
// Check KYC status
const status = await mg.onboard.canPayout(customer.id);
console.log(status); // { allowed: true, status: 'APPROVED' }3. Get FX Quote
// Get a quote (valid for 2 minutes)
const quote = await mg.liquidity.getQuote({
from: 'USD',
to: 'NGN',
amount: 100,
});
console.log(quote);
// {
// id: 'quote_123...',
// from_currency: 'USD',
// to_currency: 'NGN',
// from_amount: 100,
// to_amount: 151500,
// rate: 1550,
// fee: 2,
// expires_at: '2025-01-15T10:02:00Z'
// }
// Check time remaining
const seconds = mg.liquidity.getQuoteTimeRemaining(quote);
console.log(`Quote expires in ${seconds} seconds`);4. Confirm Quote & Send Payout
// Confirm the quote (lock the rate)
const confirmation = await mg.liquidity.confirmQuote(quote.id);
// Send the payout
const payout = await mg.payouts.send({
quote_id: quote.id,
customer_id: customer.id,
recipient: {
name: 'Jane Doe',
bank_code: '058', // GTBank
account_number: '0123456789',
account_name: 'Jane Doe',
},
reference: 'INV-2025-001',
narration: 'Invoice payment',
});
// Or use the convenience method
const payout = await mg.sendPayout({
customerId: customer.id,
from: 'USD',
to: 'NGN',
amount: 100,
recipient: {
name: 'Jane Doe',
bank_code: '058',
account_number: '0123456789',
},
});5. Track Payout Status
const status = await mg.payouts.getStatus(payout.id);
console.log(status.status); // 'pending' -> 'processing' -> 'completed'Business Directors (for Business Accounts)
// Add a director
const director = await mg.onboard.createDirector(business.id, {
first_name: 'Michael',
last_name: 'Johnson',
email: '[email protected]',
phone: '2025551234',
phone_iso2: 'US',
country: 'US',
state: 'CA',
city: 'San Francisco',
street: '123 Main St',
postal_code: '94105',
birthday: '15-08-1978',
ownership: 25,
position: 'Chief Financial Officer',
});
// List all directors
const directors = await mg.onboard.listDirectors(business.id);
// Update a director
await mg.onboard.updateDirector(business.id, director.id, {
ownership: 30,
});
// Delete a director
await mg.onboard.deleteDirector(business.id, director.id);Reference Data
// Get supported countries
const countries = await mg.reference.getAllCountries();
// Get currencies for a country
const currencies = await mg.reference.getCurrencies('NG');
// Get source of funds options
const sources = await mg.reference.getSourceOfFunds();
// Get MCC codes
const mccs = await mg.reference.getMccCodes();
// Get business registration types
const types = await mg.reference.getBusinessRegistrationTypes();
// Search helpers
const realEstate = await mg.reference.findSourceOfFunds('real estate');
const software = await mg.reference.findMcc('software');
const llc = await mg.reference.findBusinessType('LLC');Sandbox Testing
Use sk_test_* API keys to enable sandbox mode with full mock data:
const mg = new MoneyGraph({ apiKey: 'sk_test_demo' });
// Create instant mock personas
const verified = await mg.onboard.createMockPersona('business_verified');
const pending = await mg.onboard.createMockPersona('pending_kyc');
const rejected = await mg.onboard.createMockPersona('rejected_kyc');
// All operations work with mock data
const quote = await mg.liquidity.getQuote({ from: 'USD', to: 'NGN', amount: 100 });Available mock personas:
business_verified- Approved business with directorsindividual_verified- Approved personal accountpending_kyc- Account awaiting KYC approvalrejected_kyc- Account with rejected KYC
Error Handling
import { MoneyGraph, MoneyGraphError } from '@moneygraph/sdk';
try {
await mg.payouts.send({ ... });
} catch (error) {
if (error instanceof MoneyGraphError) {
switch (error.code) {
case 'KYC_PENDING':
console.log('Customer KYC is still pending');
break;
case 'KYC_REJECTED':
console.log('Customer KYC was rejected');
break;
case 'QUOTE_EXPIRED':
console.log('Quote has expired, get a new one');
break;
case 'RATE_LIMITED':
console.log('Too many requests, slow down');
break;
default:
console.log(`Error: ${error.message}`);
}
}
}Error codes:
INVALID_API_KEY- API key is invalidUNAUTHORIZED- Not authorized for this actionKYC_PENDING- KYC verification pendingKYC_REJECTED- KYC verification rejectedKYC_ALREADY_APPROVED- Cannot update approved KYCQUOTE_EXPIRED- FX quote has expiredQUOTE_NOT_FOUND- Quote ID not foundCUSTOMER_NOT_FOUND- Customer ID not foundDIRECTOR_NOT_FOUND- Director ID not foundVALIDATION_ERROR- Invalid request parametersRATE_LIMITED- Too many requestsSANDBOX_ONLY- Feature only available in sandbox
TypeScript Support
Full TypeScript support with strict types for all currencies:
import type {
PayInCurrency, // 21 options (fiat + crypto)
PayoutCurrency, // 107+ local rails currencies
HoldingCurrency, // 73 wallet currencies
Customer,
Quote,
Payout,
} from '@moneygraph/sdk';AI Integration
This SDK is optimized for AI coding assistants:
- Cursor: Copy
.cursor/rules/moneygraph.mdcto your project - Lovable: Paste
LOVABLE_PROMPT.mdinto Custom Knowledge - Claude.ai: Use
CLAUDE_AI_INSTRUCTIONS.mdas Project Instructions - Base44: Use
recipes/BASE44_GUIDE.mdfor app generation
Recipes
Ready-to-use implementation guides in recipes/:
| Recipe | Description |
|--------|-------------|
| supabase-edge-function.ts | Backend proxy for browser apps (handles CORS) |
| ACCEPT_PAYMENTS.md | Card payments, widget, popup checkout for merchants |
| REMITTANCE_FLOW.md | International money transfers (Sender→Recipient→Transaction) |
| BASE44_GUIDE.md | Base44 AI app generator integration |
Accept Payments (Merchants)
Initialize with your public key for client-side payments:
const mg = new MoneyGraph({
apiKey: 'sk_test_xxx', // Server-side
publicKey: 'pk_test_xxx', // Client-side payments
});Widget Embed
<script src="https://stratospay.com/embed.js"></script>
<div class="stratos-embed"></div>
<script>
checkout.init({
public_key: "pk_test_xxx",
external_reference: "order_" + Date.now(),
amount: 10000, // cents
currency: "USD",
title: "Order Payment",
description: "Payment for Order #12345",
customer: {
first_name: "John",
last_name: "Doe",
email: "[email protected]",
ip_address: "127.0.0.1"
},
billing_address: {
country: "US",
city: "Los Angeles",
address: "123 Main St",
postal_code: "90001"
},
onsuccess: (data) => console.log("Success!", data),
onerror: (data) => console.log("Error", data)
});
</script>Popup Checkout
<script src="https://stratospay.com/popup.js"></script>
<button onclick="checkout.init(config)">Pay Now</button>Direct Card Charge (Server-side)
// ⚠️ Requires PCI DSS compliance!
import { TEST_CARDS } from '@moneygraph/sdk';
const result = await mg.payments.chargeCard({
title: "Order Payment",
description: "Order #12345",
external_reference: `order_${Date.now()}`,
amount: 100,
currency: "USD",
customer: { first_name: "John", last_name: "Doe", email: "[email protected]", ip_address: "127.0.0.1" },
billing_address: { country: "US", city: "LA", address: "123 Main St", postal_code: "90001" },
card: {
card_number: TEST_CARDS.VISA_SUCCESS,
cvv: "123",
expire: "12/30"
}
});
if (result.status === 'requires_action') {
// Redirect to result.action_url for 3DS
}Test Cards
| Card | Result |
|------|--------|
| 4917484589897107 | Success |
| 5555555555554444 | Success |
| 6011000991300009 | Blocked |
| 6011111111111117 | Insufficient Funds |
| 4263982640269299 | Requires 3DS |
See recipes/ACCEPT_PAYMENTS.md for complete guide.
License
MIT
