ZapAPI Docs
Get StartedConceptsAI GatewayGuidesPayment GatewaySDKAPI ReferenceResources

TypeScript SDK

Official @zapapi/sdk package — typed access to every ZapAPI API: payments, wallets, addresses, marketplace, and the AI gateway. Zero dependencies.

The official ZapAPI SDK is the fastest way to integrate. It's a zero-dependency TypeScript client that wraps the whole REST API with full types, idempotency-key support, streaming AI completions, and built-in webhook signature verification. Works in Node 18+, Deno, Bun, and modern browsers.

Install

Install the SDK
npm install @zapapi/sdk

Works in Node 18+, Deno, Bun, and modern browsers. TypeScript types are included — no @types/* package needed.

Quick start

charge.ts
import { ZapAPI } from '@zapapi/sdk';

const zap = new ZapAPI(process.env.ZAPAPI_KEY); // zap_live_… or zap_test_…

// Create an invoice (BOLT11) — settles to the project's settlement wallet.
// With a project-scoped key (Dashboard → Project → API Keys), the API key
// is all you need — no projectId, no providerId.
const invoice = await zap.invoices.create(
  {
    amount: 21000,
    description: 'Pro plan',
  },
  'unique-idempotency-key', // safe retries — never double-charge
);

console.log(invoice.paymentRequest); // lnbc210n1…

Where do the sats land?

Every project has a settlement wallet (Dashboard → Project → Settlement Wallet): your default wallet, a dedicated project wallet, an account wallet, or your own external wallet via NWC. Invoices always settle there — you never pass a provider id. With an account-level key, pass projectId: 'proj_…' explicitly.

You can also pass a config object for full control:

Custom config
const zap = new ZapAPI({
  apiKey: process.env.ZAPAPI_KEY,
  baseUrl: 'https://api.zapapi.com/v1', // override for self-hosted
  timeoutMs: 30_000,
  fetchFn: myFetch, // custom fetch (older Node, proxies, testing)
});

Test mode

Keys starting with zap_test_ create test invoices. Webhook events carry livemode: false, and the client exposes a convenience flag:

const zap = new ZapAPI('zap_test_…');
zap.isTestMode; // true

Fiat-denominated invoices

Pass a fiat currency and the invoice is converted to sats at the current rate. The rate is snapshotted on the invoice for audit:

const invoice = await zap.invoices.create({
  amount: 25, // $25
  currency: 'USD',
  description: 'Pro plan',
});

console.log(invoice.amount);   // 30684 (sats)
console.log(invoice.fiatRate); // 81476.00 (USD/BTC at creation)

Supported fiat codes: USD, EUR, GBP, INR, BRL, JPY, CAD, AUD.

Idempotency

All POST endpoints accept an Idempotency-Key. Retrying with the same key returns the same response — payments are never double-created:

await zap.invoices.create(params, `order-${orderId}`);

If a request with the same key but a different body is replayed, the API returns 409 Conflict (err.isConflict on the typed error).

Resources

Invoices

const invoice = await zap.invoices.create(params, idempotencyKey?);
const one = await zap.invoices.get(id);
const { invoices, total } = await zap.invoices.list({ projectId, status, limit, offset });
const fresh = await zap.invoices.checkStatus(id);   // poll the settlement wallet
const cancelled = await zap.invoices.cancel(id);    // pending invoices only
const { qrCode } = await zap.invoices.getQRCode(id); // data URL for <img>

Refunds

// Full repayment to the customer's lightning address
const refund = await zap.refunds.create(invoice.id, {
  destination: 'customer@wallet.com',
  reason: 'Customer requested cancellation',
});

// Partial repayment
await zap.refunds.create(invoice.id, { destination: '…', amountSats: 5000 });

// Credit note (record only — settle off-band)
await zap.refunds.create(invoice.id, { type: 'credit', amountSats: 5000 });

const forInvoice = await zap.refunds.listForInvoice(invoice.id);
const { refunds, total } = await zap.refunds.list({ limit: 50 });
const link = await zap.paymentLinks.create({
  description: 'Tip jar ☕',
  type: 'flexible',
  minAmount: 21,
  maxAmount: 100000,
});
// share link.paymentUrl — QR via zap.paymentLinks.getQRCode(link.id)

await zap.paymentLinks.updateStatus(link.id, 'disabled');
const all = await zap.paymentLinks.list();
await zap.paymentLinks.delete(link.id);

Customers (CRM)

// Project customers — auto-built from settled invoices/payment links
const { customers } = await zap.customers.list({ projectId: 'proj_…', segment: 'vip' });
const customer = await zap.customers.get(id);
const stats = await zap.customers.stats('proj_…');
const top = await zap.customers.leaderboard(10);

Subscription plans (recurring billing)

// Create a plan on a project — renewals settle to the settlement wallet
const plan = await zap.plans.create({
  name: 'Pro',
  amountSats: 21000,
  interval: 'month',   // 'week' | 'month' | 'year'
  trialDays: 7,
  perks: ['Priority support'],
});
// Hosted checkout: https://zapapi.app/subscribe/<plan.id>
// Subscribers get a magic-link portal (pause / cancel / NWC auto-pay);
// failed renewals get a 3-day grace → past_due → cancel after 7 days.

const { subscriptions, total } = await zap.subscriptions.list({ status: 'active' });
const { mrrSats, arrSats, activeSubscribers } = await zap.subscriptions.revenue();
await zap.subscriptions.cancel(subscriptionId);

Discounts (coupons & offers)

// Coupon — the customer enters the code at checkout
await zap.discounts.create({
  projectId: 'proj_…',
  code: 'LAUNCH20',
  type: 'percent',     // or 'amount' (fixed sats off)
  percentOff: 20,
  maxRedemptions: 100, // optional cap
});

// Offer — auto-applied at checkout in its window, no code needed
await zap.discounts.create({
  projectId: 'proj_…',
  mode: 'offer',
  code: 'LAUNCH-WEEK',
  type: 'percent',
  percentOff: 15,
  endsAt: '2026-11-04T00:00:00Z',
});

// The payer pays amount − discount; the discount is snapshotted on the invoice
const invoice = await zap.invoices.create({
  amount: 21000,
  description: 'Pro plan',
  couponCode: 'LAUNCH20',
});

Gift cards

// Sell a card — the buyer pays now into your settlement wallet;
// the card activates on settlement
const { card, purchase } = await zap.giftCards.issue({
  balanceSats: 21000,
  issueType: 'paid',   // or 'free' (merchant-funded comp cards)
});

// The recipient redeems real sats into their own wallet
// (public — the code is the capability)
const { lnurl, remainingSats } = await zap.giftCards.redeem(card.code, 21000);
// → show lnurl as a QR; their wallet pulls the sats (LNURL-withdraw)

Webhook endpoints

const endpoint = await zap.webhookEndpoints.create({
  url: 'https://api.yourapp.com/hooks/zapapi',
  events: ['invoice.paid', 'zap.received'],
  projectId: 'proj_…',
});
// ⚠️ endpoint.secret is returned EXACTLY ONCE — store it for verification

const all = await zap.webhookEndpoints.list({ projectId: 'proj_…' });
await zap.webhookEndpoints.updateStatus(endpoint.id, 'disabled');
await zap.webhookEndpoints.delete(endpoint.id);

Webhooks

ZapAPI signs every delivery with a Stripe-style t=,v1= scheme. Verify using the raw request body (not the parsed JSON) and the signing secret shown once when you created the endpoint:

Express webhook handler
import express from 'express';
import { ZapAPI } from '@zapapi/sdk';

const app = express();

app.post(
  '/webhooks/zapapi',
  express.raw({ type: 'application/json' }),
  (req, res) => {
    const ok = ZapAPI.webhooks.verify(
      req.body.toString(),
      req.headers['x-zapapi-signature'] as string,
      process.env.ZAPAPI_WEBHOOK_SECRET!,
    );
    if (!ok) return res.sendStatus(400);

    const event = JSON.parse(req.body.toString());
    switch (event.type) {
      case 'invoice.paid':
        // fulfill the order — event.data.paymentHash, event.data.preimage
        break;
      case 'zap.received':
        // someone zapped you — event.data.amountSats, event.data.senderPubkey
        break;
    }
    res.json({ received: true });
  },
);

Replay protection: events older than 5 minutes are rejected by default. Tune with the fourth parameter: ZapAPI.webhooks.verify(raw, header, secret, toleranceSeconds).

Other frameworks — just make sure you pass the raw body:

FrameworkRaw body setup
Expressexpress.raw({ type: 'application/json' }) on the route
Fastifyfastify.addContentTypeParser('application/json', { parseAs: 'string' }, …)
Next.js (route handlers)await req.text() — already raw
Honoawait c.req.text() — already raw

Errors

All non-2xx responses throw a typed ZapAPIError with the HTTP status and helpers for common cases:

import { ZapAPI, ZapAPIError } from '@zapapi/sdk';

try {
  await zap.invoices.create(params);
} catch (err) {
  if (err instanceof ZapAPIError) {
    err.status;         // 400, 401, 403, 409, 429, …
    err.code;           // machine-readable code when available
    err.payload;        // raw API error body
    err.isUnauthorized; // 401 — bad/expired key
    err.isForbidden;    // 403 — missing scope
    err.isNotFound;     // 404
    err.isConflict;     // 409 — idempotency conflict
    err.isRateLimited;  // 429 — slow down
  }
}

AI Gateway

500+ models paid per query in sats — catalog, chat (streaming), balance, Lightning topups, usage, and NWC auto-topup:

ai.ts
// Browse the live catalog
const models = await zap.ai.listModels('chat');

// Non-streaming completion
const completion = await zap.ai.completions.create({
  model: 'anthropic/claude-sonnet-5.5',
  messages: [{ role: 'user', content: 'Hello!' }],
});

// Streaming (async generator of text deltas)
for await (const delta of zap.ai.completions.stream({
  model: 'openai/gpt-6-luna',
  messages: [{ role: 'user', content: 'Write a haiku about Lightning' }],
  stream: true,
})) {
  process.stdout.write(delta);
}

// Balance, topups, usage
const balance = await zap.ai.getBalance();     // sats
const topup = await zap.ai.createTopup(5000);  // Lightning invoice
await zap.ai.checkTopup(topup.id);             // credits when paid
const usage = await zap.ai.getUsageSummary();  // spend + top models

// NWC auto-topup (never hit a 402)
await zap.ai.saveAutoTopup({
  nwcConnectionId: 'conn-uuid',
  thresholdSats: 500,
  topupSats: 5000,
  dailyCapSats: 20000,
});

AI-specific error helpers on ZapAPIError: isInsufficientBalance (402), isModelNotFound (404), isModelRetired (404), isRateLimited (429). See AI Gateway docs for the full model catalog, vision, web search and thinking levels.

API coverage

Every user-facing API — payments, wallets, addresses, marketplace, and the AI gateway. (Platform-admin endpoints are intentionally excluded.)

ResourceMethods
zap.invoicescreate, get, list, checkStatus, cancel, getQRCode
zap.refundscreate, listForInvoice, list
zap.customerslist, get, stats, leaderboard
zap.planscreate, list, get, update, delete
zap.subscriptionslist, revenue, cancel
zap.discountscreate, list, update, delete, validate, resolveOffer
zap.giftCardsissue, list, get, disable, check, checkPurchase, redeem
zap.paymentLinkscreate, get, list, updateStatus, delete, getQRCode
zap.webhookEndpointscreate, list, get, updateStatus, delete
zap.projectscreate, list, listShared, get, getStats, update, delete
zap.paymentslist, get, getStats, getDailyStats, exportCsv
zap.apiKeyscreate, list, get, revoke, delete
zap.fxcurrencies, rates, rate, convert
zap.providers (deprecated — use project settlement wallets / zap.nwcConnections)create, list, get, test, disconnect, delete
zap.walletgetInfo, listWallets, createWallet, updateWallet, deleteWallet, setDefaultWallet, getPayments, checkPayment, createInvoice, cancelInvoice, payInvoice, payLnurl, decode, lnurlScan
zap.nwcConnectionslist, create, get, update, refresh, payInvoice, delete
zap.lightningAddresseslistDomains, search, register, list, get, setActive, setWallet, delete
zap.paywallscreate, list, get, setStatus, delete
zap.swapsgetInfo, list, createSubmarine, createReverse, get, refresh
zap.withdrawalscreate, list, get, cancel, getLimits
zap.directorylistApps, getApp, categories, boostProducts, listMyApps, createApp, updateApp, boostApp, checkBoost
zap.marketplacelistProviders, search, applyAsProvider, listMyProviders, getProviderStats, listOrders, getOrder, payOrder, checkOrder, cancelOrder
zap.watchOnlycreateWallet, listWallets, getWallet, deleteWallet, getAddresses, freshAddress, refresh, createPsbt
zap.ailistModels, getModel, getBalance, getRate, createTopup, checkTopup, listTopups, getUsage, getUsageSummary, getAutoTopup, saveAutoTopup, toggleAutoTopup, removeAutoTopup
zap.ai.completionscreate (non-streaming), stream (SSE async generator)
zap.aiToolslist, quote, execute, jobs, waitForCompletion, history
ZapAPI.webhooksverify(rawBody, header, secret, tolerance?)

Anything the SDK doesn't cover yet can be called directly over the REST API with the same API key — see the API Reference.

On this page