@moneygraph/sdk
Version:
AI-native SDK for global payouts powered by StratosPay
419 lines (343 loc) • 10.7 kB
Markdown
AI-native SDK for global payouts powered by StratosPay. Send money to 107+ countries with automatic FX, KYC enforcement, and developer-friendly APIs.
- 🌍 **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
```bash
npm install @moneygraph/sdk
yarn add @moneygraph/sdk
pnpm add @moneygraph/sdk
```
```typescript
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'
```
```typescript
// Personal account
const customer = await mg.onboard.createCustomer({
account_type: 'personal',
first_name: 'John',
last_name: 'Doe',
email: 'john@example.com',
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: 'jane@company.com',
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',
},
},
});
```
```typescript
// 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' }
```
```typescript
// 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`);
```
```typescript
// 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',
},
});
```
```typescript
const status = await mg.payouts.getStatus(payout.id);
console.log(status.status); // 'pending' -> 'processing' -> 'completed'
```
```typescript
// Add a director
const director = await mg.onboard.createDirector(business.id, {
first_name: 'Michael',
last_name: 'Johnson',
email: 'michael@company.com',
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);
```
```typescript
// 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');
```
Use `sk_test_*` API keys to enable sandbox mode with full mock data:
```typescript
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 directors
- `individual_verified` - Approved personal account
- `pending_kyc` - Account awaiting KYC approval
- `rejected_kyc` - Account with rejected KYC
```typescript
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 invalid
- `UNAUTHORIZED` - Not authorized for this action
- `KYC_PENDING` - KYC verification pending
- `KYC_REJECTED` - KYC verification rejected
- `KYC_ALREADY_APPROVED` - Cannot update approved KYC
- `QUOTE_EXPIRED` - FX quote has expired
- `QUOTE_NOT_FOUND` - Quote ID not found
- `CUSTOMER_NOT_FOUND` - Customer ID not found
- `DIRECTOR_NOT_FOUND` - Director ID not found
- `VALIDATION_ERROR` - Invalid request parameters
- `RATE_LIMITED` - Too many requests
- `SANDBOX_ONLY` - Feature only available in sandbox
Full TypeScript support with strict types for all currencies:
```typescript
import type {
PayInCurrency, // 21 options (fiat + crypto)
PayoutCurrency, // 107+ local rails currencies
HoldingCurrency, // 73 wallet currencies
Customer,
Quote,
Payout,
} from '@moneygraph/sdk';
```
This SDK is optimized for AI coding assistants:
- **Cursor**: Copy `.cursor/rules/moneygraph.mdc` to your project
- **Lovable**: Paste `LOVABLE_PROMPT.md` into Custom Knowledge
- **Claude.ai**: Use `CLAUDE_AI_INSTRUCTIONS.md` as Project Instructions
- **Base44**: Use `recipes/BASE44_GUIDE.md` for app generation
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:
```typescript
const mg = new MoneyGraph({
apiKey: 'sk_test_xxx', // Server-side
publicKey: 'pk_test_xxx', // Client-side payments
});
```
```html
<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: "john@example.com",
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>
```
```html
<script src="https://stratospay.com/popup.js"></script>
<button onclick="checkout.init(config)">Pay Now</button>
```
```typescript
// ⚠️ 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: "john@example.com", 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
}
```
| Card | Result |
|------|--------|
| `4917484589897107` | Success |
| `5555555555554444` | Success |
| `6011000991300009` | Blocked |
| `6011111111111117` | Insufficient Funds |
| `4263982640269299` | Requires 3DS |
See `recipes/ACCEPT_PAYMENTS.md` for complete guide.
MIT