splitpay-sdk
v2.0.0
Published
Open-source, zero-backend bill splitting SDK for Indian consumer apps
Maintainers
Readme
SplitPay
Open-source SDK for splitting payments via UPI. Drop a "split this payment" button into any Indian consumer app — checkout pages, order confirmations, group bookings — and let users collect their share from friends.
No backend required. Split data lives in the URL itself. No server, no database, no API keys.
How it works
- User taps "Split this payment" on a checkout page
- Enters their UPI ID, picks how many people to split with
- Gets a single shareable link
- Sends it via WhatsApp (or any messenger)
- Each friend opens the link, sees their share, pays via GPay/PhonePe/Paytm
Money goes directly from friend to user via UPI. SplitPay never touches the money.
Install
npm install splitpay-sdkQuick start
Two components. That's the full integration.
1. Trigger (your checkout page)
import { SplitPayTrigger } from 'splitpay-sdk'
import 'splitpay-sdk/css'
<SplitPayTrigger
amount={1497}
description="Swiggy Order #4821"
merchantName="Swiggy"
baseUrl="https://yourapp.com/pay"
/>2. Recipient page (one route in your app)
import { SplitPayRecipientPage } from 'splitpay-sdk'
import 'splitpay-sdk/css'
// Route: /pay (the page reads the URL hash automatically)
<SplitPayRecipientPage />That's it. No env vars, no backend, no config.
How the link works
The payment link encodes all split data in the URL hash fragment:
https://yourapp.com/pay#eyJ0IjoibmlraGlsQG9rYXhpcyIsImEiOjQ5OSwiZCI6IlN3aWdneSBPcmRlciJ9The hash contains a base64-encoded JSON payload with the UPI ID, amount, description, and merchant info. The recipient page decodes it client-side. Nothing is sent to any server.
Everything after # is never transmitted over HTTP — not to your server, not to CDNs, not to analytics tools.
Props
<SplitPayTrigger />
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| amount | number | Yes | Total bill amount |
| description | string | No | Order description shown in the modal |
| merchantName | string | No | Your brand name |
| merchantLogo | string | No | URL to your logo |
| baseUrl | string | No | Base URL for recipient page (defaults to current origin + /pay) |
| currency | string | No | Only 'INR' supported (default) |
| amountUnit | string | No | 'rupees' (default) or 'paise' |
| orderId | string | No | Your order ID, passed through to callbacks |
| theme | object | No | Colors, fonts, border radius |
| onSplitCreated | function | No | Called when link is generated |
| onModalOpen | function | No | Called when modal opens |
| onModalClose | function | No | Called when modal closes |
<SplitPayRecipientPage />
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| hash | string | No | Override hash for testing. Defaults to window.location.hash |
Theming
<SplitPayTrigger
theme={{
primaryColor: '#e53935',
fontFamily: 'Your Font, sans-serif',
borderRadius: '12px',
triggerText: 'Split the bill',
}}
...
/>Core functions (non-React usage)
For custom UIs or server-side link generation:
import { encodeSplitUrl, decodeSplitUrl, splitAmount, generateUpiLink } from 'splitpay-sdk/core'
const link = encodeSplitUrl({
baseUrl: 'https://yourapp.com/pay',
upiId: 'xyz@upi',
amount: 1497,
count: 3,
description: 'Dinner',
initiatorName: 'Nikhil',
})
const data = decodeSplitUrl(link)
// { upiId, perPersonAmount, totalAmount, count, description, initiatorName, ... }The core export has zero dependencies — no React, no DOM. Works in Node, Bun, or any JS runtime.
Optional: status tracking
The default SDK is fully stateless. If you want an in-app "who paid?" panel, deploy the server template from server/ to your own Vercel + Upstash Redis. See server/README.md.
Limitations
- INR only (UPI)
- Max 8 people per split
- Payment confirmation is via UPI push notification to the initiator — there is no automated server-side verification
- React 16.8+ required for components (core functions work anywhere)
License
MIT
