Accept Stellar payments (XLM or Stellar assets like USDC) using simple payment links and a developer-friendly API.
This project aims to feel like Stripe/PayPal, but built on Stellar. Merchants create a payment, share a link or QR code, and the API confirms the on-chain payment and notifies the merchant.
- Create payment intents with an amount, asset, and recipient
- Generate a payment link (ready for QR code usage)
- Verify payments on Stellar via Horizon
- Track status in Supabase (pending → confirmed)
- Send webhook notifications when payments are confirmed
- Backend: Node.js + Express
- Database: Supabase (Postgres)
- Stellar:
stellar-sdk+ Horizon API - Frontend: Next.js + Tailwind (starter shell in
frontend/)
- Node.js 20+
- Redis (required for backend rate limiting)
- Supabase project (URL, service role key, and Postgres connection string)
- Install dependencies:
cd backend
npm install- Configure environment:
cp .env.example .envIf you skip this, backend startup validation fails and prints missing required keys.
Optional: bring up Redis quickly with Docker:
docker run --name stellar-redis -p 6379:6379 redis:7-alpineOr install Redis locally (example with Homebrew):
brew install redis
brew services start redis- Fill out
backend/.env:
SUPABASE_URL=your_supabase_url
SUPABASE_SERVICE_ROLE_KEY=your_service_role_key
DATABASE_URL=your_supabase_transaction_pooler_uri
REDIS_URL=redis://localhost:6379
STELLAR_NETWORK=testnet
# Optional overrides:
STELLAR_HORIZON_URL=
USDC_ISSUER=your_usdc_issuer
PAYMENT_LINK_BASE=http://localhost:3000
CREATE_PAYMENT_RATE_LIMIT_MAX=50
CREATE_PAYMENT_RATE_LIMIT_WINDOW_MS=60000
- Apply schema in Supabase:
- Use
backend/sql/schema.sqlin Supabase SQL editor.
- Run the API:
npm run devOr start Redis + API together from the backend folder:
docker compose upAPI will be available at http://localhost:4000.
Rate limiting uses Redis-backed shared state, so multiple API instances behind a load balancer enforce the same counters.
Generate a static OpenAPI asset for SDK generation or external docs:
cd backend
npm run build:docsThis writes backend/public/openapi.json.
Verify the XLM -> USDC path-payment flow on Stellar testnet without a wallet:
cd backend
npm run verify:path-payment:testnetThis script creates disposable testnet accounts, issues a temporary USDC asset, places a DEX offer, discovers the best XLM -> USDC path, submits a live path_payment_strict_receive, and prints the transaction hash plus the recipient's received USDC amount.
GET /healthPOST /api/create-paymentPOST /api/sessionsGET /api/payment-status/:idPOST /api/verify-payment/:idGET /api/merchant-brandingPUT /api/merchant-branding
{
"amount": 50,
"asset": "USDC",
"asset_issuer": "G...ISSUER",
"recipient": "G...RECIPIENT",
"description": "Digital product",
"webhook_url": "https://merchant.app/webhooks/stellar",
"branding_overrides": {
"primary_color": "#5ef2c0",
"secondary_color": "#b8ffe2",
"background_color": "#050608"
}
}POST /api/create-payment and POST /api/sessions are rate-limited per API key. By default the backend allows 50 requests per 60 seconds and returns 429 Too Many Requests with a Retry-After header when the limit is exceeded.
Both endpoints return branding_config in the response. The config is resolved in this order:
- per-session
branding_overrides - merchant
branding_config - system defaults
POST /api/verify-payment/:id checks Horizon for a matching payment and, if found, marks it as confirmed and fires a webhook.
Webhook payload:
{
"event": "payment.confirmed",
"payment_id": "...",
"amount": 50,
"asset": "USDC",
"asset_issuer": "G...ISSUER",
"recipient": "G...RECIPIENT",
"tx_id": "..."
}The project currently has a comprehensive roadmap of 100+ active issues covering:
- Core Stellar Integrations: SEP-0001, SEP-0010, Path Payments, etc.
- Backend Architecture: Service layer refactor, Redis idempotency, API versioning.
- Frontend/UX: Merchant branding, real-time checkout, dashboard analytics.
- Security & Reliability: Webhook signatures, rate limiting, audit logs.
- Infrastructure: Sentry monitoring, Prometheus metrics, database archival.
We are actively seeking contributors! See the GitHub Issues to get started. Each issue is tagged with complexity (complexity:trivial, complexity:medium, complexity:high) and category.
If you are new, look for issues labeled good first issue.