Platform Architecture
How ZapAPI is put together — the three product surfaces, the payment core, the AI gateway, and how data flows between them.
ZapAPI is one NestJS platform serving three product surfaces that share the same payment core, identity, and Lightning infrastructure.
Surfaces
| Surface | What it is | Key modules |
|---|---|---|
| Payments | Merchant payment gateway — invoices, payment links, webhooks, projects, API keys | invoices, payments, payment-links, webhooks, projects, api-keys, providers |
| Creator | Creator monetization — bio pages, subscriptions, tipping, lightning addresses, marketplace | bio-links, creator-plans, lightning-address, directory, marketplace, paywalls |
| AI Gateway | 500+ AI models paid per query in sats | ai (gateway, catalog sync, pricing, credits, topups, auto-topup) |
System map
Clients ── Next.js apps (dashboard / payments / creator / ai surfaces)
── Public pages (checkout, bio pages, /models catalog)
── External developers (REST API + @zapapi/sdk)
── Nostr clients (LNURL-pay, NIP-05, NIP-57)
── OpenAI-compatible AI tools (Claude Code, Cursor, SDKs)
│
▼
┌────────────────────────────────────────────────────────┐
│ ZapAPI Server (NestJS) │
│ │
│ Identity & access Payment core AI gateway │
│ ─ auth, RBAC ─ invoices ─ model sync │
│ ─ API keys ─ payments ─ pricing │
│ ─ projects ─ payment links ─ credits │
│ ─ plans/quotas ─ webhooks ─ topups │
│ ─ providers ─ auto-topup │
│ ─ fx │
│ │
│ Lightning layer Data Realtime │
│ ─ LNbits adapter ─ PostgreSQL ─ Redis/Bull │
│ ─ NWC adapters ─ TypeORM ─ SSE/WS │
│ ─ LNURL service ─ migrations ─ cron sweeps │
└────────────┬─────────────────────┬─────────────────────┘
│ │
┌─────────▼────────┐ ┌─────────▼─────────┐
│ Lightning infra │ │ External services │
│ ─ LNbits server │ │ ─ OpenRouter │
│ ─ Nostr relays │ │ ─ CoinGecko (FX) │
│ ─ NWC wallets │ │ ─ Stripe (fiat) │
└───────────────────┘ └────────────────────┘The payment core (shared)
Every surface settles through the same Lightning layer:
- LNbits adapter — invoice creation (BOLT11), payment verification, wallet provisioning. Platform wallets and per-user wallets both live here.
- Invoices module — the invoice of record: amounts, status transitions (pending → paid/expired), FX snapshots for fiat-denominated invoices, overpayment tracking, idempotent settlement (CAS transitions so webhook and poller can't double-settle).
- Webhooks — Stripe-style HMAC-signed events with retries and delivery logs, for both inbound (provider → us) and outbound (us → merchants).
- FX service — CoinGecko rates, 60s cache with stale-while-error, used for fiat invoices and the AI sats conversion.
The AI gateway flow
AI request (chat completion)
→ auth (zap_* key or JWT)
→ model resolution (catalog row by id; suffixes stripped for pricing)
→ pre-flight balance check (402 with required_sats if short)
→ OpenRouter (single upstream; key in server env only)
→ stream through to client (SSE) or buffer
→ settle: actual usage × listed price → sats at live FX + buffer
→ ledger row: tokens, per-component sats, FX rate, marginThe model catalog syncs from upstream on a schedule — new models appear and retired models deactivate automatically. Prices re-markup on every sync; the markup is configuration, not code. Deactivation is guarded so a bad upstream read can never wipe the catalog.
Creator & identity flow
Lightning addresses and Nostr identity share one path: a claimed address
serves LNURL-pay (LUD-06/12/16), NIP-05 (/.well-known/nostr.json), and
NIP-57 zap receipts. Inbound payments settle to the owner's wallet;
outbound zaps publish kind-9735 receipts to relays. Creator plans bill
supporters through NWC pull-subscriptions.
Data & realtime
- PostgreSQL + TypeORM — one database; migrations are the only schema authority (no silent sync in production).
- Redis + Bull — webhook delivery queues and background jobs.
- Cron sweeps — one central endpoint fans out to every periodic task: payment reconciliation, AI model catalog sync, AI auto-topups, session and log cleanup. On serverless, Vercel Cron hits the same endpoint.
Security posture
- Provider and wallet credentials are AES-256-CBC encrypted at rest
(
ENCRYPTION_KEYrequired in production). - API keys stored as SHA-256 hashes; the full key is shown once at creation.
- The AI upstream key lives only in server environment — never in the DB, never sent to clients.
- Every secret class has a documented rotation path (see Security & Compliance).