Docs
BitChat Checkout SDK
A minimal integration so merchants can accept BitChat as a payment alternative to PayPal and Stripe. The server sets the price and checkout info, the frontend only renders the QR, and the backend confirms payment via API.
Trying Bit-Chat for the first time?
If you want the fastest user path instead of the developer setup, open the dedicated onboarding page with exact first messages for Telegram, WhatsApp, Signal, and Email.
Quickstart (Copy & Paste)
One minimal server + client example. Keep secrets on the server.
// 1) Install
npm i @bit-chat/sdk qrcode
// 2) Server (Node/Express)
import express from "express";
import { BitChat } from "@bit-chat/sdk";
import { randomUUID } from "node:crypto";
const app = express();
app.use(express.json());
const sdk = new BitChat({
apiToken: process.env.BITCHAT_API_TOKEN,
apiSecret: process.env.BITCHAT_API_SECRET,
});
app.post("/checkout", (req, res) => {
const purchaseId = randomUUID();
const checkout = sdk.createCheckout({
amount: 29.9,
fiatCurrency: "EUR",
merchantsContact: "@bit-chat-shop",
platform: "Telegram",
purchaseId,
});
res.json(checkout);
});
app.get("/payments/:purchaseId", async (req, res) => {
const payment = await sdk.pollForPayment({
purchaseId: req.params.purchaseId,
intervalMs: 3000,
timeoutMs: 120000,
});
res.json({ paid: Boolean(payment), payment });
});
app.listen(3000);
// 3) Client (browser)
import QRCode from "qrcode";
async function loadCheckout() {
const checkoutRes = await fetch("/checkout", { method: "POST" });
const checkout = await checkoutRes.json();
const qr = await QRCode.toDataURL(checkout.qrMessage, {
width: 240,
margin: 2,
});
document.getElementById("bitchat-qr").src = qr;
const statusRes = await fetch("/payments/" + checkout.purchaseId);
const status = await statusRes.json();
if (status.paid) console.log("paid", status.payment);
}
loadCheckout();Flow in 20 Seconds
- 1. Server creates `purchaseId` + price + QR message.
- 2. Frontend renders the QR for the user.
- 3. Server polls the payments API for `purchaseId`.
- 4. On match: mark checkout as paid.
QR Message Format
The QR contains exactly this sentence. It is human‑readable and works with BitChat or any standard QR scanner.
send <amount> <fiatCurrency> to <merchantsContact> via <platform> for purchase <purchaseId>Example:
send 29.90 EUR to @bit-chat-shop via Telegram for purchase 4a9c3d47-4dd8-4b15-9a5b-3aaf8e3a57f1Server: Create Checkout
The server defines price, contact, platform and `purchaseId` and returns the QR message to the frontend. Secrets stay server‑side.
import { BitChat } from "@bit-chat/sdk";
import { randomUUID } from "node:crypto";
const sdk = new BitChat({
apiToken: process.env.BITCHAT_API_TOKEN!,
apiSecret: process.env.BITCHAT_API_SECRET!,
});
app.post("/checkout", async (req, res) => {
const purchaseId = randomUUID();
const checkout = sdk.createCheckout({
amount: 29.9,
fiatCurrency: "EUR",
merchantsContact: "@bit-chat-shop",
platform: "Telegram",
purchaseId,
});
res.json(checkout);
});Client: Render QR
The frontend only renders the QR. No secrets in the browser.
import QRCode from "qrcode";
async function renderCheckout() {
const res = await fetch("/checkout", { method: "POST" });
const checkout = await res.json();
const dataUrl = await QRCode.toDataURL(checkout.qrMessage, {
width: 220,
margin: 2,
});
const img = document.getElementById("bitchat-qr");
img.src = dataUrl;
}
renderCheckout();Verify Payment
The merchant server checks payment via the payments API. A match on `purchaseId` means the payment arrived.
API_TOKEN="f242ad65-0711-4a73-81d3-a70373efa78c" API_SECRET="Bhv8JrqKLbBrqthM4tZt7AW26s1LSWB3" NONCE=$(date +%s000)
curl -X GET "https://www.livingroomofsatoshi.com/api/v1/wallet/payments" -H "api-token: $API_TOKEN" -H "api-nonce: $NONCE" -H "api-signature: $(echo -n "/api/v1/wallet/payments$NONCE" | openssl dgst -sha256 -hmac "$API_SECRET" -binary | base64)" -H "Content-Type: application/json"Sample response (short). Important: `description` includes the `purchaseId`.
{
"address": "lnbc200u1p53etx0pp...",
"amount": 0.00020000,
"currency": "LIGHTNING",
"description": "purchase: 4a9c3d47-4dd8-4b15-9a5b-3aaf8e3a57f1",
"status": "PAID",
"time": "2025-11-18T17:28:47.266Z",
"transactionId": "f3c30ea8aaf3..."
}TypeScript: Polling Helper
Minimal helper that checks every 3 seconds whether the `purchaseId` appears. Stops automatically after timeout.
import { BitChat } from "@bit-chat/sdk";
const sdk = new BitChat({
apiToken: process.env.BITCHAT_API_TOKEN!,
apiSecret: process.env.BITCHAT_API_SECRET!,
});
const payment = await sdk.pollForPayment({
purchaseId,
intervalMs: 3000,
timeoutMs: 120000,
});
if (payment) {
// mark order as paid
}Agent payment events
If you're evaluating Bit-Chat for autonomous agents or operator-assisted flows, use the dedicated schema page for minimalpayment_required andpayment_receipt examples, including the manual top-up human approval fallback.
Production Checklist
- Never expose API token/secret in the browser.
- Always generate `purchaseId` on the server.
- Payment `description` must contain the `purchaseId`.
- Only server code should mark orders as `PAID`.
- Keep the QR message format exact (no deviations).
- Run checkout and payments endpoints over HTTPS.