UNPKG

@moneygraph/sdk

Version:

AI-native SDK for global payouts powered by StratosPay

419 lines (343 loc) 10.7 kB
# @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 ```bash npm install @moneygraph/sdk # or yarn add @moneygraph/sdk # or pnpm add @moneygraph/sdk ``` ## Quick Start ```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' ``` ## Complete Payout Flow ### 1. Create a Customer ```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', }, }, }); ``` ### 2. Complete KYC ```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' } ``` ### 3. Get FX Quote ```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`); ``` ### 4. Confirm Quote & Send Payout ```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', }, }); ``` ### 5. Track Payout Status ```typescript const status = await mg.payouts.getStatus(payout.id); console.log(status.status); // 'pending' -> 'processing' -> 'completed' ``` ## Business Directors (for Business Accounts) ```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); ``` ## Reference Data ```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'); ``` ## Sandbox Testing 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 ## Error Handling ```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 ## TypeScript Support 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'; ``` ## 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: ```typescript const mg = new MoneyGraph({ apiKey: 'sk_test_xxx', // Server-side publicKey: 'pk_test_xxx', // Client-side payments }); ``` ### Widget Embed ```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> ``` ### Popup Checkout ```html <script src="https://stratospay.com/popup.js"></script> <button onclick="checkout.init(config)">Pay Now</button> ``` ### Direct Card Charge (Server-side) ```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 } ``` ### 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