JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 7
  • Score
    100M100P100Q59051F
  • License MIT

AI-native SDK for global payouts powered by StratosPay

Package Exports

  • @moneygraph/sdk
  • @moneygraph/sdk/types

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/sdk

Quick 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: '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',
    },
  },
});

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: '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);

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 directors
  • individual_verified - Approved personal account
  • pending_kyc - Account awaiting KYC approval
  • rejected_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 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

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.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

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: "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>
<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: "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
}

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