Skip to content

Latest commit

 

History

History
660 lines (586 loc) · 17.1 KB

File metadata and controls

660 lines (586 loc) · 17.1 KB

External accounts are bank accounts, cryptocurrency wallets, or payment destinations outside Grid where you can send funds. Grid supports two types:

  • Customer external accounts - Scoped to individual customers, used for withdrawals and customer-specific payouts
  • Platform external accounts - Scoped to your platform, used for platform-wide operations like receiving funds from external sources
Customer external accounts often require some basic beneficiary information for compliance. Platform accounts are managed at the organization level.

Create external accounts by region or wallet

**ACH, Wire, RTP**
curl -X POST 'https://api.lightspark.com/grid/2025-10-13/customers/external-accounts' \
  -H 'Authorization: Basic $GRID_CLIENT_ID:$GRID_CLIENT_SECRET' \
  -H 'Content-Type: application/json' \
  -d '{
    "currency": "USD",
    "platformAccountId": "user_123_primary_bank",
    "accountInfo": {
      "accountType": "US_ACCOUNT",
      "accountNumber": "123456789",
      "routingNumber": "021000021",
      "accountCategory": "CHECKING",
      "bankName": "Chase Bank",
      "beneficiary": {
        "beneficiaryType": "INDIVIDUAL",
        "fullName": "John Doe",
        "birthDate": "1990-01-15",
        "nationality": "US",
        "address": {
          "line1": "123 Main Street",
          "city": "San Francisco",
          "state": "CA",
          "postalCode": "94105",
          "country": "US"
        }
      }
    }
  }'
Category must be `CHECKING` or `SAVINGS`. Routing number must be 9 digits. **CLABE/SPEI**
curl -X POST 'https://api.lightspark.com/grid/2025-10-13/customers/external-accounts' \
  -H 'Authorization: Basic $GRID_CLIENT_ID:$GRID_CLIENT_SECRET' \
  -H 'Content-Type: application/json' \
  -d '{
    "currency": "MXN",
    "platformAccountId": "mx_beneficiary_001",
    "accountInfo": {
      "accountType": "CLABE",
      "clabeNumber": "123456789012345678",
      "bankName": "BBVA Mexico",
      "beneficiary": {
        "beneficiaryType": "INDIVIDUAL",
        "fullName": "María García",
        "birthDate": "1985-03-15",
        "nationality": "MX",
        "address": {
          "line1": "Av. Reforma 123",
          "city": "Ciudad de México",
          "state": "CDMX",
          "postalCode": "06600",
          "country": "MX"
        }
      }
    }
  }'
**PIX**
curl -X POST 'https://api.lightspark.com/grid/2025-10-13/customers/external-accounts' \
  -H 'Authorization: Basic $GRID_CLIENT_ID:$GRID_CLIENT_SECRET' \
  -H 'Content-Type: application/json' \
  -d '{
    "currency": "BRL",
    "platformAccountId": "br_pix_001",
    "accountInfo": {
      "accountType": "PIX",
      "pixKey": "user@email.com",
      "pixKeyType": "EMAIL",
      "bankName": "Nubank",
      "beneficiary": {
        "beneficiaryType": "INDIVIDUAL",
        "fullName": "João Silva",
        "birthDate": "1988-07-22",
        "nationality": "BR",
        "address": {
          "line1": "Rua das Flores 456",
          "city": "São Paulo",
          "state": "SP",
          "postalCode": "01234-567",
          "country": "BR"
        }
      }
    }
  }'

Key types: CPF, CNPJ, EMAIL, PHONE, or RANDOM

**IBAN/SEPA**
curl -X POST 'https://api.lightspark.com/grid/2025-10-13/customers/external-accounts' \
  -H 'Authorization: Basic $GRID_CLIENT_ID:$GRID_CLIENT_SECRET' \
  -H 'Content-Type: application/json' \
  -d '{
    "currency": "EUR",
    "platformAccountId": "eu_iban_001",
    "accountInfo": {
      "accountType": "IBAN",
      "iban": "DE89370400440532013000",
      "swiftBic": "DEUTDEFF",
      "bankName": "Deutsche Bank",
      "beneficiary": {
        "beneficiaryType": "INDIVIDUAL",
        "fullName": "Hans Schmidt",
        "birthDate": "1982-11-08",
        "nationality": "DE",
        "address": {
          "line1": "Hauptstraße 789",
          "city": "Berlin",
          "state": "Berlin",
          "postalCode": "10115",
          "country": "DE"
        }
      }
    }
  }'
**UPI**
curl -X POST 'https://api.lightspark.com/grid/2025-10-13/customers/external-accounts' \
  -H 'Authorization: Basic $GRID_CLIENT_ID:$GRID_CLIENT_SECRET' \
  -H 'Content-Type: application/json' \
  -d '{
    "currency": "INR",
    "platformAccountId": "in_upi_001",
    "accountInfo": {
      "accountType": "UPI",
      "vpa": "user@okbank",
      "beneficiary": {
        "beneficiaryType": "INDIVIDUAL",
        "fullName": "Priya Sharma",
        "birthDate": "1991-05-14",
        "nationality": "IN",
        "address": {
          "line1": "123 MG Road",
          "city": "Mumbai",
          "state": "Maharashtra",
          "postalCode": "400001",
          "country": "IN"
        }
      }
    }
  }'
**NGN Bank Transfer**
curl -X POST 'https://api.lightspark.com/grid/2025-10-13/customers/external-accounts' \
  -H 'Authorization: Basic $GRID_CLIENT_ID:$GRID_CLIENT_SECRET' \
  -H 'Content-Type: application/json' \
  -d '{
    "currency": "NGN",
    "platformAccountId": "ng_bank_001",
    "accountInfo": {
      "accountType": "NGN_ACCOUNT",
      "accountNumber": "0123456789",
      "bankName": "First Bank of Nigeria",
      "beneficiary": {
        "beneficiaryType": "INDIVIDUAL",
        "fullName": "Chukwuemeka Okonkwo",
        "birthDate": "1990-06-20",
        "nationality": "NG",
        "address": {
          "line1": "15 Marina Street",
          "city": "Lagos",
          "state": "Lagos",
          "postalCode": "100001",
          "country": "NG"
        }
      }
    }
  }'
Account number must be exactly 10 digits. **ZAR Bank Transfer**
curl -X POST 'https://api.lightspark.com/grid/2025-10-13/customers/external-accounts' \
  -H 'Authorization: Basic $GRID_CLIENT_ID:$GRID_CLIENT_SECRET' \
  -H 'Content-Type: application/json' \
  -d '{
    "currency": "ZAR",
    "platformAccountId": "za_bank_001",
    "accountInfo": {
      "accountType": "ZAR_ACCOUNT",
      "accountNumber": "1234567890",
      "bankName": "Standard Bank",
      "beneficiary": {
        "beneficiaryType": "INDIVIDUAL",
        "fullName": "Thabo Mbeki",
        "birthDate": "1985-04-12",
        "nationality": "ZA",
        "address": {
          "line1": "42 Nelson Mandela Drive",
          "city": "Johannesburg",
          "state": "Gauteng",
          "postalCode": "2000",
          "country": "ZA"
        }
      }
    }
  }'
Account number must be 9-13 digits. **KES Mobile Money (M-PESA)**
curl -X POST 'https://api.lightspark.com/grid/2025-10-13/customers/external-accounts' \
  -H 'Authorization: Basic $GRID_CLIENT_ID:$GRID_CLIENT_SECRET' \
  -H 'Content-Type: application/json' \
  -d '{
    "currency": "KES",
    "platformAccountId": "ke_mpesa_001",
    "accountInfo": {
      "accountType": "KES_ACCOUNT",
      "phoneNumber": "+254712345678",
      "provider": "M-PESA",
      "beneficiary": {
        "beneficiaryType": "INDIVIDUAL",
        "fullName": "Wanjiku Kamau",
        "birthDate": "1990-08-20",
        "nationality": "KE",
        "address": {
          "line1": "Kenyatta Avenue 15",
          "city": "Nairobi",
          "postalCode": "00100",
          "country": "KE"
        }
      }
    }
  }'
Phone number must be in format `+254XXXXXXXXX` (9 digits after country code). Provider must be `M-PESA`. **TZS Mobile Money**
curl -X POST 'https://api.lightspark.com/grid/2025-10-13/customers/external-accounts' \
  -H 'Authorization: Basic $GRID_CLIENT_ID:$GRID_CLIENT_SECRET' \
  -H 'Content-Type: application/json' \
  -d '{
    "currency": "TZS",
    "platformAccountId": "tz_mobile_001",
    "accountInfo": {
      "accountType": "TZS_ACCOUNT",
      "phoneNumber": "+255712345678",
      "provider": "VODACOM",
      "beneficiary": {
        "beneficiaryType": "INDIVIDUAL",
        "fullName": "Juma Hassan",
        "birthDate": "1988-02-14",
        "nationality": "TZ",
        "address": {
          "line1": "Samora Avenue 28",
          "city": "Dar es Salaam",
          "postalCode": "11101",
          "country": "TZ"
        }
      }
    }
  }'
Phone number must be in format `+255XXXXXXXXX` (9 digits after country code). Providers: `AIRTEL` or `VODACOM`. **ZMW Mobile Money**
curl -X POST 'https://api.lightspark.com/grid/2025-10-13/customers/external-accounts' \
  -H 'Authorization: Basic $GRID_CLIENT_ID:$GRID_CLIENT_SECRET' \
  -H 'Content-Type: application/json' \
  -d '{
    "currency": "ZMW",
    "platformAccountId": "zm_mobile_001",
    "accountInfo": {
      "accountType": "ZMW_ACCOUNT",
      "phoneNumber": "+260971234567",
      "provider": "MTN",
      "beneficiary": {
        "beneficiaryType": "INDIVIDUAL",
        "fullName": "Mwila Chanda",
        "birthDate": "1992-11-05",
        "nationality": "ZM",
        "address": {
          "line1": "Cairo Road 100",
          "city": "Lusaka",
          "postalCode": "10101",
          "country": "ZM"
        }
      }
    }
  }'
Phone number must be in format `+260XXXXXXXXX` (9 digits after country code). Providers: `TNM`, `AIRTEL`, `ZAMTEL`, or `MTN`. **RWF Mobile Money**
curl -X POST 'https://api.lightspark.com/grid/2025-10-13/customers/external-accounts' \
  -H 'Authorization: Basic $GRID_CLIENT_ID:$GRID_CLIENT_SECRET' \
  -H 'Content-Type: application/json' \
  -d '{
    "currency": "RWF",
    "platformAccountId": "rw_mobile_001",
    "accountInfo": {
      "accountType": "RWF_ACCOUNT",
      "phoneNumber": "+250781234567",
      "provider": "MTN",
      "beneficiary": {
        "beneficiaryType": "INDIVIDUAL",
        "fullName": "Uwimana Diane",
        "birthDate": "1995-06-30",
        "nationality": "RW",
        "address": {
          "line1": "KN 5 Avenue",
          "city": "Kigali",
          "postalCode": "00100",
          "country": "RW"
        }
      }
    }
  }'
Phone number must be in format `+250XXXXXXXXX` (9 digits after country code). Providers: `MTN` or `AIRTEL`. **CAD Bank Transfer**
curl -X POST 'https://api.lightspark.com/grid/2025-10-13/customers/external-accounts' \
  -H 'Authorization: Basic $GRID_CLIENT_ID:$GRID_CLIENT_SECRET' \
  -H 'Content-Type: application/json' \
  -d '{
    "currency": "CAD",
    "platformAccountId": "ca_bank_001",
    "accountInfo": {
      "accountType": "CAD_ACCOUNT",
      "bankCode": "001",
      "branchCode": "00012",
      "accountNumber": "1234567",
      "beneficiary": {
        "beneficiaryType": "INDIVIDUAL",
        "fullName": "Emily Thompson",
        "birthDate": "1988-09-12",
        "nationality": "CA",
        "address": {
          "line1": "456 Queen Street West",
          "city": "Toronto",
          "state": "ON",
          "postalCode": "M5V 2B3",
          "country": "CA"
        }
      }
    }
  }'
Bank code is 3 digits, branch code is 5 digits, account number is 7-12 digits. **Bitcoin Lightning (Spark Wallet)**
curl -X POST 'https://api.lightspark.com/grid/2025-10-13/customers/external-accounts' \
  -H 'Authorization: Basic $GRID_CLIENT_ID:$GRID_CLIENT_SECRET' \
  -H 'Content-Type: application/json' \
  -d '{
    "currency": "BTC",
    "platformAccountId": "btc_spark_001",
    "accountInfo": {
      "accountType": "SPARK_WALLET",
      "address": "spark1pgssyuuuhnrrdjswal5c3s3rafw9w3y5dd4cjy3duxlf7hjzkp0rqx6dj6mrhu"
    }
  }'
Spark wallets don't require beneficiary information as they are self-custody wallets. **Ethereum L1 (USDC)**
curl -X POST 'https://api.lightspark.com/grid/2025-10-13/customers/external-accounts' \
  -H 'Authorization: Basic $GRID_CLIENT_ID:$GRID_CLIENT_SECRET' \
  -H 'Content-Type: application/json' \
  -d '{
    "currency": "USDC",
    "platformAccountId": "usdc_eth_001",
    "accountInfo": {
      "accountType": "ETHEREUM_WALLET",
      "address": "0xAbCDEF1234567890aBCdEf1234567890ABcDef12"
    }
  }'
Ethereum wallets support USDC on Ethereum L1. No beneficiary information required. Use `platformAccountId` to tie your internal id with the external account.

Sample Response:

{
  "id": "ExternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965",
  "customerId": "Customer:019542f5-b3e7-1d02-0000-000000000001",
  "status": "ACTIVE",
  "currency": "USD",
  "platformAccountId": "user_123_primary_bank",
  "accountInfo": {
    "accountType": "US_ACCOUNT",
    "accountNumber": "123456789",
    "routingNumber": "021000021",
    "accountCategory": "CHECKING",
    "bankName": "Chase Bank",
    "beneficiary": {
      "beneficiaryType": "INDIVIDUAL",
      "fullName": "John Doe",
      "birthDate": "1990-01-15",
      "nationality": "US",
      "address": {
        "line1": "123 Main Street",
        "city": "San Francisco",
        "state": "CA",
        "postalCode": "94105",
        "country": "US"
      }
    }
  }
}

Business beneficiaries

For business accounts, include business information:

{
  "currency": "USD",
  "platformAccountId": "acme_corp_account",
  "customerId": "Customer:019542f5-b3e7-1d02-0000-000000000001",
  "accountInfo": {
    "accountType": "US_ACCOUNT",
    "accountNumber": "987654321",
    "routingNumber": "021000021",
    "accountCategory": "CHECKING",
    "bankName": "Chase Bank",
    "beneficiary": {
      "beneficiaryType": "BUSINESS",
      "businessInfo": {
        "legalName": "Acme Corporation, Inc.",
        "taxId": "EIN-987654321"
      },
      "address": {
        "line1": "456 Business Ave",
        "city": "New York",
        "state": "NY",
        "postalCode": "10001",
        "country": "US"
      }
    }
  }
}

Account status

Beneficiary data may be reviewed for risk and compliance. Only ACTIVE accounts can receive payments. Updates to account data may trigger account re-review.

Status Description
PENDING Created, awaiting verification
ACTIVE Verified and ready for transactions
UNDER_REVIEW Additional review required
INACTIVE Disabled, cannot be used

Listing external accounts

List customer accounts

curl -X GET 'https://api.lightspark.com/grid/2025-10-13/customers/external-accounts?customerId=Customer:019542f5-b3e7-1d02-0000-000000000001' \
  -H 'Authorization: Basic $GRID_CLIENT_ID:$GRID_CLIENT_SECRET'

List platform accounts

For platform-wide operations, list all platform-level external accounts:

curl -X GET 'https://api.lightspark.com/grid/2025-10-13/platform/external-accounts' \
  -H 'Authorization: Basic $GRID_CLIENT_ID:$GRID_CLIENT_SECRET'
Platform external accounts are used for platform-wide operations like depositing funds from external sources.

Best practices

Validate account details before submission:
// US accounts: 9-digit routing, 4-17 digit account number
if (!/^\d{9}$/.test(routingNumber)) {
  throw new Error("Invalid routing number");
}

// CLABE: exactly 18 digits
if (!/^\d{18}$/.test(clabeNumber)) {
  throw new Error("Invalid CLABE number");
}

// NGN: exactly 10-digit account number
if (!/^\d{10}$/.test(ngnAccountNumber)) {
  throw new Error("Invalid Nigerian account number");
}

// CAD: 3-digit bank code, 5-digit branch code, 7-12 digit account number
if (!/^\d{3}$/.test(bankCode)) {
  throw new Error("Invalid bank code");
}
if (!/^\d{5}$/.test(branchCode)) {
  throw new Error("Invalid branch code");
}
if (!/^\d{7,12}$/.test(cadAccountNumber)) {
  throw new Error("Invalid Canadian account number");
}

// ZAR: 9-13 digit account number
if (!/^\d{9,13}$/.test(zarAccountNumber)) {
  throw new Error("Invalid South African account number");
}

// African mobile money phone numbers
if (!/^\+254\d{9}$/.test(kesPhoneNumber)) {
  throw new Error("Invalid Kenyan phone number");
}
if (!/^\+255\d{9}$/.test(tzsPhoneNumber)) {
  throw new Error("Invalid Tanzanian phone number");
}
if (!/^\+260\d{9}$/.test(zmwPhoneNumber)) {
  throw new Error("Invalid Zambian phone number");
}
if (!/^\+250\d{9}$/.test(rwfPhoneNumber)) {
  throw new Error("Invalid Rwandan phone number");
}
Verify status before sending payments:
if (account.status !== "ACTIVE") {
  throw new Error(`Account is ${account.status}, cannot process payment`);
}
Never expose full account numbers. Display only masked info:
function displaySafely(account) {
  return {
    id: account.id,
    bankName: account.accountInfo.bankName,
    lastFour: account.accountInfo.accountNumber.slice(-4),
    status: account.status,
  };
}